]> git.proxmox.com Git - mirror_smartmontools-debian.git/commitdiff
Imported Upstream version 6.1+svn3812
authorGiuseppe Iuculano <iuculano@debian.org>
Sun, 2 Jun 2013 06:38:57 +0000 (08:38 +0200)
committerGiuseppe Iuculano <iuculano@debian.org>
Sun, 2 Jun 2013 06:38:57 +0000 (08:38 +0200)
105 files changed:
AUTHORS
CHANGELOG [deleted file]
ChangeLog [new file with mode: 0644]
ChangeLog-5.0-6.0 [new file with mode: 0644]
INSTALL
Makefile.am
NEWS
README
atacmdnames.cpp
atacmdnames.h
atacmds.cpp
atacmds.h
ataidentify.cpp [new file with mode: 0644]
ataidentify.h [new file with mode: 0644]
ataprint.cpp
ataprint.h
autogen.sh
cciss.cpp
configure.ac [new file with mode: 0644]
configure.in [deleted file]
csmisas.h
dev_areca.cpp [new file with mode: 0644]
dev_areca.h [new file with mode: 0644]
dev_interface.cpp
dev_interface.h
do_release
drivedb.h
examplescripts/README
getopt/getopt.c
getopt/getopt.h
int64.h
knowndrives.cpp
knowndrives.h
megaraid.h
os_darwin.cpp
os_darwin.h
os_darwin/SMART.in
os_freebsd.cpp
os_freebsd.h
os_generic.cpp
os_generic.h
os_linux.cpp
os_linux.h
os_netbsd.cpp
os_netbsd.h
os_openbsd.cpp
os_openbsd.h
os_os2.cpp
os_os2.h
os_qnxnto.cpp
os_qnxnto.h
os_solaris.cpp
os_solaris.h
os_solaris_ata.s
os_win32.cpp
os_win32/daemon_win32.cpp
os_win32/daemon_win32.h
os_win32/hostname_win32.cpp [deleted file]
os_win32/hostname_win32.h [deleted file]
os_win32/installer.nsi
os_win32/runcmd_vc10.vcxproj [deleted file]
os_win32/smartctl_res.rc.in [new file with mode: 0644]
os_win32/smartctl_vc10.vcxproj [deleted file]
os_win32/smartctl_vc10.vcxproj.filters [deleted file]
os_win32/smartd_res.rc.in [new file with mode: 0644]
os_win32/smartd_vc10.vcxproj [deleted file]
os_win32/smartd_vc10.vcxproj.filters [deleted file]
os_win32/smartd_warning.cmd [new file with mode: 0644]
os_win32/smartmontools_vc10.sln [deleted file]
os_win32/syslog.h
os_win32/syslog_win32.cpp
os_win32/syslogevt.c [deleted file]
os_win32/syslogevt.mc
os_win32/syslogevt_vc10.vcxproj [deleted file]
os_win32/vc10/runcmd.vcxproj [new file with mode: 0644]
os_win32/vc10/smartctl.vcxproj [new file with mode: 0644]
os_win32/vc10/smartctl.vcxproj.filters [new file with mode: 0644]
os_win32/vc10/smartd.vcxproj [new file with mode: 0644]
os_win32/vc10/smartd.vcxproj.filters [new file with mode: 0644]
os_win32/vc10/smartmontools.sln [new file with mode: 0644]
os_win32/vc10/wtssendmsg.vcxproj [new file with mode: 0644]
os_win32/wmiquery.cpp
os_win32/wtssendmsg.c [new file with mode: 0644]
regex/regcomp.c
regex/regex.c
regex/regex.h
regex/regex_internal.c
regex/regex_internal.h
regex/regexec.c
scsiata.cpp
scsicmds.cpp
scsicmds.h
scsiprint.cpp
scsiprint.h
smartctl.8.in
smartctl.cpp
smartctl.h
smartd.8.in
smartd.conf
smartd.conf.5.in
smartd.cpp
smartd.initd.in
smartd_warning.sh.in [new file with mode: 0644]
utility.cpp
utility.h

diff --git a/AUTHORS b/AUTHORS
index c9e56a01a7203106de7625c5125ebd6abd63d3b1..74af81593cc9e4ac282f6455ab5e9327c4dfdc05 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,4 +1,4 @@
-$Id: AUTHORS 3096 2010-04-30 14:32:49Z chrfranke $
+$Id: AUTHORS 3751 2013-01-18 21:19:43Z chrfranke $
 
 This code was originally developed as a Senior Thesis by Michael
 Cornwell at the Concurrent Systems Laboratory (now part of the Storage
@@ -10,29 +10,30 @@ ucsc-smartsuite and smartsuite packages, and is derived from that code.
 
 Maintainers / Developers:
 
-Bruce Allen            <smartmontools-support@lists.sourceforge.net>
-Erik Inge Bolsø                <knan@mo.himolde.no>
-Stanislav Brabec       <sbrabec@suse.cz>
-Peter Cassidy          <pcassidy@mac.com>
-Casper Dik             <casper@holland.sun.com>
-Christian Franke       <franke@computer.org>
-Guilhem Frézou         <guilhem.frezou@catii.fr>
-Douglas Gilbert                <dgilbert@interlog.com>
-Guido Guenther         <agx@sigxcpu.org>
-Geoff Keating          <geoffk@geoffk.org>
-Dr. David Kirkby       <drkirkby@ntlworld.com>
-Kai Mäkisara           <kai.makisara@kolumbus.fi>
-Eduard Martinescu      <martines@rochester.rr.com>
-Frédéric L. W. Meunier <http://www.pervalidus.net/contact.html>
-Keiji Sawada           <card_captor@users.sourceforge.net>
-Manfred Schwarb                <manfred99@gmx.ch>
-David Snyder            <dasnyderx@yahoo.com>
-Sergey Svishchev       <svs@ropnet.ru>
-Phil Williams          <phil@subbacultcha.demon.co.uk>
-Richard Zybert         <richard.zybert@zybert.co.uk>
-Yuri Dario             <mc6530@mclink.it>
-Shengfeng Zhou         <linux@highpoint-tech.com>
-Praveen Chidambaram    <bunchofmails@gmail.com>
+Bruce Allen             <smartmontools-support@lists.sourceforge.net>
+Erik Inge Bolsø         <knan@mo.himolde.no>
+Stanislav Brabec        <sbrabec@suse.cz>
+Peter Cassidy           <pcassidy@mac.com>
+Praveen Chidambaram     <bunchofmails@gmail.com>
+Yuri Dario              <mc6530@mclink.it>
+Casper Dik              <casper@holland.sun.com>
+Christian Franke        <franke@computer.org>
+Guilhem Frézou          <guilhem.frezou@catii.fr>
+Douglas Gilbert         <dgilbert@interlog.com>
+Guido Guenther          <agx@sigxcpu.org>
+Jordan Hargrave         <jordan_hargrave@dell.com>
 Joerg Hering            <hering.ruegen@gmx.de>
-Tomas Smetana          <tsmetana@redhat.com>
-Jordan Hargrave                <jordan_hargrave@dell.com>
+Geoff Keating           <geoffk@geoffk.org>
+Dr. David Kirkby        <drkirkby@ntlworld.com>
+Kai Mäkisara            <kai.makisara@kolumbus.fi>
+Eduard Martinescu       <martines@rochester.rr.com>
+Frédéric L. W. Meunier  <http://www.pervalidus.net/contact.html>
+Alex Samorukov          <samm@os2.kiev.ua>
+Keiji Sawada            <card_captor@users.sourceforge.net>
+Manfred Schwarb         <manfred99@gmx.ch>
+Tomas Smetana           <tsmetana@redhat.com>
+David Snyder            <dasnyderx@yahoo.com>
+Sergey Svishchev        <svs@ropnet.ru>
+Phil Williams           <phil@subbacultcha.demon.co.uk>
+Shengfeng Zhou          <linux@highpoint-tech.com>
+Richard Zybert          <richard.zybert@zybert.co.uk>
diff --git a/CHANGELOG b/CHANGELOG
deleted file mode 100644 (file)
index cac139e..0000000
--- a/CHANGELOG
+++ /dev/null
@@ -1,5020 +0,0 @@
-CHANGELOG for smartmontools
-
-$Id: CHANGELOG 3561 2012-06-05 19:49:31Z chrfranke $
-
-The most recent version of this file is:
-http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/CHANGELOG?view=markup
-
-Maintainers / Developers Key (alphabetic order):
-[AS]  Alex Samorukov
-[BA]  Bruce Allen
-[OB]  Oliver Bock
-[EB]  Erik Inge Bolsø
-[SB]  Stanislav Brabec
-[PC]  Peter Cassidy
-[MC]  Matthieu Castet
-[YD]  Yuri Dario
-[CD]  Casper Dik
-[CF]  Christian Franke
-[GF]  Guilhem Frézou
-[DG]  Douglas Gilbert
-[GG]  Guido Guenther
-[JPH] Jordan Powell Hargrave
-[JH]  Joerg Hering
-[GK]  Geoff Keating
-[DK]  Dr. David Kirkby
-[DL]  Dan Lukes
-[KM]  Kai Mäkisara
-[EM]  Eduard Martinescu
-[FM]  Frédéric L. W. Meunier
-[GP]  Gabriele Pohl
-[AR]  Adam Radford
-[KS]  Keiji Sawada
-[MS]  Manfred Schwarb
-[TS]  Tomas Smetana
-[DS]  David Snyder
-[SS]  Sergey Svishchev
-[PW]  Phil Williams
-[LW]  Leon Woestenberg
-[SZ]  Shengfeng Zhou
-[RZ]  Richard Zybert
-
-<DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
-
-  [CF] man pages: Minor updates and syntax fixes.
-
-  [CF] smartd.service.in: Add ExecReload and StandardOutput.
-       Make EnvironmentFile optional (ticket #194).
-
-  [CF] drivedb.h USB updates:
-       - HP Desktop HD BD07 (0x03f0:0xbd07)
-       - Iomega Prestige Desktop USB 3.0 (0x059b:0x0070)
-       - Prolific PL2507 (0x067b:0x2507): unsupported -> -d usbjmicron,0
-       - WD My Passport USB 3.0 (0x1058:0x0748)
-       - WD My Book Essential USB 3.0 (0x1058:0x1140)
-       - Sharkoon SATA QuickDeck Pro (0x1f75:0x0888): unsupported
-       - Hitachi Touro Desk (0x4971:0x1015)
-
-  [CF] Move function str_starts_with() to utility.h.
-
-  [CF] smartctl.8.in, smartd.conf.5.in: Note required Areca SAS firmware version.
-
-  [CF] INSTALL, smartctl.8.in: Announce OS X SAT SMART Driver (ticket #25).
-
-  [CF] Add smart_device::is_syscall_unsup().
-
-  [CF] os_win32.cpp: Avoid ENOTSUP which is not provided by some versions
-       of MinGW.
-
-  [DG] os_linux.cpp: Fix scsi pass-through SG_INFO_CHECK mask logic
-       (ticket #225)
-
-  [CF] drivedb.h updates:
-       - Sandforce Driven SSDs: OCZ-NOCTI
-       - Intel 330 Series SSDs (ticket #227)
-
-  [CF] smartctl.8.in, smartd.conf.5.in: Document '-d areca N[/E]' support
-       for Windows.
-
-  [CF] os_win32.cpp: Add help text and error messages for '-d areca,N[/E]'.
-
-  [CF] os_win32.cpp win_areca_device: Disable full 48-bit ATA support.
-       Add missing set_err() calls.  Remove unused function and parameter.
-
-  [CF] os_win32.cpp: Add support for SATA disks behind Areca SATA and SAS
-       controllers.  Requires '-d areca,N[/E]' as type and '[/dev/]arcmsrX'
-       as device name.
-
-       Patch was provided by Hank Wu from Areca.
-
-  [CF] Windows installer: Make name of checksum file 32-/64-bit specific.
-
-  [CF] Windows installer: Add support for combined 32-/64-bit installer.
-
-  [CF] Windows installer: Drop support for UBCD4Win.
-
-  [AS] os_freebsd.cpp: sync Areca code with linux version by adding optional 
-       enclosure number.
-
-  [CF] smartctl.8.in, smartd.conf.5.in: Add brief doc for '-d areca N/E'.
-
-  [CF] os_linux.cpp: Add optional enclosure number to '-d areca' option.
-       This adds support for SATA disks behind Areca SAS controllers.
-
-       Patch was provided by Hank Wu from Areca.
-
-  [CF] smartctl: Add log addresses and statistics value from ACS-3 revision 2.
-
-  [CF] drivedb.h updates:
-       - Crucial/Micron RealSSD C300/C400/m4: m4 512GB
-       - Indilinx Everest/Martini based SSDs: OCZ-PETROL
-       - SAMSUNG SpinPoint F4 EG (AFT): Fix link
-       - Seagate Momentus 4200.2: ST960812A
-       - Seagate Momentus 5400.2: ST960821A (from 4200.2)
-       - Seagate Barracuda 7200.12: ST3500413AS
-       - Western Digital RE3 Serial ATA: WD7502ABYS
-       - Western Digital AV-GP: WD....AV[CD]S, split entry
-       - Western Digital AV-GP (Adv. Format): WD10EU[CR]X
-
-  [CF] autogen.sh: Set svn:eol-style=LF to be compatible with Cygwin bash.
-
-  [CF] autogen.sh: automake 1.11.3 is OK.
-
-  [CF] drivedb.h updates:
-       - Sandforce Driven SSDs: Smart Storage Systems XceedSTOR,
-         XceedIOPS2, Xcel-200
-       - Smart Storage Systems XceedSecure2 SSDs
-       - Smart Storage Systems XceedUltraX/Adtron A25FBX SSDs
-       - Smart Storage Systems Adtron A25FB 2xN SSDs
-       - Smart Storage Systems Adtron A25FB 3xN SSDs
-       Original patch was provided by Rusty Carruth
-
-  [CF] drivedb.h updates:
-       - Remove outdated IBM links
-       - Update all links to Seagate Knowledge Base
-       - Hitachi Deskstar 7K1000.D
-
-  [CF] drivedb.h USB update:
-       - Seagate Expansion External (0x0bc2:0x3332) (ticket #223)
-
-  [CF] drivedb.h USB updates:
-       - Samsung Story Station (0x04e8:0x5f05)
-       - Toshiba STOR.E (0x0930:0x0b1b)
-
-  [CF] smartctl: Add options '-f hex' and '-f hex,[id|val]' to print
-       attribute IDs and/or values as hex.
-
-  [CF] smartd.8.in: Fix signal name (Debian bug 661801).
-
-  [CF] Add 'raw56', 'hex56', 'raw24(raw8)' attribute print formats.
-       Change default for Power_On_Hours to 'raw24(raw8)'.
-       This provides more reasonable output for SandForce based devices
-       missing in drivedb.h.
-
-  [CF] configure.in, Makefile.am: Support new SVN 1.7 working copy format.
-
-  [CF] drivedb.h update:
-       - Intel 520 Series SSDs: Add units to attributes 241, 242, 249.
-
-  [AS] drivedb.h: fixed identifier for Seagate SV35 series.
-
-  [CF] Print command duration in ATA debug output.
-       Add smart_interface::get_timer_usec().
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: G.SKILL Phoenix Pro
-       - Intel 520 Series SSDs
-       - SAMSUNG SpinPoint F4 EG: Update firmware download link
-
-  [CF] drivedb.h updates:
-       - Add comment with default settings.
-       - Samsung based SSDs: Fix attribute 240
-
-  [CF] Windows: Add Win8 to get_os_version_str().
-
-  [CF] Windows: Remove MSVC specific pragma, disable warning in project file.
-
-  [CF] Add '-d sat,auto[,N]' option for controller independent SAT detection.
-
-  [CF] dev_interface.h: Replace this_is_ata/scsi(*) by hide_ata/scsi(bool).
-
-  [CF] smartctl: Allow '-d test' in conjunction with other '-d TYPE' options.
-
-  [AS] FreeBSD: sync init script with one from ports repository.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: ADATA S510
-       - JMicron based SSDs: Toshiba THNSNC128GMLJ
-       - Samsung based SSDs: 830 Series
-       - Hitachi Deskstar E7K1000
-       - Hitachi Ultrastar A7K1000: Fix name, allow trailing characters
-       - Hitachi Ultrastar A7K2000: Remove duplicate entry
-       - Toshiba 2.5" HDD MK..55GSX
-       - Western Digital AV-GP: WD..EURS variants
-
-  [CF] drivedb.h USB updates:
-       - Buffalo MiniStation HD-PCTU2 (0x0411:0x01d9) (ticket #211)
-       - Philips SDE3273VC/97 (0x0471:0x2021) (ticket #212)
-       - Samsung M2 Portable 3.0 (0x04e8:0x60c5)
-       - Iomega GDHDU2 (0x059b:0x0475)
-       - LaCie minimus USB 3.0 (0x059f:0x104a)
-       - Seagate FreeAgent GoFlex Desk USB 3.0 (0x0bc2:0x50a5)
-       - Maxtor BlackArmor Portable (0x0d49:0x7550)
-       - WD My Passport Essential SE USB 3.0 (0x1058:0x0742)
-       - Initio (0x13fd:0x1e40)
-       - Verbatim External Hard Drive 2TB (0x18a5:0x022a)
-       - Hitachi Touro Desk (0x4971:0x1011)
-
-  [CF] smartd: Add smartd.conf directive '-e' to set ATA settings on
-       startup: aam, apm, lookahead, security-freeze, standby, wcache.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Corsair Force GT
-       - Indilinx Barefoot based SSDs: Corsair Nova
-       - SAMSUNG SpinPoint M8
-       - Seagate SV35.5
-
-  [CF] smartctl: Change short option for '--set' from '-e' to '-s'.
-       Keep backward compatibility with short option for '--smart'.
-
-  [CF] smartctl: Print description of APM level.
-
-  [CF] smartctl: Add option '-e standby,[N|off|now]' to set standby timer
-       or standby mode.
-
-  [CF] smartctl: Add options '-g security' and '-e security-freeze' to
-       get/freeze ATA security settings.
-
-  [CF] smartctl: Add options '-g/e lookahead' and '-g/e wcache' to get/set
-       read look-ahead and write cache feature.
-
-  [CF] smartctl: Add options '-g aam' and '-e aam,[N|off]' to get/set
-       ATA Automatic Acoustic Management feature.  Add '-g all'.
-
-  [CF] os_win32.cpp: Prevent warnings from gcc option -Wformat-security.
-
-  [CF] smartctl: Add options '-g, --get apm' and '-e, --set apm,[N|off]'
-       to get/set ATA Advanced Power Management feature.
-       Original patch was provided by Marcus Sorensen.
-
-  [AS] os_freebsd.cpp - do not skip ATA devices from cam list. Starting from
-       FreeBSD 9.0 such devices are exported ONLY as camdev`s, so DEVICESCAN
-       was broken. Its possible to get duplicates now on some old systems.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add OCZ Solid 3, OCZ Deneva 2 C/R
-       - Seagate Momentus 5400.7
-
-  [CF] Happy New Year! Update copyright year in version info.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add Patriot Pyro
-       - Intel 320 Series SSDs: Fix 40GB
-       - Seagate Barracuda XT: Add 4TB
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add Corsair Force 3
-       - Hitachi Travelstar 5K320: Add SA00 and SA02 models
-       - Western Digital Caviar SE SATA: Add 300GB
-
-  [CF] Cygwin smartd: Remove SIGQUIT workaround, no longer needed with
-       current Cygwin tty emulation.
-
-  [CF] smartd: Disable auto standby also after start of scheduled
-       self-test.
-
-  [CF] smartd: Add smartd.conf DEFAULT directive.  Allows to set default
-       settings for multiple devices.
-
-  [CF] smartd: Re-enable auto standby if smartd.conf is re-read.
-
-  [AS] drivedb.h update: Seagate Barracuda (SATA 3Gb/s, 4K Sectors)
-
-  [AS] drivedb.h update: Seagate Constellation ES.2 (SATA 6Gb/s)
-
-  [CF] drivedb.h updates:
-       - Sandforce Driven SSDs: Add OCZ Vertex 3 Max IOPS (ticket #209)
-       - Seagate ST1.2 CompactFlash (found in ticket #125)
-
-  [CF] Fix GPL version reported by '-V' option.
-       Now reports GPLv2+ which is consistent with file headers.
-       Patch was provided by Stanislav Brabec.
-
-  [CF] drivedb.h updates:
-       - Sandforce Driven SSDs: Add OCZ Deneva 2 Async variant, 60GB, 480GB
-       - Indilinx Martini based SSDs: OCZ VERTEX-PLUS only
-
-  [CF] smartd: Add '-l offlinests,ns' and '-l selfteststs,ns' directives.
-       dev_interface: Add smart_interface::disable_system_auto_standby().
-       os_win32.cpp: Implement disable_system_auto_standby().
-
-  [CF] dev_interface: Let smart_interface::set_err() return false.
-
-  [CF] drivedb.h updates:
-       - SAMSUNG SpinPoint M8U (USB)
-       - Toshiba 3.5" HDD MKx002TSKB: Fix typo
-
-  [CF] smartctl: Print average temperature from SCT status only if
-       value is reasonable.  Field is not part of ATA-8.
-
-  [CF] smartd: Report ignored '-r' and '-R' directives.
-
-  [CF] smartctl: Use 16-bit value (ATA-8) for extended self-test polling
-       time if 8-bit value is 0xff (ticket #207).
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add OCZ-REVODRIVE3, OCZ Z-DRIVE R4
-       - Hitachi Travelstar Z7K320
-       - Toshiba 2.5" HDD MK..56GSY
-       - Toshiba 2.5" HDD MKx002TSKB
-       - Seagate U9
-       - Seagate U*: sort entries, unify names, remove duplicate
-       - Seagate Constellation ES (SATA 6Gb/s)
-       - Seagate DB35
-       - Seagate DB35.2
-       - Western Digital Scorpio Black: Add 500GB
-       - Western Digital Scorpio Black (Adv. Format)
-
-  [CF] drivedb.h USB updates:
-       - Samsung S2 (0x04e8:0x1f05)
-       - Toshiba Stor.E (0x0939:0x0b16) (ticket #206)
-       - Seagate FreeAgent (0x0bc2:0x5040)
-       - Initio/Thermaltake BlacX (0x13fd:0x0840)
-
-  [DG] [SCSI] smartd: skip non-storage devices (e.g. SES devices)
-
-  [AS] drivedb.h updates: Added Seagate SV35 Series
-
-  [CF] smartctl: Don't start ATA self-test if another test is already
-       running (ticket #40).  Add option '-t force' to allow override.
-
-  [CF] atacmds.h: Remove bogus ataSmart*Test*() prototypes.
-
-  [CF] Define __attribute_format_printf() for functions with printf() style
-       arguments.  Allow MinGW build with __USE_MINGW_ANSI_STDIO enabled.
-
-  [CF] Makefile.am: Replace sed compound command in MAN_FILTER.
-       This fixes build on Solaris (ticket #203).
-
-  [AS] os_freebsd.cpp: Dereference symlinks before guess of device type
-       (problem reported by email).
-
-  [CF] drivedb.h USB updates:
-       - LG Mini HXD5 (0x043e:0x70f1)
-       - Freecom/Intel (0x07ab:0xfc8e)
-       - Dura Micro (0x0c0b:0xb001) (Debian bug 643928)
-       - Initio 6Y120L0 (0x13fd:0x1150): unsupported
-
-  [CF] drivedb.h USB update:
-       - Seagate FreeAgent GoFlex Desk USB 3.0 (0x0bc2:0x50a1):
-         Revert to -d sat,12 (ticket #151).
-
-  [AS] os_freebsd.cpp - fixed crash on FreeBSD9-RC1 caused by r225950
-
-  [AS] smartctl.8 - added information about -d areca on FreeBSD
-
-  [AS] os_freebsd.cpp: backport quirks for the LSI controllers with SATA
-       disks to the FreeBSD. Tested with DELL Perc/6i controller.
-
-  [AS] os_freebsd.cpp: disable SAT autodetection on megaraid controllers
-
-  [AS] drivedb.h update: 
-       - Hitachi Ultrastar 7K2000
-
-  [CF] drivedb.h update:
-       - Seagate Momentus XT: Add bug warning for firmware SD24 and SD25
-
-  [CF] Don't include pkg-config macros in aclocal.m4, copy to m4/pkg.m4
-       instead.  Allow builds from SVN without pkg-config installed
-       but prevent 'make dist' when pkg-config support is missing.
-
-  [CF] Move automake --foreign option from autogen.sh to configure.in.
-       This fixes autoreconf support.
-
-  [CF] Replace COPYING file with current (2010-03-24) version from
-       http://www.gnu.org/licenses/gpl-2.0.txt
-
-smartmontools 5.42 2011-10-20
-
-  [CF] Windows installer: Add install dir to PATH in CMD shortcut.
-
-  [CF] drivedb.h updates:
-       - SAMSUNG SpinPoint MP5
-       - Seagate Barracuda 7200.11: Change warning text, Seagate
-         apparently released fixed firmware without changing version
-         number (Debian bug 632758)
-       - Western Digital RE4 GP
-       - Western Digital VelociRaptor: Add 150GB, 300GB LHX variants
-       - Western Digital Scorpio Blue Serial ATA (Adv. Format):
-         Add 1TB JPVT variant
-
-  [CF] drivedb.h USB update:
-       - WD Elements SE USB 3.0 (0x1058:0x1042)
-
-  [CF] Windows installer: Rework to support UAC.
-       Replace *-run.bat files by runcmd?.exe wrappers.
-       Run drive menu entries elevated (ticket #173).
-
-  [CF] smartctl.8.in: Add example script which prints all status bits
-       (ticket #191).
-
-  [CF] Cygwin smartd: Remove '--service' option, update man page.
-
-  [CF] smartd: Require absolute path name also for '-p' option.
-       Allow relative path names for '-A', '-s', '-p' in Windows
-       version only.
-
-  [CF] smartd: Log model family from drive database if known.
-
-  [CF] drivedb.h update:
-       - SMART Xcel-10 2.5 SATA SSD: Shorten names,
-         document supported default attributes.
-
-  [CF] smartctl -P showall: Report error if attribute name is too long.
-
-  [AS] freebsd: use system ciss header if available, it is added
-       to the base system by recent commit.
-
-  [CF] smartd.conf.5.in: Update Windows 'msgbox' info.
-       Add missing IF/ENDIF for Solaris and Windows.
-
-  [CF] man pages: Remove reference to T13 web site.  It does no
-       longer provide links to the ATA documents.
-
-  [CF] smartctl: Replace '-t scttempint,N[,p]' option
-       by '-l scttempint,N[,p]'.
-
-  [CF] drivedb.h USB update:
-       - Oxford (0x0928:0x0000): unsupported, see
-         https://bugs.freedesktop.org/show_bug.cgi?id=24951
-
-  [CF] Minor cleanup to prevent warnings from new gcc 4.6 options
-       -Wunused-but-set-parameter/variable.
-
-  [CF] Windows smartd: Fix format string for 64-bit version.
-
-  [CF] Remove EXPERIMENTAL notes for features already present in 5.40.
-
-  [CF] smartctl: Add new log addresses from ACS-3 revision 1.
-
-  [CF] smartctl: Print ATA ACS-x versions properly (ticket #183).
-
-  [CF] smartctl: Add option '-l devstat[,PAGE]',
-       print ATA Device Statistics log pages (ticket #106).
-
-       Thanks to David Boreham for providing access to a machine for testing.
-
-  [AS] man pages: trivial man page syntax fixes (ticket #199)
-
-  [CF] drivedb.h update:
-       - SMART Xcel-10 2.5 SATA SSD: Fix syntax error (ticket #200)
-
-  [AS] drivedb.h update:
-       - SMART Xcel-10 2.5 SATA SSD
-
-  [DG] [SCSI] document 'ssd' list option in man page and smartctl usage.
-
-  [CF] Windows: Fix device type detection for Intel ICHxR RAID Volumes.
-
-  [CF] smartd: Resend warning emails if problem reappears (ticket #167).
-
-  [CF] smartd: Add separate directives '-l offlinests' and '-l selfteststs'
-       to enable tracking of status changes.  Disable '-l offlinests' by
-       default to avoid misleading messages (see Debian bug 636078).
-
-  [CF] drivedb.h updates:
-       - Crucial/Micron RealSSD C300/C400: Add m4 series (ticket #192)
-       - SandForce Driven SSDs: Add OCZ-AGILITY3
-       - Indilinx Barefoot based SSDs: Add RENICE Z2
-       - Intel 710 Series SSDs
-
-  [CF] Windows smartd: Fix quoting of service command line.
-
-  [CF] Cygwin smartd: Remove FreeConsole() after fork().
-       No longer needed for recent versions of Cygwin DLL.
-
-  [CF] smartd: Add some sleep() time after machine standby mode.
-       Some drivers (Intel ICHxR Windows driver) report failures if
-       pass-through is accessed immediately after wake up.
-
-  [AS] -d hpt on linux/freebsd - increased max channel number to 16,
-       fixed documentation.
-       (see http://permalink.gmane.org/gmane.linux.utilities.smartmontools/7846)
-
-  [AS] os_linux.cpp - disabling SMART WRITE LOG SECTOR command on 
-       megaraid interface for SATA disks.
-
-  [AS] os_freebsd.cpp: -l scterc was broken on FreeBSD, fixed for atacam and
-       ata drivers (bug #198).
-
-  [CF] drivedb.h updates:
-       - Crucial/Micron RealSSD C300/C400: Add C400
-       - SandForce Driven SSDs: Add Kingston HyperX,
-         OCZ-REVODRIVE, OCZ Deneva 2
-       - Intel X18-M/X25-M/X25-V G2 SSDs: Add 120GB
-       - Hitachi Travelstar 7K200: Match capital letters also
-       - Hitachi Ultrastar 7K3000
-       - Seagate Barracuda Green: Add ST2000DL001-* (ticket #195)
-       - WD My Passport Essential SE: Add WD10TMVW-*
-
-  [CF] drivedb.h USB updates:
-       - Seagate FreeAgent GoFlex USB 3.0 (0x0bc2:0x5071) (ticket #195)
-       - Seagate FreeAgent GoFlex Desk USB 3.0 (0x0bc2:0x50a1):
-         Enable -d sat,16 (ticket #151).
-       - Oyen Digital MiniPro USB 3.0 (0x0dc4:0x020a) (ticket #193)
-       - WD My Passport Essential SE USB 3.0 (0x1058:0x0740)
-
-  [CF] Windows: Add MSVC10 support, remove MSVC8 project files.
-
-  [DG] [SCSI] smartctl output Solid State Media (SSD) percentage used
-       endurance indicator. Add '-l ssd', useful for SATA SSDs?
-
-  [CF] atacmds.cpp: Rework search for temperature min/max values
-       in attributes 190/194.  This fixes temperature tracking
-       for recent WDC drives.
-
-  [CF] drivedb.h USB updates:
-       - LaCie rikiki USB 3.0 (0x059f:0x1057)
-       - Freecom Mobile Drive XXS (0x07ab:0xfc88)
-       - WD Elements SE (0x1058:0x1023)
-
-  [CF] drivedb.h updates:
-       - Indilinx Barefoot based SSDs: Add G.Skill Falcon
-       - JMicron based SSDs (JMF61x): Add Kingston SSDNow V100 Series
-       - Transcend CompactFlash Cards: Add 8, 16GB
-       - Toshiba 1.8" HDD MD..29GSG
-       - SAMSUNG SpinPoint M7U
-       - Western Digital Caviar Green (Adv. Format): Add SATA 6Gb/s variants
-       - Western Digital My Passport USB: Shorten names
-
-  [DG] [SCSI] smartd initial log entry for each drive now shows INQUIRY
-       strings and optionally the LU (logical unit) id and capacity
-
-  [AS] os_freebsd.cpp: fixed return type in autodetect_smart_device.
-
-  [CF] drivedb.h USB updates:
-       - WD My Book Essential (0x1058:0x0910, Debian bug 633724)
-       - Atech (0x11b0:0x6298)
-
-  [CF] drivedb.h update:
-       - Seagate Barracuda ES.2: Add Dell firmware versions (ticket #189)
-
-  [CF] drivedb.h updates:
-       - Seagate Maxtor DiamondMax 21: Add STM380215AS
-       - Seagate Barracuda 7200.12: Add ST3250312AS, ST31000524AS
-       - Toshiba 2.5" HDD MK..50GACY
-       - Toshiba 2.5" HDD MK..76GSX
-
-  [AS] smartd.8 - removed configuration file information from this manual,
-       added reference to smartd.conf.5.
-
-  [AS] smartd.conf.5 - added more platform-specific sections, corrected "areca"
-       device information, corrected sample configuration.
-
-  [AS] os_freebsd.cpp: detecting access to /dev/mfidX devices to show help (#97)
-
-  [CF] Update configure options in INSTALL file, remove outdated info.
-
-  [CF] int64.h: Remove outdated uint64_to_double() workaround for MSVC6.
-
-  [CF] os_win32/update-smart-drivedb.nsi: Add support for /S(ilent) option.
-
-  [CF] configure.in: Don't search for initddir and systemdsystemunitdir
-       when cross-compiling.
-
-  [CF] Makefile.am: Use same syntax also for ENABLE_* man page sections.
-
-  [CF] Add experimental support for platform-specific man pages.
-
-  [CF] Windows: Move '-I os_win32' from configure.in to Makefile.am.
-
-  [CF] configure.in: Fix check for __attribute__((packed)).
-
-  [CF] drivedb.h USB update:
-       - Verbatim Portable Hard Drive (0x18a5:0x0214)
-
-  [CF] drivedb.h update:
-       - SandForce Driven SSDs: Add OWC Mercury Extreme Pro RE (ticket #168)
-
-  [CF] os_linux.cpp: Let MegaRAID autodetect_open() fail for SATA devices.
-       MegaRAID SAT layer has serious bugs as reported by AS.
-
-  [AS] os_freebsd.cpp: Implement 48bit support for the new "atacam" 
-       interface. Tested on FreeBSD 8.2 and works fine. 
-
-  [CF] os_win32.cpp: Fix USB ID detection if two devices with the same
-       name exist (ticket #178).
-
-  [AS] os_freebsd.cpp: including ciss headers to the base, we can not rely 
-       on the header sources in the build time. Also this file was changed 
-       last time > 2 yrs. ago and it is unlikely that it will be changed in 
-       the feature. This will fix FreeBSD PR 150235.
-
-  [AS] drivedb.h update: Added Samsung Story Station 3.0 USB.
-
-  [AS] os_linux.cpp: Areca code converted to the new interface.
-       Patch is based on os_freebsd.cpp patch and is not tested yet.
-
-  [AS] os_freebsd.cpp: Areca code converted to the new interface.
-
-  [AS] os_freebsd.cpp: Added support for the Areca RAID controllers. 
-       Support is basesd on Linux code, but using IOCTL on areca control
-       device instead of SCSI commands to talk with the drives. Hardware
-       access was provided by Andrej Binder.
-
-  [CF] Don't use isprint() for ASCII character check as it may be affected
-       by setlocale().
-
-  [AS] os_freebsd.cpp: Remove all referenced to the FreeBSD 5.0.
-       It is unsupported for a very long time and probably will not compile
-       and work anyway. Also this will fix bug #154.
-
-smartmontools 5.41 2011-06-09
-
-  [MS] drivedb.h: revert attribute 190 to default for Samsung SSD controllers,
-       some 470 series SSDs seem to have some temperature information at
-       this location.
-
-  [MS] drivedb.h update:
-       add attribute details for Samsung controllers, centralize entries
-
-  [MS] drivedb.h update:
-       add attribute details for JMicron JMF61x controllers
-
-  [CF] drivedb.h update:
-       - SandForce Driven SSDs: Add OCZ DENEVA
-
-  [CF] os_win32.cpp: Ignore vendor ID "ATA" if returned by
-       IOCTL_STORAGE_QUERY_PROPERTY.
-
-  [CF] Add ATA NCQ commands to error register decoding.
-
-  [CF] Re-enable '--with-initscriptdir=auto' as default.
-       Change search for initddir and systemdsystemunitdir such that
-       default ./configure does never overwrite system files.
-
-  [MS] drivedb.h update:
-       disentangle Transcend SSD versions
-
-  [MS] drivedb.h update:
-       add attribute details for Crucial C300
-
-  [MS] smartd.initd.in:
-       fix for debian, cleanup. Based on patch of CF.
-
-  [AS] --with-initscriptdir default changed to "no" from "auto" to avoid 
-       filesystem pollution.
-
-  [MS] drivedb.h cleanup:
-       harmonize family names, add AF information into name
-
-  [MS] drivedb.h update:
-       - OCZ Vertex 3
-       - Seagate Barracuda Green 1TB variant
-
-  [CF] Windows: Avoid '%n' printf format specifier because it is always
-       disabled in recent versions of msvcrt.dll.  This fixes truncation
-       of smartd warning email (ticket #174).
-
-  [MS] smartd.initd.in:
-       cleanup, provide targets "reload" and "report" for all platforms
-
-  [CF] drivedb.h update:
-       - JMicron based SSD (JMicron JMF602?): rename from
-         Kingston SSDNow V Series, move Transcend IDE and SATA
-         entries to here.
-
-  [CF] Support ':BYTEORDER' for all attribute print formats.
-
-  [CF] drivedb.h update:
-       - Kingston SSDNow V Series SSDs (ticket #171)
-
-  [CF] Increase size of drive database option parse buffer
-       to allow long '-v N,FORMAT:BYTEORDER,NAME' options.
-
-  [MS] drivedb.h update:
-       - Western Digital Scorpio Blue Advanced Format variants
-
-  [MS] drivedb.h update:
-       correct typo for Cowon iAudio X5
-
-  [MS] drivedb.h USB updates:
-       - Maxtor OneTouch 200GB (unsupported)
-       - LaCie Little Disk
-
-  [AS] FreeBSD: Added native rc.conf style script to the package. 
-       Modifications to the configure script to use correct template and
-       path.
-
-  [AS] freebsd_os.cpp:
-       Fix memory leak in the ata detection code (added free())
-       Using bzero in cam code to clear structure (fixing varnish varning)
-
-  [MS] drivedb.h update:
-       Kingston SSDNow S100 Series
-
-  [MS] drivedb.h USB update:
-       - Samsung S1 Portable
-       - LaCie rikiki USB 3.0
-       - Seagate FreeAgent GoFlex USB 3.0
-       - Cowon iAudio X5
-       - Oxford OXU921DS chip (unsupported)
-
-  [CF] Windows: Add debug output of SCSI sense data.
-
-  [CF] Add 'smartd.service' file for systemd.
-       Add configure option '--with-systemdsystemunitdir'.
-       Disable initd script if systemd is used.
-
-  [MS] drivedb.h update:
-       - Western Digital AV-25 family
-
-  [MS] drivedb.h update:
-       JMicron based SSDs: Add
-         Kingston SSDNow V, Kingston SSDNow V+100, TOSHIBA THNS128GG4BBAA,
-         APPLE SSD TS*, ADATA S596 Turbo
-
-  [CF] drivedb.h update:
-       - Intel 510 Series SSDs (ticket #170)
-
-  [CF] smartctl: Don't issue SMART DISABLE command to 3ware controllers
-       when the port number was not specified (ticket #165).
-
-  [CF] Use get_errmsg() from device instead of errno or syserror() for
-       printing error messages.
-
-  [MS] drivedb.h updates:
-       - G.Skill FALCON II SSD (Indilinx)
-       - HP 250GB SATA disk VB0250EAVER
-       - SAMSUNG SpinPoint M5 HM160HC
-       - SAMSUNG SpinPoint MT2 HM100UI
-       - SAMSUNG HM100UX
-       - Hitachi Deskstar 5K3000 Series
-       - Seagate Barracuda Green (Adv. Format)
-       - Seagate Barracuda XT 3TB variant
-       - Western Digital RE4 Serial ATA family
-       - Western Digital Caviar Green WD20EACS
-       - Western Digital Caviar Black family, SATA 3.0 variants
-       - QUANTUM FIREBALLlct20 10
-       - QUANTUM FIREBALLP AS60.0
-
-  [CF] drivedb.h update:
-       - SandForce Driven SSDs: Add more OCZ SF-1200 and SF-1500 based drives
-
-       Thanks to Sudhir Verman from OCZ Technology for providing this info.
-
-  [CF] drivedb.h USB updates:
-       - Seagate Expansion External (0x0bc2:0x3300) (Debian bug 621411)
-       - ASMedia USB 3.0 (0x174c:0x55aa) (unsupported)
-
-  [CF] smartctl.8.in: Clarify '-t vendor,N' (ticket #169).
-       Update Intel info (ticket #168).
-
-  [CF] drivedb.h update:
-       - Intel 320 Series SSDs (ticket #168)
-
-  [CF] smartctl: Always print sector size in '-i' output (ticket #166).
-
-  [CF] os_linux.cpp: Shorten version string.
-
-  [CF] smartctl: Add option '-f brief' to select new attribute output
-       format.  This format includes additional attribute flags
-       (ticket #109) and fits in 80 columns (ticket #158).
-       This format is now the default for '-x'.
-
-  [CF] smartd: Log changes of offline data collection status if
-       '-l selftest' is specified.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add ADATA S599 64GB,
-         OWC Mercury Extreme Pro
-       - Kingston branded X25-V SSDs (ticket #156)
-       - Transcend SATA Solid State Drive: Truncate attribute name
-
-  [CF] drivedb.h USB updates:
-       - LaCie (0x059f:0x1029) (ticket #153)
-       - WD My Book Office Edition (0x1058:0x1101)
-       - JMicron USB 3.0 (0x152d:0x0539)
-
-  [CF] drivedb.h USB update:
-       - Verbatim Pocket Hard Drive (0x18a5:0x0227) (ticket #159)
-
-  [CF] drivedb.h update:
-       - SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS) (ticket #159)
-
-  [CF] Add support for ATA Long Logical Sectors (LLS) (ticket #159).
-
-  [DG] [SCSI] smartctl: (re-)use capacity formatting in utility.cpp
-
-  [CF] configure.in: Remove '-Wno-format' for MinGW.
-       Recent MinGW versions support MSVCRT printf format strings.
-
-  [CF] Print ATA disk capacity with SI prefix.
-       Add/move capacity formatting to utility.cpp
-
-  [CF] Add error messages if ATA pass-through does not return required
-       ATA output registers (for SMART RETURN STATUS, GET POWER MODE).
-       This prevents misleading 'SMART Status command failed' messages
-       (see ticket #155).
-
-  [CF] Fix WWN support check for older ATA-7 disks.
-
-  [DG] [SCSI] smartctl: add 'Logical Unit id' from the Device
-       Identification VPD page (0x83)
-
-  [DG] [SCSI] smartctl: add 'User Capacity' (disk size) in human
-       readable form
-
-  [CF] smartctl, smartd: Print World Wide Name (WWN) of ATA device.
-
-  [CF] smartctl: Print more specific error message if IDENTIFY DEVICE
-       failed (ticket #61).  Add check for empty IDENTIFY data.
-
-  [CF] Windows installer: Add help message box.
-
-  [CF] Windows installer: Request admin rights, select 'All Users'
-       section.  This fixes shortcut removal under Vista and later.
-       Add '/SO' option to select components for unattended install.
-       Patch was provided by József Fejes.
-
-  [CF] Windows: Add update-smart-drivedb.nsi NSIS script to build
-       drivedb.h update tool.
-
-  [CF] Windows: Move search for NSIS compiler from Makefile.am to
-       configure.in.
-
-  [CF] update-smart-drivedb.in: Move DRIVEDB_BRANCH name creation
-       from script to configure.in.
-
-  [CF] os_linux.cpp: Replace printf() by pout().  Disable unused
-       function dumpdata().
-
-  [CF] Windows: Include CSMI (for Intel RAID) in default DEVICESCAN.
-
-  [CF] configure.in: Remove info messages about old defaults.
-
-  [CF] drivedb.h: Set unneeded USB bcdDevice patterns to empty.
-
-  [CF] Rework USB ID drivedb search.  Stop search at first matching
-       entry with empty bcd_device pattern.
-
-  [CF] Move handling of '-F swapid' from formatting to identity read
-       function.  Remove unneeded 'fix_swapped_id' parameters.
-
-  [CF] smartd: Log warning from drive database if present.
-       smartctl: Do not search drive database twice.
-
-  [MS] drivedb.h USB updates:
-       - Samsung S2 Portable variant (0x04e8:0x1f08)
-       - Lacie rikiki (0x059f:0x102a)
-       - Toshiba Stor.E Steel series (0x0930:0x0b11)
-       - Super Top generic enclosure (0x14cd:0x6116)
-
-  [CF] Let constructor of regular_expression throw on error by default.
-
-  [CF] smartd: Preserve last selective self-test span in '.state' file
-       and use it if the selective self-test log was cleared (ticket #88).
-
-  [CF] smartctl --scan-open: Make output compatible with smartd.conf
-       (ticket #108).  Fix possible crash if autodetect_open() returns
-       new object.
-
-  [CF] do_release: Re-add signing of tarball.
-
-  [CF] os_linux.cpp: Change '-d sat' to '-d sat,12' for USB only if
-       kernel is older than 2.6.29.  Add kernel release to version info.
-
-  [CF] smartd: Add '-l scterc,READTIME,WRITETIME' directive (ticket #150).
-
-  [CF] smartctl: Fix exit status of '-l xerror' and '-l xselftest'
-       (ticket #144).
-
-  [CF] smartd: Use '-M daily' as default if state persistence is enabled.
-       This avoids that emails are suppressed forever (ticket #35).
-
-  [CF] smartd: Log identify information of each ATA device.
-
-  [CF] smartd: Disable '-C' and '-U' monitoring if raw values are
-       very large (ticket #148).
-
-  [CF] smartd: Write reserved attribute byte to '.state' file
-       (ticket #118).
-
-  [MS] drivedb.h USB updates:
-       - Seagate FreeAgent Go Flex Desk USB 3.0
-       - Toshiba Canvio 500GB
-
-  [MS] drivedb.h USB updates:
-       - Freecom HD 500GB (0x07ab:0xfcda)
-       - Generic JMicron adapter (0x152d:0x2337)
-       - RaidSonic ICY BOX IB-110StU3-B (0x1759:0x500[02])
-       - Connectland BE-USB2-35BP-LCM (0x040d:0x6204)
-       - Freecom Classic HD 120GB (0x07ab:0xfccd)
-       - OCZ THROTTLE OCZESATATHR8G (0x152d:0x0602)
-       - Vantec NST-400MX-SR (0x1a4a:0x1670)
-       - Intenso Memory Station 2.5" (0x13fd:0x1840)
-
-  [CF] Don't report failed self-tests outdated by a newer successful
-       extended self-test as errors (ticket #147).
-       This affects smartctl exit status and smartd syslog output and
-       warning email.  Only implemented for ATA.
-
-  [CF] os_linux.cpp: Don't use buffer of size PATH_MAX for the result
-       of realpath().  This also fixes compilation on Debian Lenny.
-
-  [CF] smartd man pages: Add some missing [ATA only].
-
-  [CF] os_linux.cpp: Dereference symlinks before guess of device type
-       (ticket #146).  Minor rework of autodetect_smart_device().
-
-  [CF] smartctl -l scterc: Don't get ERC if only set is requested.
-       This prevent misleading error messages if ATA output registers
-       are not supported.
-
-  [CF] Windows: Prevent warnings from gcc 4.5.1.
-
-  [CF] os_netbsd.cpp, os_openbsd.cpp: Add missing <errno.h>
-
-  [CF] os_freebsd.cpp: Add missing <errno.h>
-
-  [CF] dev_legacy.cpp: Add missing <errno.h>
-
-  [CF] Linux megaraid: Fix pass-through of non-data ATA commands
-       (ticket #149).
-       Only reject commands which require ATA output registers.
-
-  [CF] configure.in: Remove '-fno-strict-aliasing' from CXXFLAGS.
-       This reverts r2992 (see ticket #23).
-
-  [CF] Linux megaraid: Avoid strict-aliasing warnings.
-       Patch was provided by Stanislav Brabec (2009-06-03).
-
-  [MS] Make functions without prototypes static.
-
-  [MS] Remove unnecessary includes, move inclusion of errno.h from scsicmds.h
-       to the appropriate *.cpp files. Add cciss.h to cciss.cpp.
-
-  [MS] os_linux.cpp: rename variables to please "-Wshadow"
-       utility.cpp: remove unused variable "start"
-       os_win32/syslogevt.c: plug resource leak
-
-  [CF] Rename variables to prevent warnings if '-Wshadow' is set.
-       Remove unnecessary includes.  Fix some comments.
-
-  [CF] drivedb.h updates:
-       - Intel X18-M/X25-M/X25-V G2 SSDs: Add firmware bug warning
-       - Samsung SpinPoint M6
-       - Samsung SpinPoint M7E (AFT)
-       - Samsung PM800 SSDs
-       - Samsung PM810 (470 series) SSDs
-
-  [CF] Windows: Add experimental CSMI support for disks behind Intel Matrix
-       RAID driver. Accessed through new device names '/dev/csmi[0-9],N'.
-       Experimental DEVICESCAN can be enabled by '-d csmi'.
-
-  [MS] - ataprint.cpp: adjust print format for insanely large
-           offline data collection times (e.g. WD drives).
-       - getopt: change config.h #include format from angle brackets to quotes
-
-  [MS] drivedb.h update:
-       - Fujitsu MJA2 BH series
-       - Toshiba MK..59GSXP series (Adv. Format)
-       - Toshiba MK..59GSM series (Adv. Format)
-       - Western Digital Caviar Blue SATA 3.0 variants
-       - Seagate Barracuda XT
-
-  [CF] smartctl: Print help message if no option is specified (ticket #39).
-       Don't issue any other ATA command if only '-n POWERMODE' is specified.
-
-  [CF] smartd: Output multiple lines via separate syslog(3) calls
-       (ticket #135).
-
-  [CF] smartctl: Add new ATA minor revisions and log addresses from ACS-2
-       revision 4a.  Replace runtime asserts by compile time asserts.
-
-  [CF] smartd: Remove "default: /var/log/messages" hint from warning mail.
-       This obsoletes Debian patch 60_remove-redhatism.diff.
-
-  [CF] Windows: Include USB devices in DEVICESCAN (ticket #116).
-
-  [CF] Windows: Use direct WMI access to detect USB IDs (ticket #115).
-       This replaces 'wmic' runs and speeds up USB detection.
-
-  [CF] configure.in: Rework platform-specific settings.
-
-  [CF] configure.in: Remove some no longer used settings:
-       -lselinux (duplicate), NEED_SOLARIS_ATA_CODE, OS_FREEBSD.
-
-  [CF] Makefile.am: Remove SUBDIRS. Recursive targets are no longer used.
-
-  [CF] Use log directory to check for old error and self-test log
-       support (ticket #89).
-
-  [CF] drivedb.h USB update:
-       - WD My Book Essential 3TB USB 3.0
-
-  [CF] Fix usb header includes for DragonFly BSD (ticket #141).
-
-  [CF] smartctl: Print physical and logical sector sizes (ticket #62).
-
-  [CF] drivedb.h updates:
-       - Fujitsu MHT: Add AC variant
-       - Fujitsu MHW2 AC
-       - Samsung SpinPoint T166: Needs '-v 197,increasing'
-       - Seagate Barracuda 7200.11: Add firmware SD81 as buggy
-       - WD Scorpio Blue EIDE: Add 320GB
-
-  [CF] drivedb.h USB updates:
-       - Samsung S2 Portable (ticket #136)
-       - Move Verbatim 0x152d:0x2351 to JMicron section
-
-  [AS] drivedb.h updates:
-       - Verbatim Portable Hard Drive eSATA & USB 2.0 Combo 500GB
-
-  [CF] Happy New Year! Update copyright year in version info.
-
-  [CF] drivedb.h updates:
-       - Hitachi Deskstar 7K3000
-       - Hitachi Travelstar 7K320: Add ...362 variant
-       - Seagate Maxtor DiamondMax 21: Add STM3250310AS
-       - Toshiba 2.5" HDD MK..65GSX
-       - WD Caviar Green (Adv. Format): Add 750GB, 2.5TB, 3TB
-
-  [CF] drivedb.h USB updates:
-       - Micron USB SSD (unsupported, ticket #133)
-       - Samsung G2 Portable (ticket #132)
-       - Samsung Story Station 3.0 (ticket #130)
-       - Seagate FreeAgent GoFlex (ticket #131)
-
-  [CF] update-smart-drivedb.in: Add workaround for OpenBSD shell bug:
-       'set -e; if eval false; ...' aborts script (ticket #128).
-
-  [CF] update-smart-drivedb.in: Add platform specific download tools:
-       'fetch' on FreeBSD (ticket #127), 'ftp' on OpenBSD.
-
-  [CF] drivedb.h USB updates:
-       - JMicron 0x152d:0x2509
-       - WD My Passport 0730
-
-  [CF] drivedb.h updates:
-       - Samsung SpinPoint F3 EG: Add 2TB
-       - SandForce Driven SSDs: Add ADATA S599, SuperTalent TeraDrive CT
-       - Seagate Constellation (SATA)
-       - Seagate Constellation ES (SATA)
-       - WDC My Passport: Add WD5000BMVW
-
-  [CF] drivedb.h update:
-       - Samsung SpinPoint F4 EG: Add 1.5TB, update firmware bug warning.
-
-  [DG] [SCSI] Fix log page sanity check problem if the DS bit set
-       in response. Caused '-l background' to fail.
-
-  [CF] drivedb.h updates:
-       - Samsung SpinPoint F4 EG: Warning about bad blocks
-
-  [CF] update-smart-drivedb.in: Replace ERE by BRE.  Script does no
-       longer require GNU sed (Ticket #126).
-
-  [DG] In '-r ioctl' show vendor specific SCSI commands as such rather
-       than 'unknown'.
-
-  [CF] Add check for CompactFlash Signature in ATA IDENTIFY data.
-       This avoids that older CF microdrives are detected as ATAPI
-       devices (Ticket #125).
-
-  [CF] drivedb.h updates:
-       - Apple SSDs TS*
-       - Crucial RealSSD C300 Series
-       - Kingston SSDNow V Series
-       - Indilinx Barefoot based SSDs: Add OCZ-ONYX
-       - SandForce Driven SSDs: Add OCZ VERTEX2-PRO
-       - Transcend CompactFlash Cards: Add TS4GCF133
-
-  [CF] Windows installer: Add missing quotes in smartctl-run.bat
-       and smartd-run.bat (Ticket #124).
-
-  [CF] OpenBSD: Fix DEVICESCAN for OpenBSD >= 4.8 (Ticket #123).
-
-  [CF] daemon_win32.cpp: Remove duplicate assignment (Ticket #120).
-
-  [CF] Makefile.am: Do not overwrite existing smartd.conf file
-       (Ticket #122).  If smartd.conf exists and differs from the
-       default then smartd.conf.sample is installed instead
-       If smartd.conf.sample exists on uninstall then smartd.conf is
-       preserved.
-
-  [CF] Linux megaraid: Fix segfault on non-data commands (Ticket #78).
-       The /dev/megaraid_sas_ioctl_node driver does not allow
-       sge_count = 1 and sgl[0].iov_len = 0.
-
-  [CF] Remove EXPERIMENTAL notes for features already present
-       in 5.39.
-
-  [CF] Rework '-d TYPE' documentation on man pages.
-
-  [CF] drivedb.h updates:
-       - Seagate Maxtor DiamondMax 21: Add 80GB
-       - Western Digital Caviar Black: Add 1TB/64MB
-
-  [CF] drivedb.h USB updates:
-       - iRiver iHP-120/140 (Ticket #119)
-       - ASMedia ASM1051
-
-  [CF] Makefile.am: Handle examplescripts in main Makefile.
-       Remove 'examplescripts/Makefile.am'.
-
-  [CF] configure.in: New option '--with-exampledir' allows to change
-       path of 'DOCDIR/examplescripts' directory.
-       (Debian package uses '/usr/share/doc/smartmontools/examples')
-
-  [CF] Replace global 'con->dont_print/...' variables by 'printing_is_*'.
-       Remove global 'con'trol pointer.  Remove file 'extern.h'.
-
-  [CF] Replace global 'con->reportata/scsiioctl' variables by '*_debugmode'.
-
-  [CF] Replace global 'con->conservative/permissive' variables by
-       'failuretest_*'.  Move failuretest() function to smartctl.cpp.
-
-  [CF] Remove unused CONTROLLER_* defines.
-
-  [CF] Remove unused controller support from dev_legacy adapter module.
-
-  [CF] Make 'debugmode' variable local to smartd.cpp.
-
-smartmontools 5.40 2010-10-16
-
-  [CF] examplescripts/Example3: Use stdin to pass message to 'wall'
-       command (ticket #114).
-
-  [CF] smartd: Fix setting of SMARTD_DEVICE and SMARTD_DEVICETYPE
-       environment variables (ticket #113).
-       Regression was introduced by rework of smartd data structures.
-       SMARTD_DEVICE is now set to the plain device name.
-       SMARTD_DEVICETYPE is now set to 'auto' if no '-d' directive is
-       specified.  Smartctl now accepts '-d auto' for this purpose.
-
-  [CF] Remove "Lifetime" from Min/Max temperature attribute output
-       (ticket #111).  Interval is device specific.
-
-  [CF] configure.in: Print resource/message compiler info for Windows only.
-
-  [CF] FreeBSD: Rework get_dev_names_cam() to support more than 26 devices.
-
-  [CF] drivedb.h updates:
-       - Seagate Barracuda 7200.10: Add 360GB
-       - USB: Iomega MDHD-UE
-       Patch provided by Rob Marissen.
-
-  [DL] Standby mode not detected properly on FreeBSD (ticket #91).
-
-  [MS] os_linux.cpp: fix "gcc -flto" build error by including stddef.h
-
-  [CF] drivedb.h update:
-       - Indilinx Barefoot based SSDs: Add OCZ-VERTEX 1199 and -TURBO
-
-  [CF] TODO file: Move open entries to tickets #106, #107, #108, #109, #110.
-       Remove outdated entries.
-
-  [CF] drivedb.h USB update:
-       - SunPlus 0x04fc:0x0c05
-
-  [CF] drivedb.h update:
-       - SandForce Driven SSDs: Add Corsair Force, fix typo
-
-  [CF] Print hex values of unknown self-test type or status.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Fix regex for Unigen UG99SGC
-       - Seagate Momentus XT series
-       - Quantum Bigfoot: Add 12.7GB
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add 11 attributes of new FW,
-         add Unigen UG99PGC
-       - WD AV ATA family: Add 250GB, 320GB
-       - WD AV SATA family
-
-  [CF] Windows: Build syslogevt.exe with MinGW.  Now possible because
-       binutils provides windmc.
-
-  [CF] Makefile.am: Remove install message about smartd startup.
-       It might be misleading because it is not correct for all platforms.
-
-  [CF] configure.in: Minor fix of '--enable-drivedb' new defaults
-       detection.
-
-  [CF] Update links, configure and OS info in INSTALL file.
-       Replace tabs by spaces.
-
-  [CF] configure.in: Fix '--enable-sample' and '--with-selinux'.
-       Fix obsolete use of AC_DEFINE().
-
-  [CF] drivedb.h updates:
-       - IBM Deskstar 60GXP, 40GV & 75GXP: Update link (ticket #99)
-       - Seagate Barracuda 7200.12: Add ST31000523AS and others
-       - WD Caviar Black: Add 2TB
-       - WD VelociRaptor: Add 6 Gb/s models
-
-  [CF] Windows installer: Fix smartctl-run.bat for drive menu (ticket #31).
-
-  [CF] Windows: Create md5/sha1/sha256 checksums of the binaries.
-       Add checksums.txt file to binary distribution.
-
-  [CF] Windows: Include drivedb.h into binary distribution.
-
-  [CF] drivedb.h updates:
-       - Intel X18-M/X25-M/X25-V G2: Add X25-V 40GB
-       - Transcend CompactFlash Cards
-
-  [CF] drivedb.h updates:
-       - Seagate Momentus 7200 FDE.2: Add ST9160414ASG
-       - Seagate Pipeline HD 5900.1 and 5900.2
-       Based on patch provided by Marcin Falkiewicz.
-
-  [CF] Remove unused variable 'reportbug'.
-
-  [CF] Make function PrintOut() local to smartd.cpp, remove it from
-       smartctl.cpp.
-
-  [CF] Windows: Improve compatibility with MinGW variants.
-       Add configure check for DDK include files.
-       Drop support for '-mno-cygwin' from old Cygwin gcc.
-
-  [AS] smartctl.8.in minor update: adding FreeBSD ahci/scsi device hints
-
-  [CF] Fix build if SVN Id keywords are not expanded (ticket #94).
-
-  [CF] Windows: Remove "." from DLL search path to prevent DLL
-       preloading attacks.
-
-  [CF] drivedb.h USB update:
-       - JMicron 0x152d:0x0551 (ticket #95)
-       Add note about port multipliers to smartctl man page.
-
-  [CF] drivedb.h updates:
-       - SandForce Driven SSDs: Add Unigen drives
-       - Indilinx Barefoot based SSDs: Add ASAX Leopard Hunt II
-
-  [CF] drivedb.h update:
-       - Intel X18-M/X25-M G2: Add names of timed workload attributes.
-       Document attribute clear command '-t vendor,0x40' on smartctl
-       man page.
-
-       Thanks to Artem Danielov from Intel for providing the
-       required information and drives for testing.
-
-  [CF] drivedb.h update:
-       - SandForce Driven SSDs: Add OCZ drives with form factor info.
-
-  [CF] drivedb.h update:
-       - Intel X25-E, X18-M/X25-M (add X18-M, update attributes)
-
-  [CF] configure.in: '--enable-drivedb' is now the default.
-
-  [CF] drivedb.h update:
-       - Indilinx Barefoot based SSDs
-         (combine and update 5 SSD entries using this controller)
-
-  [CF] drivedb.h update:
-       - SandForce Driven SSDs (Demo Drive, OCZ-Agility2/Vertex2/Vertex-LE)
-
-       Thanks to Jeremy Werner (jwerner@sandforce.com) from SandForce for
-       providing the required information and a demo drive for testing.
-
-  [CF] drivedb.h update:
-       - Add 1.5TB drive to SAMSUNG SpinPoint F3 EG series
-
-  [CF] Add print formats '-v ID,msec24hour32' and '-v ID,raw24/raw32'.
-       Used by SSDs with SandForce controller.
-
-  [CF] Allow SMART threshold entries at positions different from
-       attribute table. This fixes attribute output for recent
-       SSDs with SandForce controller.
-
-  [CF] smartctl: Add option '-t vendor,N' to issue ATA
-       command SMART EXECUTE OFF-LINE IMMEDIATE with
-       a vendor specific subcommand.
-
-  [CF] drivedb.h update:
-       - SAMSUNG SpinPoint V80 series (ticket #85)
-
-  [CF] Linux: Support SATA drives on LSI 3ware 9750 controllers.
-       Patch provided by Victor Payno (ticket #86).
-       Modified to avoid duplicate code.
-
-  [CF] drivedb.h update:
-       - SAMSUNG SpinPoint M7 series
-
-  [CF] drivedb.h USB update:
-       - Buffalo JustStore Portable HD-PVU2
-
-  [CF] drivedb.h USB updates:
-       - Iomega LDHD-UP (ticket #83)
-       - WD Elements Desktop 2TB
-       - Maxtor OneTouch (0x0d49:0x7300)
-
-  [MS] drivedb.h updates:
-       - Intel X25-M SSD first Generation
-       - ExcelStor J8160
-       - OCZ Agility2
-
-  [CF] drivedb.h updates:
-       - Transcend Solid State Drives (ticket #80)
-
-  [CF] drivedb.h USB update:
-       - LaCie Rugged Hard Drive
-
-  [CF] smartctl: Add options '--scan, --scan-open'.
-
-  [CF] Windows: Use also VendorId from IOCTL_STORAGE_QUERY_PROPERTY.
-
-  [CF] smartd: Change defaults of '-C' and '-U' directives to 0 (disabled)
-       if attribute name is changed by '-v 19[78],...' directive.
-
-  [CF] configure.in: Fix include path for MinGW.
-
-  [CF] Move 'posix/reg*' to 'regex/reg*'.
-       Add configure check for regex.
-
-  [MS] cciss.cpp: avoid redefining be32toh
-       megaraid.h: replace use of undefined preprocessor macro BITS_PER_LONG
-                   by union construct (thanks to [DL]).
-                   Add assert for sizeof(ptr_t) == 8 (thanks to [CF]).
-
-  [CF] Makefile.am: Add os_qnxnto.* to EXTRA_smart*_SOURCES.
-
-  [MS] drivedb.h update:
-       - WD My Passport Essential SE 1TB variant (USB interface)
-
-  [CF] Use getopt_long() from getopt/getopt* if necessary.
-       Add missing cast to os_qnxnto.cpp.
-       This fixes build on QNX (ticket #1).
-       Thanks to Stefan (stevestereo) for testing.
-
-  [CF] drivedb.h update:
-       - WD Caviar Green (Adv. Format) family
-
-  [CF] drivedb.h USB update:
-       - Verbatim External Hard Drive 47519
-
-  [DL] Fix regression in smartctl option '-t select,M-N' which prevents
-       that more than one test span can be specified (ticket #75).
-
-  [CF] drivedb.h updates:
-       - Add raw64 attributes 1, 210-213 to all SSD drives with
-         64-bit attribute format.
-
-  [CF] Support smartd '-l xerror' also for disks which use reserved
-       byte as log index.
-
-  [CF] Fix initialization of values missing in smartd '.state' files.
-
-  [CF] Add smartd directive '-l xerror' to check error count from
-       the Extended Comprehensive SMART Error Log (ticket #34).
-
-  [CF] Fix max number of cciss devices, 128 devices are supported
-       again (ticket #49). Regression was introduced during migration
-       to new interface.
-
-  [CF] Update man pages (include Debian patch
-       60_remove-redhatism.diff and Debian Bug 570892).
-
-  [CF] Add SVN revision number to man pages.
-
-  [CF] Windows: Read default drivedb.h and smartd.conf from exe
-       directory instead of current directory.
-
-  [CF] drivedb.h update:
-       - SAMSUNG SpinPoint M series
-
-  [CF] Replace runtime check of byte ordering by compile time check.
-
-  [CF] drivedb.h USB updates:
-       - ALi M5621 (unsupported)
-       - LaCie with JMicron (ticket #69)
-       - JMicron (0x2352)
-       - Enable 48-bit commands for Hitachi drive
-
-  [CF] Read USB ID info from drivedb.h (ticket #44).
-
-  [CF] Create branch RELEASE_5_39_DRIVEDB with last drivedb.h file
-       compatible with smartmontools 5.39[.1].
-
-  [MS] drivedb.h updates:
-       - WD Raptor 80GB variant
-       - correct Regex for some WD AV-GP variants
-       - Hitachi Ultrastar A7K2000
-       - Hitachi Travelstar 5K500.B
-       - Hitachi Deskstar 7K1000.C
-       - adjust naming of Hitachi Travelstar and Deskstar drives
-
-  [CF] Move 'posix/getopt*' to 'getopt/getopt*'.  Can be used for
-       platforms with regex() but without getopt_long() (QNX, ticket #1).
-
-  [CF] smartd '-l selftest' directive: Print info if error count
-       decreased.  Avoid misleading warning if error count decreased
-       to zero (ticket #67).
-
-  [CF] smartctl: Rework ataPrintMain().  Issue ATA SMART commands only if
-       necessary.  Improve handling of SMART STATUS command failure when
-       ATA output registers are missing (ticket #27).
-
-  [CF] USB ID updates:
-       - A-DATA SH93
-       - Hitachi/SimpleTech 1TB
-
-  [CF] configure.in: Print configuration summary.
-
-  [CF] smartctl -l xselftest,selftest: Print old log if extended self-test
-       log index is out of range.  Workaround for bad log data from Intel
-       X25-M G2 (ticket #66).
-
-  [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)
-
-  [CF] Makefile.am: Avoid duplication of man page filter script.
-
-  [CF] smartd: Add option '-C, --capabilities' if libcap-ng is available
-       (ticket #45).
-       Support is added if libcap-ng is found during build. This can
-       be overridden by configure option '--with-libcap-ng=[auto|yes|no]'.
-
-       Based on Debian patch:
-       http://patch-tracker.debian.org/patch/series/view/smartmontools/5.39-3/62_lowcap.patch
-       Modified to fix regression (ticket #41, Debian bug 564876).
-
-  [CF] Bugfix release 5.39.1.
-
-  [CF] Linux: Fix spin-up of SATA drive if '-n standby' is used
-       (ticket #37).  For some reason, this happens if the SCSI/SAT
-       device is opened with O_RDWR instead of O_RDONLY.
-
-  [CF] Windows: Fix parsing of 'tw_cli' output for 3ware 9.5.x release
-       (ticket #43).
-
-  [CF] Add USB IDs of Seagate FreeAgent Go, Seagate Expansion Portable
-       and WD My Passport (IDE).
-
-  [CF] autogen.sh: Fix version regexp, allow automake 1.11.1.
-
-  [CF] Linux: Allow smartd 'DEVICESCAN -d sat' (ticket #13).
-       Detects (S)ATA devices behind a standard SAT layer
-       (Vendor ID: "ATA     "), but not USB bridges with SAT support.
-       Only added for backward compatibility with 5.38.
-       No longer needed as 'DEVICESCAN' without '-d' includes these devices.
-
-  [CF] Add USB ID of Seagate FreeAgent Desktop.
-
-  [CF] smartd: Fix directive '-l selftest' (ticket #36)
-       Regression was introduced with r2773.
-
-  [CF] smartd: Don't disable attribute tracking if read thresholds fails.
-       Windows: Don't return dummy thresholds if IOCTL_STORAGE_QUERY_PROPERTY
-       or 3ware CLI is used to read SMART data.
-
-  [CF] Windows: Print warning if admin rights are missing.
-
-  [CF] Replace some 'EXIT(status)' calls by 'return status'.
-       Remove unnecessary casts from 'nonempty()' calls.
-
-  [CF] Windows: Set ata_device::ata_identify_is_cached() return value
-       according to I/O-control actually used.
-
-  [CF] Print ATA output registers if SMART status command returns bogus
-       register values.
-
-  [CF] Windows: Don't return false ATA version info if IDENTIFY data
-       is build from IOCTL_STORAGE_QUERY_PROPERTY result or from 3ware CLI
-       output.
-       smartctl: Handle missing info about ATA version in '-i' output.
-
-  [CF] smartctl: Don't print log directory if '-q errorsonly' is specified.
-
-  [CF] smartctl: Fix option '-q, --quietmode' (ticket #11).
-       Regression was introduced with r2807.
-
-  [CF] drivedb.h update:
-       - SAMSUNG SpinPoint F2 EG series
-
-  [CF] Add USB ID of Samsung Story Station.
-
-  [MS] drivedb.h update:
-       - Hitachi Travelstar 5K320: some EA models miss last 2 "0" 
-         in model string
-       - Seagate Barracuda LP series
-
-  [CF] drivedb.h update:
-       - Crucial M225 SSD
-
-  [CF] drivedb.h updates:
-       - WDC Scorpio Blue Serial ATA (640GB, 750GB, 1TB)
-       - WDC My Passport Essential SE
-
-  [CF] Add USB ID of Toshiba PX1270E-1G16.
-
-  [CF] Happy New Year! Update copyright year in version info.
-
-  [CF] drivedb.h update:
-       - SAMSUNG SpinPoint M40/60/80 series
-
-  [CF] Add direct access to 48-bit LBA register in 'ata_in/out_regs_48bit'.
-
-  [DL] drivedb.h updates:
-       - WDC My Passport Essential/USB (capacity 250GB, 400GB & 500GB)
-
-  [DL] -r ataioctl,2: print text representation of data also (ticket #32)
-
-  [DL] FreeBSD: freebsd_ata_device::ata_pass_through implemented (part of ticket #18)
-
-  [CF] drivedb.h updates:
-       - Hitachi Travelstar 7K320 (ticket #28)
-       - Hitachi Travelstar 7K500
-
-  [DL] -l gpllog,...: print text representation of data also (ticket #30)
-
-  [DL] FreeBSD: check reallocf() result for failures
-
-  [AS] FreeBSD: fixing crash on kFreeBSD (#29), patch provided by Petr Salinger
-
-  [CF] Makefile.am: 'make check' now tests the syntax of drivedb.h.
-
-  [CF] Cygwin: Open drive database files in text mode.
-
-  [CF] Cygwin: Check for 'syslogd' and 'syslog-ng' in initd script.
-
-  [CF] Windows: Disable Win9x/ME specific code if no longer supported
-       by compiler.
-
-  [CF] Add '-v ID,FORMAT:BYTEORDER[,NAME]' to specify byte order
-       of attribute raw value.
-
-  [CF] configure.in: Change --with-docdir default from
-       'PREFIX/share/doc/smartmontools-VERSION' to
-       'DATADIR/doc/smartmontools' to make it consistent with
-       --docdir option added in autoconf 2.6x (ticket #24).
-       Autoconf 2.5x is still supported.
-
-  [CF] Move drive database entries from 'knowndrives.cpp' to new file
-       'drivedb.h'.  This allows to update the drive database from SVN
-       if installation was configured with '--enable-drivedb'.
-       Remove the Makefile target to create 'drivedb.h'.
-
-  [CF] do_release: Add support to release from a dir below 'branches'.
-       Accept partial checkouts.
-
-smartmontools 5.39.1 2010-01-28
-
-  [CF] Linux: Fix spin-up of SATA drive if '-n standby' is used
-       (ticket #37).  For some reason, this happens if the SCSI/SAT
-       device is opened with O_RDWR instead of O_RDONLY.
-
-  [CF] Windows: Fix parsing of 'tw_cli' output for 3ware 9.5.x release
-       (ticket #43).
-
-  [CF] Linux: Allow smartd 'DEVICESCAN -d sat' (ticket #13).
-       Detects (S)ATA devices behind a standard SAT layer
-       (Vendor ID: "ATA     "), but not USB bridges with SAT support.
-       Only added for backward compatibility with 5.38.
-       No longer needed as 'DEVICESCAN' without '-d' includes these devices.
-
-  [CF] smartd: Fix directive '-l selftest' (ticket #36)
-       Regression was introduced with r2773.
-
-  [CF] smartctl: Don't print log directory if '-q errorsonly' is specified.
-
-  [CF] smartctl: Fix option '-q, --quietmode' (ticket #11).
-       Regression was introduced with r2807.
-
-  [CF] Happy New Year! Update copyright year in version info.
-
-  [DL] FreeBSD: check reallocf() result for failures
-
-  [AS] FreeBSD: fixing crash on kFreeBSD (#29), patch provided by Petr Salinger
-
-  [CF] do_release: Add support to release from a dir below 'branches'.
-       Accept partial checkouts.
-
-smartmontools 5.39 2009-12-09
-
-  [CF] do_release: Commit CHANGELOG and NEWS also. Allow to review changes.
-
-  [CF] Linux: Add workaround for Adaptec series 2, 5 and 5Z controllers
-       with firmware >= 17380.  Patch was provided by Phil Wilson, see:
-       http://linux.adaptec.com/2009/07/24/using-smartmontools-538-with-series-255z-controllers-with-firmware-17380-onwards
-
-  [CF] configure.in: Add '-fno-strict-aliasing' to CXXFLAGS if supported.
-       This suppresses gcc 4.4.1 warnings on Linux and avoids possible
-       unsafe optimizations (ticket #23).
-       Patch was provided by Manfred Schwarb.
-
-  [CF] Avoid truncation of configure arguments in '-V' output.
-
-  [AS] Added USB IDs of WD Passport USB Portable
-
-  [CF] Linux: Fix segfault in 3ware interface (ticket #22).
-
-  [MS] knowndrives.cpp updates:
-       - Hitachi Deskstar 7K2000
-       - Seagate Momentus 7200 FDE.2 series
-
-  [CF] Add USB ID of WD My Passport 070A.
-       knowndrives.cpp update:
-       - WD My Passport hard drive (USB interface)
-
-  [CF] smartd: Write 'worst' attribute value to '.state' file also.
-       This allows to use state persistence with 'raw64' attributes.
-
-  [CF] Rework ATA SMART attribute check in smartctl and smartd.
-       smartd: Ignore normalized attribute value and threshold
-       if 'raw64' or 'hex64' format is selected.
-
-  [CF] Add USB IDs of Iomega LPHD080-0, 2 Genesys Logic bridges and
-       Initio 316000.
-
-  [MS] knowndrives.cpp update: Hitachi Travelstar 5K320 series
-
-  [CF] smartctl: Ignore normalized attribute value and threshold
-       if 'raw64' or 'hex64' format is selected.
-
-  [CF] knowndrives.cpp updates:
-       - add OCZ-Vertex raw64 attributes
-       - add OCZ-Agility
-       Thanks to Marcin Marszalek for the patch.
-
-  [CF] Add '-v ID,hex*' print formats. Fix '-v N,FORMAT,NAME' parsing.
-
-  [CF] Add '-v ID,raw64[,...]' print format based on a patch provided
-       by Marcin Marszalek.
-
-  [CF] Add '-v ID,RAW_FORMAT[,ATTR_NAME]' option. This allows to add new
-       attributes without the need to enhance the '-v' option.
-       Rework attribute name and raw value formatting.
-
-  [CF] Fix auto_ptr initialization in linux_scsi_device::autodetect_open().
-
-  [CF] Remove duplicate function smart_device_list::add().
-       Replace calls with push_back().
-
-  [MS] attribute update:
-       trim attribute names to 23 chars
-
-  [CF] Add smart pointer class template to manage device object pointers.
-       Remove related 'delete' calls and 'try/catch' blocks.
-
-  [CF] do_release: Replace generation of '*.asc' by '*.md5' and '*.sha1'.
-
-  [MS] attribute updates:
-       - change attributes 202,204,205 to the meanings as found in wdidle3.exe
-         retain old entries as comments (possible Fujitsu use)
-       - add attribute 240 as found in Fujitsu MHY2xxxBH
-
-  [MS] attributes updates:
-       - attributes 225, 232 and 233 for Intel X25-E SSD
-       - non-conflicting attributes extracted from wdidle3.exe
-         (thanks to Franc Zabkar and Dan Lukes)
-
-  [CF] Update Windows and ./configure info in INSTALL file.
-
-  [CF] Update 'do_release' script for SVN.
-
-  [MS] knowndrives.cpp updates:
-       - Western Digital MyPassport Essential hard drive (USB interface)
-       - Seagate Momentus 7200.4 series
-       - Western Digital Raptor X
-       - Intel X25-E SSD
-
-  [CF] knowndrives.cpp updates:
-       - New Seagate 7200.11 firmware version
-       - Update IBM link
-
-  [CF] smartctl: Use printf() instead of pout() for exception error
-       messages to avoid access to bogus 'con->dont_print'.
-
-  [CF] smartd: Add missing help texts for '-A', '-B' and '-s'.
-
-  [CF] Add missing check for log page 0x11 support to smartctl
-       '-l sataphy' option.
-
-  [CF] Add USB ID of Freecom Hard Drive XS.
-
-  [AS] Linux: Autodetect DELL PERC and MegaRAID controllers.
-       Hiding debug messages coming from megaraid code.
-
-  [AS] Linux: Fixed SATA drives support on megaraid device (see ticket #15).
-
-  [AS] FreeBSD: Removed all old detection code, moving everything to
-       the objects. Now we are using CAM/ATA enumerators to guess device
-       type.
-
-  [AS] FreeBSD: Added autodetection for the ada disks (untested).
-       Code for USB device detection refactored.
-
-  [AS] FreeBSD: cam_get_umassno rewritten using XPT_PATH_INQ
-
-  [AS] FreeBSD: do not open/close cam device on every request for SCSI
-       disks. Use com->camdev both for SCSI and ATAPICAM.
-
-  [AS] FreeBSD: added support for the ada disks, based on agapon patch
-
-  [CF] Add names for attributes 184 and 188, see ticket #17.
-
-  [CF] configure.in: Change configure date syntax.
-       Add message to '-mno-cygwin' option check.
-
-  [GK] Add names for some attributes used in MLC flash drives:
-       175, 176, 177, 181, 182
-
-  [CF] Windows: Check support of gcc '-mno-cygwin' option in configure.
-       This option has been removed in Cygwin gcc 4.x.  Update INSTALL
-       instructions accordingly.
-
-  [CF] Increase SCSI_TIMEOUT_DEFAULT from 6 to 20 seconds to avoid
-       timeouts when a disk spins up from standby mode.
-
-  [CF] Add USB ID of AcomData 504 (OnSpec USB bridge).
-
-  [AS] Correcting manual pages (FreeBSD related)
-
-  [AS] FreeBSD: fix FTBFS on GNU/kFreeBSD (reported by derevko).
-
-  [AS] FreeBSD: Add USB autodetection to smartd DEVICESCAN directive.
-
-  [CF] Add USB ID of Myson Century CS8818, add some comments.
-
-  [CF] Return info strings from 'smart_interface::get_*()' functions as
-       'std::string' instead of 'const char *'. Static buffers are no
-       longer needed.
-
-  [SZ] FreeBSD: Fix highpoint type detection and ioctl failed for parameter
-       error.
-
-  [CF] Linux: Add USB autodetection to smartd DEVICESCAN directive.
-
-  [CF] Add USB IDs of Maxtor Basics Desktop and ISD-300A1.
-
-  [AS] Use malloc() to ensure that the read buffer lands on a single
-       page.  This avoids some bugs seen on LSI controlers under
-       FreeBSD.
-
-  [CF] Add missing help text for '-d usb*' options.
-
-  [CF] Linux: Dereference '/dev/disk/by-*/*' symlink before device type
-       autodetection.
-
-  [AS] FreeBSD: Support SATA disks attached to a SAS controller (based on
-       patch from freebsd ports tree).
-
-  [AS] FreeBSD: Added FreeBSD 8 libusb2 device autodetecion, new
-       configure check for -lusb.
-
-  [AS] FreeBSD: Added USB device autodetection and fixed -d switch behavior.
-
-  [AS] FreeBSD: Migrate os_freebsd.cpp to new interface.
-
-  [CF] Fix max number of 3ware devices, 128 devices are supported again.
-       Regression was introduced during migration to new interface.
-       Thanks to Michael Holweg for the problem report.
-
-  [CF] Windows installer: Add 'DisplayVersion' to uninstall registry key.
-
-  [MS] knowndrives.cpp updates:
-       - Marvell SSD SD88SA024BA0
-       - Fujitsu MHZ2 BH series
-       - Fujitsu MHZ2 BJ series
-       - Seagate Maxtor DiamondMax 23
-       - WD Caviar Green: Add some 32MB cache variants
-       - relax OCZ-Vertex pattern
-
-  [CF] Add USB ID of Verbatim FW/USB160.
-
-  [CF] Fix data type bug in checksum test for multi sector logs.
-
-  [CF] Add USB ID of Seagate FreeAgent Go.
-
-  [MS] Add experimental feature to log attribute values at each check 
-       cycle (ATA only), activated with the smartd option 
-       "-A PREFIX" / "--attributelog=PREFIX".
-       Introduce configure options "--enable-attributelog" and
-       "--with-attributelog=PREFIX" to enable feature by default.
-
-  [DG] [SAT] Heads up about a non backwardly compatible change
-       introduced in draft SAT-2 (sat2r8b.pdf) that will break our
-       existing SAT processing code. Action needed if change stands.
-
-  [MS] smartd.cpp: Adjust umask
-
-  [CF] Makefile.am: Remove 'uninstall-docsDATA' target to fix
-       'make distcheck' with automake 1.11. The 'make uninstall'
-       of examplescripts fails if docdir does no longer exist.
-
-  [CF] Remove 'scsiata.h'. The 'scsiata.cpp' module now implements
-       parts of 'dev_interface.h'.
-
-  [CF] smartctl: Don't report an attribute as failed if threshold is 0.
-
-  [CF] Print only one warning on checksum errors in multi sector log.
-       Remove casts from calls of checksum().
-
-  [DG] minor changes to SCSI background scan strings
-
-  [MS] knowndrives.cpp updates:
-       - Fujitsu MHW2 BJ series
-       - WD Caviar Black family
-
-  [MS] Makefile.am: Make creation of svnversion.h independent of
-       locale settings
-
-  [CF] Require to specify PORT parameter of '-d usbjmicron' if two disks
-       are connected.
-
-  [CF] smartctl: Limit default number of printed entries for
-       '-l xerror' to 8, for '-l xselftest' to 25.
-
-  [CF] smartctl: Fix number of entries in '-l xselftest' output.
-
-  [CF] Add USB IDs of a SunplusIT bridge, three WD drives, and an
-       unsupported Iomega drive.
-
-  [CF] Makefile.am: Use 'svnversion' instead of 'svn info' to get
-       the revision number. This also checks for mixed and modified
-       working copies.
-
-  [CF] Remove CVS Id strings from '-V, --version' output.
-
-  [CF] Update CONTRIBUTORS section on man pages.
-
-  [CF] Makefile.am: 'make maintainer-clean' now removes also files
-       generated by './autogen.sh'.
-
-  [CF] Invalidate 'do_release' script, it needs some rework for SVN.
-
-  [CF] Update documentation files for SVN.
-
-  [CF] Rename trunk/sm5 to trunk/smartmontools.
-
-  [CF] Print SVN revision number instead of time in version info line.
-       Get SVN revision number from svn (if available) or guess from
-       Id strings. Rename generated file to svnversion.h.
-
-  [CF] Makefile.am: Modify generation of cvsversion.h for SVN.
-
-  [GP] Convert CVS repository to SVN.
-
-  [CF] smartd: Fix size of monitor flag array from previous commit.
-
-  [CF] Makefile.am: Add missing 'megaraid.h'.
-
-  [CF] smartd: Add '!' flag to '-r' and '-R' directives. If specified,
-       message is logged as LOG_CRIT and warning mail is sent if
-       attribute normalized or raw value changes.
-
-  [CF] Replace global 'con->...' variables used for selective self-tests
-       by local variables.
-
-  [GK] Add names for some attributes used in Samsung MLC drives:
-       178-180 & 183
-
-  [CF] smartctl: Add option '-x, --xall' to print all info including
-       extended SMART logs and non-SMART info.
-
-  [CF] smartctl: Add '-l xerror,error' and '-l xselftest,selftest' to print
-       the old logs if the extended logs are not supported.
-
-  [MS] knowndrives.cpp updates:
-       - Western Digital AV-GP series
-       - Transcend Solid-State Drive and Transcend Solid-State Drive V series
-       - Seagate Momentus 5400.5 series
-
-  [CF] Disable 48-bit ATA commands for JMicron USB bridges by default
-       because these commands do not work with all devices.
-       Add '-d usbjmicron,x' to enable 48-bit commands.
-       Thanks to Alexander Shaduri for the problem report.
-
-  [CF] smartd: Don't ignore the '-n' directive when a self-test is
-       scheduled. Start the self-test later when the disk is active
-       again.
-
-  [DG] SCSI (SAS): implement '-l sasphy,reset' (reset part was stub
-       prior to this)
-
-  [DG] add 'ATA, SCSI command sets and SAT' section to smartctl.8 .
-       [SCSI] add 'number of background medium scans' field
-
-  [DG] SCSI (SAS): add '-l sasphy' and '-l sasphy,reset' into smartctl
-       to output SAS device phy information (from the Protocol specific
-       log page)
-
-  [CF] autogen.sh: Remove 'CYGWIN=check_case:strict', this does no
-       longer work on Cygwin 1.7.  Print warning if Automake version
-       cannot handle case insensitive filesystems.
-
-  [CF] Remove '#define TRUE/FALSE', use 'bool' and 'true/false'.
-
-  [CF] Add 'options' parameter to SCSI printing routine. Move global
-       'con->...' smartctl variables to 'options' parameters of
-       printing routines.
-
-  [CF] Windows: Remove outdated entry about undocumented system calls
-       from WARNINGS file.
-
-  [CF] Print General Purpose Logs even if GPL feature bit is missing.
-       Needed for some older disks which implement READ LOG EXT but
-       do not report the GPL feature set.
-       Change order of the extended log outputs ('-l xerror',
-       '-l xselftest', '-l sataphy'). Extended logs are now printed
-       before their old versions.
-
-  [CF] autogen.sh: automake 1.10.2 and 1.11 are OK.
-
-  [CF] Fix syntax error in prototype of 'safe_snprintf()'.
-       Thanks to Alexander Shaduri for bug report and patch.
-
-  [DG] SCSI: Fetch load-unload cycle counts.
-
-  [CF] Windows: Add Win-7 and Win2008 to get_os_version_str().
-
-  [CF] smartd: Fix '-M test' directive in conjunction with '-s' option.
-       Thanks to Matthias Becher for the problem report.
-
-  [MS] knowndrives.cpp updates:
-       - Add Seagate Barracuda 7200.12 series
-       - Add Seagate Momentus 5400.4 series
-       - Add Hitachi Deskstar 7K1000.B series
-       - Add Transcend SSD TS32GSSD25-M
-       - Add OCZ Vertex 1199
-
-  [CF] knowndrives.cpp updates:
-       Add Samsung S250 series.
-       Add '-v 198,increasing' to Samsung P80.
-       Replace '#if/#endif' by comment to fix configure option
-       '--enable-drivedb'.
-
-  [CF] knowndrives.cpp update:
-       Add Seagate 7200.11 with 'CC' firmware which is unaffected
-       by the bug. Thanks to Bas Mevissen for the patch.
-
-  [CF] Replace global 'con->...' variables used for drive presets
-       by local variables.
-
-  [CF] Simplify '-v' vendor attribute option parsing.
-       Add '-v 197,increasing' and '-v 198,increasing' options
-       to specifiy that an uncorrectable count is never reset.
-       This modifies the printed attribute names and smartd's
-       default setting of '-C' and '-U' directives.
-       Both '-v' options can also be preset in the drive database.
-
-  [CF] Add '+' modifier to smartd '-C' and '-U' directives.
-       If specified, a warning is only printed if the raw value
-       increases.
-
-  [CF] Add smartctl option '-l xselftest[,NUM]' to print
-       ATA SMART Extended Self-test Log (GP Log 0x07).
-
-  [CF] Add experimental option '-d usbsunplus' for drives behind
-       SunplusIT USB bridges. Tested on WinXP with SPIF215(?) in
-       TrekStor DataStation maxi m.u.. Many thanks to SunplusIT
-       tech support for providing the required information.
-
-  [CF] Windows: Provide a non-console version of smartctl.exe
-       as smartctl-nc.exe. This prevents that a new console is
-       opened when smartctl is run from a GUI program with
-       stdio redirected.
-       Used by GSmartControl (http://gsmartcontrol.berlios.de/).
-
-  [CF] Remove support for platforms without getopt_long() in
-       smartctl.cpp and smartd.cpp. If getopt_long() is missing,
-       ./configure aborts with an explanatory message.
-       For now, short option help texts are only removed from
-       os_linux.cpp and os_win32.cpp. HAVE_GETOPT_LONG is still
-       defined in config.h.
-
-  [CF] Add smartctl '-d test' option to print the result of the
-       device type detection.
-
-  [CF] Enhance USB device type autodetection, use bcdDevice if known.
-       Add Cypress CY7C68300B/C (AT2LP) to the table.
-
-  [CF] Linux: Add experimental USB device type autodetection.
-       Uses USB ID info found through symlink "/sys/block/sdX/device".
-
-  [CF] Windows: Add experimental USB device type autodetection.
-       Uses WMI command line tool 'wmic' to query USB ID.
-
-  [CF] Add function smart_interface::get_usb_dev_type_by_id() to map
-       USB vendor:product IDs to '-d type' names. Can be used by
-       platform dependent layer to autodetect USB devices if ID of
-       USB bridge is known.
-
-  [CF] smartd: Log changes of self-test execution status if
-       '-l selftest'is specified.
-
-  [CF] knowndrives.cpp update:
-       Samsung SpinPoint F1 RE series
-
-  [MS] knowndrives.cpp update:
-       Seagate Momentus 5400.6 series
-
-  [CF] Add forgotten SCSI sense checks to class usbjmicron_device.
-
-  [CF] Add new SMART STATUS check command for JMicron USB bridges.
-       Should support also older chip versions and prevents a race
-       condition.
-
-  [CF] Windows: Fix win_scsi_device::scsi_pass_through() for single byte
-       data transfers. Required for JMicron SMART STATUS check.
-
-  [MS] knowndrives.cpp update:
-       Add Hitachi Travelstar C4K60 family (1.8" slim drives)
-
-  [MS] Workaround for huge raw values of attribute 9, needed
-       for Hitachi Travelstar C4K60. For the Power_On_Minutes case,
-       clip the display to 4 bytes and show the remaining part,
-       if existent, in parens.
-
-  [CF] Add experimental option '-d usbjmicron[,PORT]' for drives
-       behind JMicron USB bridges. Tested on WinXP with JM20336 in
-       AixCase AIX-ESU35CD. Many thanks to JMicron tech support
-       for providing the required information.
-
-  [MS] knowndrives.cpp update:
-       Add WD Caviar Green 8MB and 32MB cache variants, stretch to 2TB.
-  [CF] knowndrives.cpp updates: Add more entries for Samsung P80 disks
-       with old and unknown firmware. Remove old entries which would
-       match any new Samsung model reusing old firmware version number.
-
-  [CF] Windows: Add a workaround for missing multi-sector support
-       for ATA READ LOG EXT command.
-
-  [CF] Fix Extended Comprehensive Error Log index base.
-       Add workaround for Samsung disks using reserved byte as index.
-
-  [CF] knowndrives.cpp updates: Update bug warnings for
-       Seagate 7200.11, ES.2 and DiamondMax 22. Add new entries
-       for fixed firmware versions.
-
-  [CF] Add smartctl option '-l xerror[,NUM]' to print
-       ATA SMART Extended Comprehensive Error Log (GP Log 0x03).
-
-  [MS] knowndrives.cpp update:
-       Added remaining WD Scorpio Blue SATA II drives
-
-  [CF] Minor fix to remove ID 0 from 'smartctl -l sataphy ...' output.
-
-  [CF] knowndrives.cpp updates: Add warnings about possible firmware
-       bugs to Seagate 7200.11, ES.2 and DiamondMax 22 entries.
-
-  [CF] knowndrives.cpp updates: Add Samsung SpinPoint F1 series.
-
-  [CF] Windows: Fix return value of scsi_pass_through(). Regression
-       was introduced during migration to new interface. SAT over USB
-       now works on XP (both '-d sat,12' and '-d sat,16').
-
-  [MS] knowndrives.cpp updates:
-       - Added Western Digital RE2-GP family
-       - Added Hitachi Travelstar E5K160 family
-       - Allow uppercase variants of Hitachi 5K160 drives
-
-  [CF] Fix smartctl crash on '-l directory,[gs]'. Allow to override
-       missing GPL feature bit or missing log dir entry with
-       '-T permissive' option.
-
-  [SZ] os_freebsd.cpp, os_freebsd.h updates:
-       Support HighPoint RocketRAID controller under FreeBSD
-
-  [MS] knowndrives.cpp updates:
-       - Added Western Digital RE3 32MB cache variants
-       - Added WD Caviar Green 32MB cache variant (WD10EADS)
-       - Added WD Scorpio Black family
-
-  [DG] Accept half healthy (and half unhealthy) indication from the
-       SMART RETURN STATUS. This makes allowance for SAT implementations
-       (e.g. via USB) that truncate the SCSI sense buffer to 18 bytes.
-       This truncation causes the SMART RETURN STATUS indication to be
-       half health or unhealthy. If the half indication is used, then
-       warn if '-r ioctl' is given.
-
-  [MS] knowndrives.cpp updates:
-       - Added Apple SSD
-       - Added Seagate U8 family
-
-  [DL] os_freebsd.cpp:
-       Added support for CHECK_POWER_MODE and WRITE_LOG commands
-
-  [MS] knowndrives.cpp update:
-       There seem to exist WD Raptors with SATA II interface, add them.
-
-  [MS] knowndrives.cpp updates:
-       - Added remaining Seagate Barracuda 7200.11 drives
-       - Added HP 1TB SATA disk
-
-  [MS] knowndrives.cpp updates:
-       - Added Maxtor 92040U6 (DiamondMax Plus 6800)
-       - Added Seagate Maxtor DiamondMax 21 500GB version
-       - Added QUANTUM FIREBALLlct15 22
-       - Added QUANTUM FIREBALL CR6.4A
-       - Added QUANTUM FIREBALLP LM20.4
-       - Added SUN branded Toshiba MK4019GAX
-       - Added TOSHIBA MK1016GAP and relatives: MK1[05]1[67]GAP
-       - Added Western Digital WD800AB and WD2500AB
-       - Some Hitachi 7K160 drives have garbage at end of name: permit it
-
-  [CF] Add smartd '-n powermode,N' directive parameter to limit the
-       number of skipped checks. Thanks to Michal Hlavinka for the patch.
-
-  [MS] knowndrives.cpp updates:
-       - Added Hitachi Endurastar J4K30/N4K30
-       - Added Hitachi Travelstar 4K120 series
-       - Some Hitachi 7K80 drives have garbage at end of name: permit it
-       - IBM Travelstar 6GN series
-
-  [MS] knowndrives.cpp updates:
-       - Added Quantum Fireball ST4300A
-       - Added Asus-Phison SSD (solid state disk)
-       - Added Seagate DB35.3 Series
-       - Added remaining disks of the Seagate SV35.2 Series
-
-  [MS] Fix trivial compile error with "-pedantic"
-
-  [MS] Workaround for huge raw values of Reallocated_Sector_Ct and
-       Reallocated_Event_Ct for newer Fujitsu disks (only the lower
-       16 bits seem to be meaningful). Clip the display to 16 bits
-       and show the remaining part, if existent, in parens. Patch by [CF].
-
-  [CF] smartd DEVICESCAN: Fix autodetection of SAT devices.
-       Thanks to Stanislav Brabec for bug report and testing.
-
-  [MS] knowndrives.cpp update:
-       Convert file to full string regex: remove "^$" from pattern
-
-  [MS] knowndrives.cpp updates:
-       - Added Seagate Momentus 5400 PSD series (hybrid drives)
-       - Added Seagate Momentus 7200.3 series
-       - Added Hitachi Deskstar 7K250 (SUN branded)
-       - There are Hitachi Travelstar 5K250 drives with capital "HITACHI"
-       - Correct regex for Maxtor VL 30 drives
-
-  [CF] Add configure options '--enable-savestates' and
-       '--with-savestates=PREFIX' to enable smartd persistence
-       ('-s' option) by default.
-
-  [CF] smartd: Add '-s ([cnr]/../.././..)' directive to run scheduled
-       selective self-tests. Useful to perform full tests of large disks
-       not running 24x7.
-
-  [CF] Allow to read local drive database entries from optional file
-       '${sysconfdir}/smart_drivedb.h'.
-       Add configure options '--enable-drivedb' and '--with-drivedbdir=DIR'.
-       If specified, drive database is read from '${drivedbdir}/drivedb.h'.
-       (default '${prefix}/share/smartmontools/drivedb.h'). This file
-       is build from knowndrives.cpp.
-
-  [MS] knowndrives.cpp updates:
-       - Added 640GB variants of Western Digital AAKS and AACS drives
-       - Added Western Digital AV ATA family
-       - Added 160GB variant of Hitachi P7K500
-       - Added 500GB variant of Hitachi 7K1000
-       - Some cleanup for Quantum disks
-       - Added Seagate Maxtor DiamondMax 22 family
-
-  [CF] Use full string match for regexp in drive database.
-
-  [CF] Add option '-d sat+TYPE' to use SAT with controllers which
-       require option '-d TYPE'. Should work with '-d sat+megaraid,N'.
-       As a side effect, '-d usbcypress+TYPE' is also supported.
-
-  [CF] Add parser to read drive database from a file. Add '-B' option
-       to smartctl and smartd to specify database file name. File syntax
-       is identical to the C/C++ syntax used to inialize the internal
-       database array.
-
-  [CF] New syntax for drive database: Specify presets by strings
-       with '-v' and '-F' options. Use empty strings instead of NULL.
-
-  [JPH] Added Linux support for viewing disks behind MegaRAID
-       controllers
-
-  [CF] smartd: Improve min/max temperature recording in conjunction
-       with '-s' option.
-
-  [CF] Add a wrapper class for FILE *.
-
-  [CF] smartd: Add experimental support for state persistence (ATA only).
-       Add option '-s' to specify path prefix for state files.
-       Rework scheduled self-test detection to support persistence.
-       If any test schedules are within downtime, the highest priority
-       test is run after next startup.
-
-  [CF] Remove casts from 'format_ata_string()' calls.
-
-  [CF] Minor changes to fix errors and warnings from Cygwin gcc 4.3.0.
-
-  [CF] smartd: Remove SCSITIMEOUT code. According to smartd.h 1.54 CVS log
-       from 2003-10-27, it did never work.
-
-  [CF] Remove dependencies ataprint.cpp and scsiprint.cpp from smartd.
-       Move common ATA functions from ataprint.cpp to atacmds.cpp.
-       Module scsiprint.cpp was apparently never used in smartd.
-
-  [CF] Move smartd local declarations from smartd.h and utility.h to
-       smartd.cpp. Remove smartd.h.
-
-  [CF] Fixed extra '\n' in "Offline data collection status" output.
-       Thanks to Alexander Shaduri for the patch.
-
-  [CF] smartd: Separate device configuration data from device state data.
-       Use references instead of pointers for configuration and state data.
-
-  [CF] Add const-correctness and static to ATA support functions.
-
-  [CF] Add a wrapper class for regex.
-
-  [CF] Simplify 'create_vendor_attribute_arg_list()'.
-
-  [CF] smartd: Rework of main data structures. Remove explicit memory
-       allocations, use STL containers and structs with value semantics
-       instead. Remove old malloc/free based memory management helper
-       functions unless old interface is still in use.
-
-  [CF] Linux: Cleanup device scan, remove name list, create objects directly.
-
-  [CF] Linux: Cleanup smart_device::open(), type strings are no longer used.
-
-  [CF] Remove CONTROLLER_* defines and variables unless old interface
-       is still in use.
-
-  [CF] Linux: Migrate 3ware interface to 'ata_pass_through()'.
-       Multi-sector support is not complete yet. 48-bit commands
-       possibly work.
-       WARNING: Not tested, please review code before first test!
-
-  [CF] Linux: Migrate os_linux.cpp to new interface.
-
-  [CF] Add direct access to 16-bit registers in 'ata_in/out_regs_48bit'.
-
-  [CF] Add 'ata_cmd_is_ok()' parameter check,
-       remove 'ata_pass_through_28/48bit()' functions.
-
-  [CF] Add CVS date/time from cvsversion.h to man pages also.
-
-  [CF] Add configure option '--with-os-deps='os_module.o ...' to specify
-       alternate OS interface modules. Useful for testing during migration.
-
-  [CF] Remove declarations of 'optarg', 'optind', ..., include <unistd.h>
-       instead. This fixes 'auto-importing' linker warnings on Cygwin.
-
-  [CF] Add '-l sataphy[,reset]' to print SATA Phy Event Counters.
-
-  [CF] Add '-l gplog,ADDR[,FIRST[-LAST|+SIZE]]' and '-l smartlog,...'
-       to dump any log page accessible via GP or SMART read log commands.
-
-  [CF] Enhance '-l directory' to print both GP and SMART Log directories.
-       Add '-l directory[,gs]' modifiers to select GP or SMART log.
-       Enhance 'ata_cmd_in' parameter struct for 48-bit commands.
-
-  [CF] Windows: Add full ATA pass through support including 48-bit commands.
-
-  [CF] Windows: Migrate os_win32.cpp to new interface.
-
-  [CF] SAT: Add full ATA pass through support including 48-bit commands.
-
-  [MS] knowndrives.cpp update
-       - Added FUJITSU MHZ2250BS G2 and family
-
-  [MS] knowndrives.cpp updates
-       - Added Maxtor DiamondMax 60 94098H6
-       - Added Maxtor DiamondMax 1280 84000A6 and family
-       - Added Maxtor DiamondMax VL 30 31536H2 (ATA100) and family
-       - Some Seagate Barracuda 7200.9 have garbage at end of name: permit it
-       - Added Seagate Barracuda ATA ST320430A and family
-       - Regression from previous checkin: add WD RE2 WD...0ABYS again
-       - Added WD RE3 WD5002ABYS and family
-       - Added Quantum Fireball CR13.0A
-       - Added Hitachi Travelstar 5K250 HTS542525K9SA00 and family
-       - Added WD AC420400D and add whole range of AC.... which
-           have 5400rpm or higher (i.e. PIO-only drives omitted)
-
-  [MS] knowndrives.cpp updates
-       - WD: Separated entries for EIDE and SATA
-       - WD: Separated entries for Caviar SE, SE16, RE, RE2
-       - WD Named: WD Caviar AC series
-       - WD Renamed: WD Caviar RE/RE2 -> WD RE/RE2
-       - WD Renamed: WD Caviar SE/SE16 WD....AA[A-Z][A-Z] -> WD Caviar Blue
-       - WD Renamed: WD Scorpio WD....BEV[A-Z] -> WD Scorpio Blue
-       - Added WD Scorpio Blue WD3200BEVT
-       - Added WD RE2 WD5001ABYS and family
-       - Added WD Caviar Green WD5000AACS and family
-       - Added WD VelociRaptor WD3000GLFS and family
-       - Added Seagate Barracuda ES.2 ST31000340NS and family
-       - Added Samsung SP80A4H
-       - Added Maxtor DiamondMax 21 STM3160215AS and STM3320620AS
-       - Added Seagate Barracuda 7200.7 ST380819AS
-       - Added Maxtor DiamondMax 10 6B100P0
-       - Added Seagate SV35.2 Series
-       - Added Fujitsu MHY2120BH and family
-       - Added Fujitsu MHW2080BH PL (PL variant)
-       - Added Toshiba MK3252GSX and family
-
-  [BA] Fix smartctl bug: when running in silent mode '-q errorsonly'
-       do not print the Selective Self-test log.  Any errors will
-       ALREADY appear in the SMART Self-test log.
-
-  [CF] Add missing 'const' and other minor fixes to prevent gcc warnings.
-
-  [OB] Added information message about supported Areca firmware versions.
-       It's displayed in case the ATA device identification fails.
-
-  [CF] Add configuration file for Doxygen.
-
-  [CF] Add new object oriented interface to access ATA and SCSI devices.
-       smartctl and smartd are modified to use the new classes in
-       'dev_interface.{h,cpp}'. The template class in 'dev_tunnelled.h'
-       is used in 'scsiata.cpp'. The code in 'dev_ata_cmd_set.{h,cpp}'
-       supports migration from old function 'ata_command_interface()'.
-       All existing 'os_*.cpp' modules should still work without any changes.
-       The required adapter classes from 'dev_legacy.cpp' are automatically
-       added by configure if necessary.
-
-  [BA] Updated smartd and smartctl and smartd.conf man-page documentation
-       to reflect support for Areca SATA RAID controller cards.
-
-  [OB] Added support for Areca controllers to smartd. Extensive tests
-       as well as documentation are still pending however.
-
-  [OB] Implemented device locking for Areca controllers in smartctl
-
-  [BA] Fixed selective self-test code.  Data structure revision number
-       may be != 1 if no selective self-test has ever been run.  Host
-       MUST set this value (at least at the first selective self-test
-       instance).  Thanks to Curtis Stevens of WDC for clarification.
-
-  [MC] usbcypress autodetection
-
-  [BA] Starting to commit Areca code.  For now just smartctl.
-       More changes and documentation coming soon.
-       Need Areca firmware version 1.45 dated 10 June 2008 or later.
-       May need changes in opening /dev/sg and file locking.
-       Many thanks to Hank Wu!
-
-  [CF] smartd: Fix too small name buffer for 3ware with >100 devices.
-
-  [JH] now C++ Support for QNX Target
-       already tested for QNX 6.3.2 on x86 and armle target
-   
-  [CF] Allow to set BUILD_INFO from make command line.
-
-  [CF] Windows: Add MSVC8 support, remove MSVC6 project files.
-
-  [MC] Add usbcypress device support for smartd.
-
-  [CF] Add output of latest CVS date/time stamp to version info.
-       New file cvsversion.h is generated by Makefile.
-       Move formatting of version info to utility.cpp.
-
-  [AR] Fix bug in 3ware node creation where nodes would be created
-       then deleted, then recreated.
-
-  [BA] Add missing CCISS cvs version tags to '-V' printouts.
-
-  [TS] Linux: Ensure the 3ware device nodes are created with a correct
-       SELinux security context.
-
-  [AR] Add support for up to 128 devices on 3ware controllers.
-
-  [CF] C++: Added new main() with exception handlers, replaced
-       exit(x) with throw(x), removed global variable 'exitstatus'.
-       Necessary for future changes, because exit() does not call
-       any destructors.
-
-  [SS] FreeBSD: plug file descriptor leak in smartd (only happens with
-       CISS devices).  Reported by Vadim Ostranitsyn.
-
-  [SS] FreeBSD: allow smartctl to interact with SCSI /dev/pass devices,
-       thus enabling it to work with RAID controllers that expose disks
-       via these devices.  From scottl@ via FreeBSD ports.
-
-  [MC] Add usbcypress device support for smartctl.
-
-  [KS] INSTALL on Solaris: updated description to use C++ compiler.
-
-  [KS] configure.in on Solaris: added options for Sun's compiler to
-       suppress trivial warnings.
-
-  [KS] configure.in on Solaris: added direction to search suitable
-       libraries for getaddrinfo().
-
-  [TS] smartd on Linux: remove forgotten return from deviceopen();
-       SCSI device descriptors had the FD_CLOEXEC flag unset.
-
-  [CF] Added 'const' to avoid warning on depreciated string constant
-       to 'char *' conversion.
-
-  [CF] autogen.sh: automake 1.10.1 is OK. Updated message texts.
-
-  [BA] removed smartmontools.spec file (now in CVS Attic).  This
-       was not being used by RH or FC anyhow, and was out of
-       date and not maintained.
-
-  [BA] smartd on Linux: sets FD_CLOEXEC on the opened device file
-       descriptor.  The descriptor is otherwise leaked to other
-       applications (mail sender) which may be considered a security
-       risk and may result in AVC messages on SELinux-enabled systems.
-       Thanks to: Tomá Smetana" <tsmetana@redhat.com>.
-
-  [BA] smartd: when sending email, to gather information about the
-       host for the body of the email, eliminate gethostbyname()
-       in favor of the IPv6-friendly function getaddrinfo() if the
-       latter is available.  Info may be found here
-       http://udrepper.livejournal.com/16116.html
-       and here
-       http://people.redhat.com/drepper/userapi-ipv6.html
-       Thanks to: Tomá Smetana" <tsmetana@redhat.com>.
-
-       Smartmontools developers: please check that smartd still LINKS
-       properly on your systems.
-
-  [BA] Fix ugly syntax bug in os_freebsd.cpp.  How did this go
-       undetected for so long??
-
-SMARTMONTOOLS STABLE RELEASE 5.38 2008/03/10
-
-  [KS] Solaris/x86: modified configure.in for Sun's compiler.
-
-  [BA] smartd.initd.in addition from Erwan Velu <erwan@seanodes.com>
-
-  [BA] smartd fixes:
-
-       - On Linux, DEVICESCAN now automatically recognizes SATA devices
-         behind libata, and SATA devices behind the Marvell driver, and
-         treats them correctly.
-
-       - On Linux, a '-d sat' or '-d marvell' is automatically added
-         if libata or the marvell driver are recognized behind a SCSI
-         device type
-
-  [SS] (Maybe) fix attribute autosave in FreeBSD.
-
-  [SS] Major NetBSD-specific bugfixes:
-       - handle actual SCSI and ATA errors and not only ioctl() errors;
-       - set up I/O request properly for AUTO_OFFLINE and AUTOSAVE commands (inspired by
-         similar change in os_freebsd.cpp);
-       - handle AUTO_OFFLINE and AUTOSAVE like STATUS_CHECK (like os_linux.cpp does).
-
-  [GG] add kfreebsd gnu support to configure.in
-
-  [BA] Fix auto-offline support in FreeBSD.  Thanks to
-       Cyrus Rahman <crahman@gmail.com> for the patch, and
-       Eduard Martinescu for blessing it.
-
-  [DG] smartd re-opens "SCSI" devices as ATA devices if a SAT layer is
-       detected (smartd bug IMO). In Linux this upsets scsi generic
-       device nodes (e.g. /dev/sg0). Detect the re-open in os_linux.cpp
-       and set the O_RDWR flag (ATA uses the O_RDONLY flag).
-
-  [CF] Drive database: Added Fujitsu MHW2 BH, Maxtor DiamondMax 17, 20, 21,
-       Hitachi Travelstar 4K40, 5K120, 7K200, Deskstar 7K160, T7K500,
-       T7K1000, Toshiba 1.8", Seagate Momentus 5400.3, 5400.3 ED, 7200.2,
-       Barracuda 7200.11 and ES.
-       Updated Toshiba 2.5", Seagate Barracuda 7200.9 and 7200.10.
-       Added missing "(Hitachi )?" to Travelstar entries.
-
-  [CF] Drive database: Added several Western Digital Caviar and Scorpio
-       drives, added Caviar RE EIDE family.
-
-  [CF] Drive database: Added Samsung P80 series with *-25 firmware.
-
-  [CF] Replaced 'head [-n] -1' by 'sed 1...' in autogen.sh to avoid
-       portability issues.
-
-  [BA] Fixed autogen.sh script so that it uses 'grep -n 1' if 'grep -1'
-       fails.  Needed for Mac OS X 10.4. Uck.
-  [CF] Windows: Added IOCTL_STORAGE_PREDICT_FAILURE. This allows access
-       to ATA SMART status and data if other calls do not work.
-       Thanks to Jaroslaw Kowalski for pointing this out.
-       Added support to use this function without admin rights.
-
-  [CF] Added ATA-8 revision 4c message text.
-
-  [CF] Added compiler.h to cciss_ioctl.h header check to prevent
-       configure warning.
-
-  [SS] DragonFly support added (using os_freebsd code; untested).
-
-  [CF] smartctl: Fixed ATA identify byte swapping issue on big-endian
-       platforms. This regression was introduced by the change for
-       '-F swapid'. Thanks to Matthew Butch for bug report and testing.
-
-  [DG] SAT/SCSI: Improve SAT error processing code. Aborted commands from
-       ATA devices (typically because SMART was disabled) were not being
-       properly detected.
-
-  [GG] smartd: wait for the pid file to show up, return an error if it doesn't
-
-  [JH] fix bad return code (get STATUS) for QNX Part
-
-  [JH] initial porting to QNX Neutrino 6.3.2
-       need at this time a prerelease devb-eide driver and libcam.so.2
-       only tested for X86 Target, but devb-eide and lobcam.so.2 available for X86/ARM
-       the officional driver coming soon with the next QNX release
-       create two new source files os_qnxnto.[c..h]
-
-  [CF] smartd: Added option '-n, --no-fork' so that smartd works
-       better with modern init methods. Thanks to Enrico Scholz
-       for the patch from 2005-12-24.
-
-  [CF] Windows: Improved ATA/SCSI device type detection and
-       DEVICESCAN. This also fixes a regression in 3ware DEVICESCAN.
-
-  [CF] smartd: Don't start self tests in first pass to avoid
-       performance problems during boot.
-       https://bugzilla.novell.com/show_bug.cgi?id=192591
-
-  [CF] Fixed regression in SMART STATUS command on Win9x/ME.
-
-  [BA] Fixed 3ware issue with new controllers.  Documentation said
-       that one could address up to 24 disks on a single controller,
-       but in fact one was limited to 16 disks.  This is now fixed:
-       up to 32 disks can be addressed.  Thanks to Adam Radford.
-
-       NOTE1: I have patched the Linux and FreeBSD code but not
-       modified the Win32 code (it already supports up to 32 disks).
-
-       NOTE2: NOT TESTED ON LINUX.  Do not use this on a production box!
-       I will remove this NOTE2 as soon as some positive test
-       reports are recieved.
-
-       NOTE3: NOT TESTED ON FREEBSD. Do not use this on a production box!
-       I will remove this NOTE3 as soon as some positive test
-       reports are recieved.
-
-  [CF] Windows installer: Added explorer drive menu, CMD window,
-       UBCD4Win plugin, smartd service update and other minor
-       improvements.
-
-  [CF] Windows: Modified drive letter handling for explorer drive
-       context menu: try SCSI if type is unknown, allow 'X:\.' syntax.
-
-  [CF] Windows: Added automatic ATA/SCSI device type detection and
-       SCSI device scanning. The device names '/dev/sdX' and
-       '/dev/pd<n>' now work for both ATA and SCSI disks.
-
-  [CF] smartctl: Added ability to parse '-r ataioctl,2' output from
-       stdin ('-') and simulate the ATA commands for testing purposes.
-
-  [BA] SMART Attributes: added 187, 189, more accurate name for 190.
-
-  [CF] Windows: Added drive letters 'X:' as alternate disk device names.
-
-  [CF] smartctl: Added '-F swapid' to fix ATA identify string byte
-       ordering. Added '-q noserial' to suppress serial number output.
-
-  [CF] Windows: Added '/dev/n?st<n>' as alternate device names for SCSI
-       tapes. These names are also used by Cygwin's /dev emulation layer.
-       Thanks to Corinna Vinschen (Cygwin project lead) for pointing this
-       out. 
-
-  [CF] Windows: Added IOCTL_SCSI_MINIPORT_*SMART* for commands not handled
-       properly by SMART_IOCTL in disk class driver. This allows to use
-       READ_LOG, WRITE_LOG and ABORT_SELFTEST even if the driver does not
-       support ATA_PASS_THROUGH.
-
-  [CF] Added ATA-8 revision 4, fixed WRITE LOG '-r ioctl' output.
-
-  [BA] Updated smartctl and smartd so that they can be used with the latest
-       3ware controllers which have 24 ports.  Also updated docs.
-       Thanks to Tim Bell at CERN.
-
-  [GG] bit 4 in smartctl's return code might be set even when the dist check
-       didn't return "DISK OK"
-
-  [CF] Drive database: added '-F samsung3' for Samsung P80 firmware
-       BH100-35.
-
-  [SS] Applied patch from Dean Bennett to fix scheduled tests on 
-       Highpoint RAID controllers.
-
-  [BA] Added patch from Tejun Heo http://thread.gmane.org/gmane.linux.ide/13222/focus=13235
-       to fix broken auto-offline and auto-save via libata.  Very clean fix: does it
-       "the right way".  Thanks Tejun!
-
-  [CF] Added message text for ATA-7 self-test execution status 8
-       ("... handling damage").
-
-  [GG] cciss: support more than 16 disks (patch taken from
-       http://cciss.sourceforge.net/smartmontools_cciss_more_than_16_drives.patch
-       and adjusted for smartd)
-
-  [DG] Solaris: [SCSI] add USCSI_RQENABLE flag to uscsi pass-through so
-       sense buffer is made available. Expand reporting at this level.
-
-  [GK] Darwin: Improve handling of powered-down drives.
-
-  [SS] CCISS physical drive enumeration method changed (incompatibly).
-
-  [CF] Fixed smartd crash on missing '-s' directive argument.
-
-  [SS] Support CCISS on FreeBSD (kernel source is required until FreeBSD PR 109813
-       is fixed).
-
-  [DG] SCSI/TAPE: some IBM tape drives don't react properly to a LOG
-       SENSE with an allocation length of 4; work around for that case.
-
-  [CF] Applied Guido's patch to fix CCISS LUN array bounds check
-       (openSUSE bug #239956) and remove trailing spaces in
-       os_linux.cpp.
-
-  [CF] Fixed 64-bit compilation issue in SCT status struct.
-
-  [DG] SAT/SCSI: make real SCSI disks visible to DEVICESCAN in
-       smartd again.
-
-  [CF] Fixed check of SCT temperature table size.
-
-  [CF] Added ATA-8 draft revisions, added SCT status format 3.
-
-  [CF] Drive database: added Samsung T166 series.
-
-  [CF] ATA: Added ',p' option for '-t scttempint,N' to make
-       setting persistent.
-
-  [CF] ATA: Added '-t scttempint,N' option to set SCT temperature
-       logging interval.
-
-  [CF] ATA: Added '-l scttemp[sts,hist]' options to print disk
-       temperature information and history table provided by
-       SMART Command Transport (SCT) Feature Set.
-
-  [CF] ATA: Added '-t selective,{redo,next,cont}' commands to
-       perform tests based on the last ranges still stored on
-       disk. Added 'N+SIZE' and 'N-max' format for LBA range
-       specification.
-
-  [CF] Added Min/Max Temperature format used in attribute 190 of
-       recent Maxtor disks (DiamondMax 20).
-
-  [CF] Linux: Added check for <linux/cciss_ioctl.h> to allow build
-       (without CCISS support) also when this file is missing.
-
-  [CF] Added -F samsung3 option to correct firmware bug reporting
-       completed self-tests as still in progress. Thanks to Manfred
-       Schwarb for the patch.
-
-  [CF] Added missing const specifiers (undetected by gcc 3.4 and 4.X)
-       to fix compilation with gcc 2.X.
-
-  [CF] Linux: compile fix for SuSE, config.h must be included first.
-
-smartmontools 5.37 Experimental Release
-
-  [CF] Windows: Added alternate method for (limited) monitoring of
-       3ware controllers by parsing the output of CLI or 3DM.
-       Either "tw_cli" can be run internally ("/dev/tw_cli/cx/py"),
-       or data can be read from standard input ("/dev/tw_cli/stdin")
-       or clipboard ("/dev/tw_cli/clip").
-
-  [DG] Remove linux specific libata detect code; rely on general SAT
-       code. smartd should now generate a sensible log message for
-       ATA devices behind a SAT layer on all architectures.
-
-  [BA] Increased max line length MAXLINELEN for /etc/smartd.conf from
-       128 to 256 characters to handle long strings in
-       /dev/disk/by-id.  Thanks to Martin Krafft.
-
-  [PW] Drive database: added missing drives from Seagate Momentus 5400.2
-       family
-
-  [BA] Finished Christian's fix (next item below) by removing
-       LINUX_86_64 hack from configure.in.
-
-  [CF] Fixed inclusion of PRI?64 macros from inttypes.h.
-
-  [CF] Windows: Added WRITE LOG to support selective self tests.
-
-  [CF] Fix selective self test log revision number if '-T permissive'
-       is specified (Tested with Samsung HD401LJ).
-
-  [CF] Windows: Fixed int64 printf format for MinGW runtime.
-
-  [PW] Drive database: added Seagate Barracuda 7200.10 family, Seagate
-       Momentus 42 family, Maxtor DiamondMax 60 ATA 66 family, Maxtor
-       DiamondMax 60 ATA 100 family, and Western Digital Caviar Serial
-       ATA family
-
-  [PW] Drive database: added missing drives from Seagate Barracuda
-       7200.9 family, Seagate Barracuda 7200.7 family, Seagate Momentus
-       7200.1 family, Toshiba 2.5" HDD family (80 GB and above), Western
-       Digital Caviar RE Serial ATA family, Hitachi Deskstar 7K80 family,
-       and Maxtor DiamondMax 4320 Ultra ATA family
-
-  [BA] Linux: compile fix for SuSE.  Check for existence
-       of linux/compiler.h and include in os_linux.h if
-       present.  Thanks to SB.
-
-  [BA] smartd: DEVICESCAN will now pick up SATA/SAT devices
-       attached to a SCSI device tree via SAT translation.
-       Note: this is a bit of a hack.  I will document it once
-       I know if this needs to be Linux only or can have more
-       general application.
-
-  [BA] Added a couple SATA commands to the tables -- thanks DG!
-       Phil -- how about going through and systematically adding
-       these new commands to atacmdnames.cpp?
-
-  [BA] Linux s86_64: get rid of some compiler warnings on
-       x86_64 Linux systems.
-
-  [CF] Windows: Added missing support for READ_LOG, ABORT_SELFTEST
-       and CHECK_POWER_STATE for 3ware 9000 controllers. Thanks to
-       Greg de Valois for implementing this new ioctl in the driver.
-
-  [PW] Drive database: added Seagate NL35 SATA family.  Thanks to Kai
-       Harrekilde-Petersen for providing a patch.
-
-  [DG] [SCSI, Windows] add SPT interface for NT and later. New device
-       names are "pd<n>", "sd<l>" and "tape<n>".
-
-  [PW] Drive database: added Western Digital Scorpio family, Fujitsu MHV
-       family, Maxtor MaXLine Pro 500 family, and Maxtor DiamondMax 11
-       family
-
-  [PW] Drive database: added missing drives from Toshiba 2.5" HDD
-       (30-60 GB) family, Maxtor DiamondMax 10 family, Seagate Barracuda
-       7200.8 family, Fujitsu MHT family, and Maxtor DiamondMax Plus 8
-       family
-
-  [SB] Added examplescripts/Example4 using powersave-notify.
-
-  [SB] More temperature monitoring examples in smartd.conf with DEVICESCAN.
-
-  [SB] Minor improvements of SuSE part of init script.
-
-  [CF] Drive database: added Samsung P80 series, P120 series, SP8004H
-       and T series.
-
-  [GG] Add CCISS (Compaq Smart Array Controller) support with contributions
-       from Praveen Chidambaram, Douglas Gilbert, Guido Guenther and Frédéric
-       BOITEUX
-
-  [PW] Drive database: added Hitachi Deskstar T7K250 and Hitachi
-       Deskstar 7K500 series.  Thanks to L. J. Wu for providing a
-       patch
-
-  [PW] Drive database: added Maxtor MaXLine III family, Seagate U7
-       family, Seagate ST34321A, FUJITSU MHM2060AT, FUJITSU MHT2040AS,
-       Western Digital Caviar SE16 family, IBM Travelstar 4GT family,
-       QUANTUM FIREBALLP KA9.1, QUANTUM FIREBALL SE4.3A, TOSHIBA
-       MK1032GAX, TOSHIBA MK4026GAX
-
-  [PW] Drive database: added missing drives from Western Digital Caviar
-       SE (Serial ATA) and WD Raptor families
-
-  [CF] Windows: Added support for 3ware 9000 controllers using extended
-       SMART functionality in new 3ware driver. This includes DEVICESCAN
-       support for at most 2 controllers. Thanks to Greg de Valois from
-       AMCC/3ware for new driver features, development support and
-       hardware for testing.
-
-  [SZ] smartd: Support HighPoint RocketRAID controller under GNU/linux
-
-  [DG] [SCSI] First cut for '-l background' to show background scan
-       results log
-
-  [SZ] smartctl: Support HighPoint RocketRAID controller under GNU/linux
-
-  [KS] C++ compile fixes for Solaris with a few cleanups.
-
-  [BA] C++ compile fixes for Darwin (thanks to CF)
-
-  [CF] Removed old *.c files (now in CVS Attic).
-
-  [CF] Added changes for C++ to platform independent and Windows
-       related files.
-
-  [BA] Tagged last .c Version with PRE_MOVE_TO_CPP. Copied *.c,v
-       to *.cpp,v in CVS repository to preserve history of source
-       files. Removed sm5_Darwin repository.
-
-  [CF] smartctl: Added -n option to skip checks when disk is in
-       low-power mode.
-
-  [CF] Windows: Added alternate system call for power state check
-       because the PASS THROUGH calls may spin up the disk.
-
-  [CF] smartd: Modified power state logging to report state changes
-       instead of standby condition.
-
-  [CF] smartd: Ignore -n directive on scheduled self tests.
-
-  [DG] [SCSI] Make start stop cycle counter log page decoding
-       more robust
-
-  [DG] Modify smartctl (but not smartd) to detect probable ATA
-       devices behind a SAT layer. In the absence of an explicit
-       device type, change to device type 'sat'.
-
-  [DG] Add indication that controller (device) type has been
-       explicitly set. Preparation for automatic detection of
-       'sat' device type unless user specifies a device type.
-
-  [SS] NetBSD: Deliver strings from ata_identify_device properly 
-       on little- and big-endian platforms.
-
-  [BA] Added published ANSI ATA-7 spec to list of recognized ATA
-       versions.
-
-  [BA] Code janitor: added missing header strings for '-V' option.
-
-  [DG] [SATA] Extend 'sat' device type to allow either 12 or 16 byte
-       variant of the SAT ATA PASS THROUGH SCSI command. Syntax is
-       '-d sat,<n>' where <n> can be 0, 12 or 16 . The ',<n>' part
-       is optional. Currently defaults to 16 byte variant but that
-       could be made platform or even device dependent.
-
-  [DG] [SATA] Add new 'sat' device type for SATA disks behind a
-       SCSI to ATA Translation (SAT) Layer (SATL). Uses the ATA
-       PASS THROUGH (16) SCSI command thence the generic SCSI
-       passthrough for each platform.
-
-  [CF] Windows: Added script and make targets to create installer
-       with NSIS (http://nsis.sourceforge.net/)
-
-  [CF] Updated hostname and links for new SourceForge CVS service.
-
-  [CF] smartd: Added '-W' directive to track temperature changes
-       and warn if temperature limits are reached.
-
-  [CF] Windows: Added IOCTL_ATA_PASS_THROUGH (Win2003, XP SP2)
-       for commands unsupported by SMART_IOCTL. Added device
-       specific options to select subset and ordering of the ATA
-       IOCTLs actually used. These options are specified as
-       modifiers of the device name (/dev/hd[a-j]:[saic]+)
-
-  [CF] Windows: Added support for drives 4-7 (/dev/hd[e-h]) via
-       SMARTVSE.VXD on Win9x/ME. Thanks to Dariusz Rzonca for
-       patch and testing.
-
-  [DG] [SCSI/SATA linux] from lk 2.6.17 SATA disk identification in
-       libata will change. Expand LibAta detection to see old
-       identifier and new variant (VPD page 0x83).
-
-  [BA] Identified Attribute 190 for Western Digital disks.  This
-       stores temperature in Celsius, just like Attribute 194.
-       But it has a failure threshold set to correspond to the
-       maximum design operating temperature of the disk, which
-       is 55 Celsius on the WD800JD drives that I studied.
-       So if this Attribute has 'failed
-       in the past' this means that the maximum disk operating
-       temperature has been exceeded.
-
-  [GK] Darwin: Add support for AHCI drivers found in Intel-based Macs.
-
-smartmontools 5.36 Stable Release
-
-  [BA] Linux: smartd/smartctl issue syntax hints to user if 3ware
-       disk controller present with EITHER 3ware OR AMCC vendor
-       name, and user syntax incorrect.
-
-  [BA] Update copyright dates to 2006.
-
-  [DG] [SCSI] Loosen sanity check on Seagate/Hitachi factory information
-       log page so it is not skipped on recent Seagate SCSI disks.
-
-  [CF] Added command 'smartd -q showtests' to list test schedules.
-
-  [CF] Added command 'smartctl -P showall MODEL [FIRMWARE]' to list
-       database entries for specific drives and firmware.
-
-  [PW] Automatically set -v 9,minutes and -v 194,unknown for Maxtor
-       DiamondMax D540X-4G drives.
-
-  [DG] [SCSI] suppress various outputs when data fails sanity checks.
-       Correct 'last n error events' log page indexing.
-
-  [DG] [SCSI] changed smartctl exit status to reflect any problems in
-       the most recent 20 self test logs [Leandro Santi]
-
-  [DG] [SCSI] Fix process return value when scsiGetSmartData() fails
-       in smartctl [Leandro Santi]
-
-  [BA] Updated docs and error message to reflect Linux libata
-       support for smartmontools starting with the 2.6.15 kernel
-       series. Also init script support for the 'tinysofa' release.
-
-  [DG] [SCSI] Mask dpofua bit when changing mode pages. Fix failure
-       of 'smartctl -l error'.
-
-  [EM] Fixed a problem with FreeBSD and 3Ware 'twe' devices
-
-  [CF] Fixed a regexp in knowndrives table, added regexp syntax check
-       via 'smartctl -P showall'.
-
-  [CF] Cygwin & Windows: Fixed memory leak in function calling
-       IOCTL_IDE_PASS_THROUGH. Thanks to Fred Schmidt for the problem
-       report.
-
-  [CF] Cygwin: added cygrunsrv support and commands "install", "remove"
-       and "status" to smartd.initd.
-
-  [SS] Fix runtime problems on big-engian NetBSD platforms (patch provided
-       by Martin Husemann)
-
-  [CF] Cygwin smartd: Open smartd.conf in textmode to allow use of
-       Windows editors.
-
-  [CF] Cygwin smartd: Added option '--service' to allow smartd running
-       as windows service via cygrunsrv. Useful in conjunction with new
-       syslogd support added in Cygwin 1.5.15.
-
-  [CF] Windows: Added patch to avoid output of non-ascii timezone names.
-
-  [EM] Incorporate various patches to provide TWE support and support for 
-       multiple 3Ware cards, Power Check Support, and FreeBSD 6.x support.
-       Thanks to Rudolf Cejka, Frank Behrens, and Jung-uk Kim.
-
-  [DG] Silence gcc 4.0.1 compile warning concerning the difference in
-       "signedness" in pointer assignments. Changes to SCSI code
-       and os_linux.c .
-
-  [PW] Additions to knowndrives table: added missing drive from Quantum
-       Fireball Plus LM series, added QUANTUM BIGFOOT TS10.0A, added
-       ExcelStor J680 and J880, added Western Digital Caviar RE Serial ATA
-       series, added missing drives from Western Digital Caviar SE series,
-       added Seagate Momentus 4200.2 series, added missing drives from
-       Maxtor DiamondMax 10 series, added Fujitsu MHG and MHH series, and
-       added Hitachi Travelstar 5K100 series.
-
-  [PW] Additions to knowndrives table: added Fujitsu MHU2100AT, added
-       Fujitsu M1623TAU, added missing drives from Seagate Barracuda
-       7200.8 series, added Seagate Momentus 5400.2 series, and added
-       QUANTUM FIREBALL CR8.4A.
-
-  [PW] Additions to knowndrives table: added missing drive from Maxtor
-       MaxLine II series, added Maxtor DiamondMax 2880 Ultra ATA series,
-       added Maxtor DiamondMax 17 VL series, added Hitachi Deskstar 7K80
-       series, and added Hitachi Deskstar 7K400 series.
-
-  [CF] Windows: Fixed unsupported 'smartctl -X' on Win2000/XP by using
-       IOCTL_IDE_PASS_THROUGH instead.
-
-smartmontools 5.34 Stable Release [NOTE: never officially released]
-
-  [CF] Cygwin & Windows smartd: Increased SCSI DEVICESCAN range
-       from ASPI adapter 0-3 to 0-9. Added diagnostic messages.
-
-  [CF] Windows smartd: Added ability to run .bat files via '-M exec'
-       directive.
-
-  [CF] Cygwin smartd: Added FreeConsole() after fork() to avoid hang
-       of terminated shell console window.
-
-  [DG] [SCSI] Add code so 'smartctl -A' outputs the number of elements
-       in the grown defect list. When this number is increasing a
-       disk has problems. N.B. Similar logic should be added to smartd.
-
-  [CF] Windows smartd: Fixed event handling to allow start of another
-       smartd process when service is already running. Useful for testing
-       service configuration changes in debug mode.
-
-  [PW] Added following drives to knowndrives table: Western Digital Raptor
-       family, Seagate Barracuda 7200.8 family, Maxtor DiamondMax 2160
-       Ultra ATA and DiamondMax 10 families, Hitachi Travelstar E7K60
-       family, Seagate Medalist 17240, 13030, 10231, 8420, and 4310,
-       TOSHIBA MK4018GAP and MK6022GAX, ExcelStor Technology J360, and
-       Western Digital Caviar AC14300.
-
-  [PW] Added missing Fujitsu MHTxxxxAT and Seagate Barracuda 7200.7 drives
-       to knowndrives table.
-
-  [PW] Added QUANTUM FIREBALLP LM10.2 to knowndrives table.  Thanks to
-       Mike Fleetwood for submitting the patch.
-
-  [KS] Solaris/SPARC: fixed not to disable automatic offline test and
-       automatic save attributes incorrectly.  Thanks to Roy Badami.
-
-  [BA] Linux: smartd init script now recognizes 'trustix' distro.
-
-  [DG] [SCSI] Medium and hardware errors were slipping through
-       unreported. Fix linux SCSI sense reporting via SG_IO ioctl.
-
-  [DG] [SCSI] Change lba of first failure in selftest output to
-       decimal (was hex) to conform with ATA output.
-
-  [GK] smartd: Detect most self-test failures even if the hour counter
-       has wrapped.
-
-  [BA] smartctl: list 'marvell' as option if user give invalid
-       -d argument
-
-  [CF] Windows: fixed SCSI timeout handling to allow long timeouts
-       for selftests.
-
-  [CF] Fixed buffer overflow issues in printone() and safe_vsnprintf()
-       which results in crash on -V option (at least on Windows).
-
-  [DG] [SCSI] Add explicit timeouts to INQUIRY and REQUEST SENSE (that
-       were missed in an earlier patch). Could have impacted freebsd.
-
-  [DG] When linux detects a sata_via_libata disk suggest that user try
-       '-d ata' (rather then '-d libata). Anticipate kernel change.
-
-  [YD] Added OS/2 and eComStation platform support.
-
-  [PW] Added Seagate U4 family, Fujitsu MHJ and MHK families, Seagate
-       Barracuda 5400.1, QUANTUM FIREBALLP KX27.3, QUANTUM FIREBALLP KA10.1,
-       and ExcelStor J340 to knowndrives table.
-
-  [DG] [SCSI] After report of Hitachi IC35L073UCDY10 disks locking up
-       on log page 0x7 (last n error events), check log page (and some
-       others) is supported (via log page 0x0) before probing.
-
-  [CF] Added safe_v?snprintf() for platforms using v?snprintf()
-       with non standard behaviour on overflow (Windows, old Linux)
-
-  [CF] smartd: Added message if check power mode spins up disk.
-
-  [CF] Windows: Added support for READ_LOG on WinNT4 using undocumented
-       pseudo SCSI command via IOCTL_SCSI_PASS_THROUGH.
-
-  [CF] smartd: Added ',q' option for '-n' directive to suppress 'skipping
-       checks' log message. This prevents a laptop disk from spinning up
-       due to this message. Thanks to Rob MacLachlan and Manfred Schwarb
-       for pointing out problem & solution.
-
-  [CF] Windows: Added function get_os_version_str() to show OS flavor in
-       copyright message.
-
-  [CF] Windows: Added function ata_identify_is_cached() to check for outdated
-       SMART enabled bit in identify data.
-
-  [CF] Windows: Added fix to prevent linkage of smartd specific win32 modules
-       to smartctl.
-
-  [PW] Added Fujitsu MPG3153AH, Hitachi Endurastar J4K20/N4K20 (formerly
-       DK23FA-20J), Seagate Momentus family, and Maxtor Fireball 3 family
-       to knowndrives table.
-
-  [PW] Added missing Maxtor DiamondMax 16, Seagate Barracuda ATA IV, and
-       Western Digital Caviar WDxxxAA/WDxxxBA drives to knowndrives table.
-
-  [CF] Windows: Added ATA check power mode for smartd -n directive.
-
-  [CF] Windows: Fixed use of new service status flag which causes hang
-       of smartd service on WinNT4.
-
-  [CF] Windows: Fixed error checking of IOCTL_IDE_PASS_THROUGH (used
-       for READ_LOG on 2000/XP). Added some diagnostic messages on
-       -r ataioctl[,2]. Thanks to Manfred Schwarb for bug report and testing.
-
-  [BA] Fixed code bug that made it impossible to enable SMART on
-       disks with failing health status.  This would happen if the
-       os_*.c author made STATUS and STATUS_CHECK work the same way.
-       I have corrected this at a higher level; we now handle the
-       case where STATUS and STATUS_CHECK are identical without
-       issues. 
-
-  [LW] Make os_linux.c/marvell_command_interface() always return 0 on STATUS.
-       Needed for a disk having bad SMART status.
-
-  [CF] smartctl: Added drive family printing.
-
-  [CF] autogen.sh: Allow automake 1.9, added message if automake
-       version is unknown.
-
-  [BA] smartctl: use locale-specific separators for printing disk
-       capacity.  Also use AC_CHECK_HEADERS not AC_CHECK_HEADER in
-       configure.in.
-
-  [BA] clean-up of #include structure so that -V options to smartd
-       and smartctl work correctly.  Please, don't #include header
-       files into other header files.
-
-smartmontools 5.33 Experimental Release
-
-  [BA] smartctl: ATA disks, if SMART ATTRIBUTE THRESHOLDS page has ID
-       errors with some Attributes having NULL IDs, print Attribute
-       info anyway (but issuing a warning to the user).
-
-  [DG] [SCSI] Decode Last n error events log page; decode track following
-       and positioning errors [Hitachi]
-
-  [EM] FreeBSD: another tweak, __packed__ introduced in Version 5.0040
-
-  [EM] Cleaner tweak of fixes for FreeBSD 4.x.
-
-  [EM] Fix compilation errors under FreeBSD 4.x, as it is still using
-       and old GCC
-
-  [EM] Remove 3ware/FreeBSD specific files and just include pieces we need
-
-  [DG] Add logic in smartd to detect 3ware, Marvell controllers and SATA
-       disks behind an ATA-SCSI simulator (in Linux). If specific device
-       types are not given and they are picked in a general SCSI device
-       scan then warn and skip.
-
-  [GG] insert correct path to smartd into smartd's init script
-
-  [BA] Changed all default paths in documentation to reflect /usr/local as
-       default path prefix.  This affects on-line man pages, primarily.
-  
-  [DS] Added support for OpenBSD
-
-  [BA] Added another environment variable SMART_FULLMESSAGE set by
-       the smartd mailing feature, and modified examplescripts/Example1
-       to illustrate it.
-
-  [BA] Fixed potentially misleading messages of the form:
-       XXX failed: success
-
-  [DG] emit warning if SATA disk detected using libata in Linux; then exit
-
-  [PW] Added Seagate U10 family, Hitachi Travelstar 7K60, Fujitsu MHR2020AT,
-       and QUANTUM FIREBALLP AS20.5 to knowndrives table.
-
-  [DG] Detect 3ware and Marvell controllers from SCSI INQUIRY vendor string
-       and suggest usage of appropriate '-d' argument in smartctl.
-
-  [LW] Tested the RELEASE_5_33_WITH_MARVELL_SUPPORT branch on
-       actual Marvell 88SX5041 hardware, with success.
-       Merged into HEAD.
-
-  [BA] Fixed nasty DEVICESCAN bug
-
-  [BA] Checked in RELEASE_5_33_WITH_MARVELL_SUPPORT branch with
-       some Marvell support.
-
-  [BA] Additional modifications of Ed's controller scheme.  Fixed
-       broken 3ware support under linux, problems with scanning
-       devices in smartd, and other small problems.
-
-  [CF] Added make targets to build formatted man pages (htmlman, txtman),
-       Windows distribution (dist-win32) and MSVC6 config.h (config-vc6).
-
-  [EM] Minor change to FreeBSD inclusion of 'twe' include files.  Add 
-       code to check if they exising in /usr/include/sys to use those
-       in preference to ones added here
-
-  [EM] Very preliminary support attempt for 3Ware controllers under 
-       FreeBSD. Also, switched 'escalade_type/escalade_port' to
-       'controler_type/controller_port' and moved away from 
-       'tryata/tryscsi' to using new 'controller*' variables to 
-       determine which controller type (ATA/SCSI/3Ware) to use.
-
-  [GK] Added initscript support for Darwin.
-
-  [CF] Windows smartd: Added ability to run smartd as a windows service,
-       including new commands "smartd install ..." and "smartd remove"
-       to install and remove the service registry entry.
-
-  [BA] smartd: warn user if -s regexp regular expression contains
-       characters other than 0123456789.*()|+?[-]{}:=SLCO since such
-       characters are 'suspicous' and may indicate a poorly formed
-       regexp.  Extended regular expression gurus: can this list be
-       reduced somewhat?
-
-  [CF] Fixed bug in Windows smartd: Missing close of config file when
-       configuration is reloaded by smartd daemon.
-
-  [CF] Windows smartd: Added mail warning feature using the "Blat"
-       (http://blat.sourceforge.net/) mailer as a default.
-
-  [PW] Added Maxtor DiamondMax Plus 5120 Ultra ATA 33 series and TOSHIBA
-       MK3017GAP to knowndrives table.
-
-  [CF] Added fixes to build smartmontools on old Linux systems
-       (libc < 6, Kernel 2.0.x).
-
-  [BA] Added ATA minor version identity strings for latest ATA specification
-       updates: ATA/ATAPI-7 T13 1532D revision 4a and ATA/ATAPI-6 published,
-       ANSI INCITS 361-2002
-
-  [PW] Added Hitachi Travelstar 5K80 family and Fujitsu MHTxxxxAH family to
-       knowndrives table.
-
-  [EM] Fix up compilation under FreeBSD < 5.x
-
-  [PW] Added QUANTUM FIREBALL EX3.2A and missing Western Digital Caviar SE
-       drives to knowndrives table.
-
-  [BA] Modified Hitachi Travelstar 80GN family regexp in drive database.
-       Thanks to [GK/CF] for problem & solution.
-
-  [GK] Added os_darwin.[ch]
-
-  [PW] Added the following drives to the knowndrives table: IBM Travelstar
-       48GH, 30GN, and 15GN family; IBM Deskstar 37GP and 34GXP family;
-       Western Digital WDC WD272AA; Maxtor DiamondMax D540X-4D family;
-       TOSHIBA MK2016GAP, MK2018GAP, MK2018GAS, MK2023GAS; and
-       QUANTUM FIREBALL ST3.2A
-
-  [BA] smartd/smarctl now print build HOST/OS information as part
-       of startup slogan.  This should make it slightly easier to
-       read bug reports from users.
-
-  [RZ] Fixed the DEVICESCAN to do what it was supposed to do - give
-       error message unless scanning is in progress.  
-
-  [BA] Update documentation to describe 3ware character devices. Better
-       error detection for missing/malfunctioning devices behind 3ware
-       controllers. Now pack 3ware ioctl structures explicitly.
-
-  [BA] For ATA devices that support LBA mode, print capacity as part
-       of smartctl --info
-
-  [RZ] Made DEVICESCAN quiet about non-existing devices unless debug
-       is on.
-
-  [DG] treat "unit attention" SCSI warning as try again in some contexts
-       (test unit ready and mode sense)
-
-  [BA] on drives that store max/min rather than min/max, get order
-       correct in printing temp.
-
-  [BA] fixed typo in 'smartctl -h' output.  Thanks to Gabor Z. Papp.
-
-  [BA] linux: clean-up to 3ware/AMCC support; dynamically create
-       or fix /dev/tw[ae][0-15] device node entries if they don't
-       exist or are incorrect. One can now use the character devices
-       /dev/twe[0-15] OR /dev/sd? for 3ware 6000/7000/8000 series
-       cards.  One must use /dev/twa[0-15] for 3ware 9000 series cards.
-       Note that selective self-tests now work via /dev/tw[ae] devices.
-       Next step: documentation.
-
-  [BA] linux: experimental "support" for 3ware/AMCC 9000 series
-       controllers that use the 3w-9xxx driver.  This will be in a
-       state of flux for a few days.  Note that this requires the
-       character interface /dev/twa[0-15].
-
-  [DG] linux: extend general SCSI OS interface to use the SG_IO ioctl. If
-       not available, use the older SCSI_IOCTL_SEND_COMMAND ioctl.
-
-  [KS] Solaris/x86: fixed system identification problem in configure
-       script.  Thanks to Stuart Swales.
-
-smartmontools 5.32
-
-  [BA] Update link to revised/updated IBM Deskstar Firmware
-
-  [CF] Cygwin & Windows: Added missing ASPI manager initialization
-       with GetASPI32SupportInfo(). Thanks to Nikolai SAOUKH for pointing
-       this out and providing a patch.
-
-  [BA] modified smartd init script to work on whitebox (thanks to
-       Michael Falzon)
-
-  [BA] removed (reverted) additional Attribute definitions from
-       http://smart.friko.pl/attributes.php.  All (or most?) of these
-       appear to be return code values for the WD Digital Life Guard Utility.
-
-  [PW] Added Seagate Medalist 17242, 13032, 10232, 8422, and 4312 to
-       knowndrives table.  Added missing Seagate U Series 5 drives.
-
-  [PW] Added the following QUANTUM models to knowndrives table:
-       FIREBALL EX6.4A, FIREBALLP AS10.2, FIREBALLP AS40.0, FIREBALL CR4.3A,
-       FIREBALLP LM15, FIREBALLP LM30, and FIREBALLlct20 30
-
-  [PW] Added missing Western Digital Protege drives to knowndrives table.
-
-  [PW] Added Maxtor DiamondMax 40 ATA 66 series and DiamondMax 40 VL Ultra
-       ATA 100 series to knowndrives table.
-
-  [PW] Added the following Hitachi/IBM drives to knowndrives table:
-       HITACHI_DK14FA-20B, Travelstar 40GNX series, Travelstar 4LP series,
-       and Travelstar DK23XXB series.  Added the missing Travelstar 80GN
-       drives.
-
-  [PW] Added Fujitsu MPB series and MPG series to knowndrives table.  Added
-       the missing Fujitsu MHSxxxxAT drives.
-
-  [KS] Solaris: added workaround for dynamic change of time-zone.
-
-  [KS] Solaris: fixed problem that autogen.sh cannot detect absence of
-       auto* tools.
-
-  [BA] smartd: added time-zone bug information to man page. 
-       Reverted CF code for _WIN32 case. 
-
-  [CF] Cygwin & Windows: Added better error messages on IDE/ATA device
-       open error.
-
-  [BA] added additional Attribute definitions from
-       http://smart.friko.pl/attributes.php
-
-  [BA] smartd: reworked TimeZone bug workaround so it is only invoked
-       for glibc.  Note: this might not be right -- a similar bug may
-       exist in other platform's libcs.
-
-  [DG] SCSI smartmontools documentation updated [2004/5/6]. See:
-       http://smartmontools.sourceforge.net/smartmontools_scsi.html
-
-  [CF] Windows: Fixed reset of TZ=GMT in glibc timezone bug workaround.
-
-smartmontools 5.31
-
-  [DG] move SCSI device temperature and start-stop log page output
-       (smartctl) into --attributes section (was in --info section).
-
-  [GG] change default installation location to /usr/local
-
-  [CF] Cygwin smartd: Fixed crash on access of SCSI devices after fork().
-
-  [PW] Added TOSHIBA MK4018GAS and the following Maxtor drive families
-       to knowndrives table: DiamondMax D540X-4G, Fireball 541DX,
-       DiamondMax 3400 Ultra ATA, DiamondMax Plus 6800 Ultra ATA 66.
-
-  [PW] Added missing Maxtor DiamondMax 16, DiamondMax D540X-4K, and
-       DiamondMax Plus 45 Ulta ATA 100 drives to knowndrives table.
-
-  [PW] Added ExcelStor J240, Hitachi Travelstar 80GN family, Fujitsu
-       MHTxxxxAT family, and IBM Deskstar 25GP and 22GXP families to
-       knowndrives table.
-
-  [CF] Cygwin smartd: Added workaround for missing SIGQUIT via keyboard:
-       To exit smartd in debug mode, type CONTROL-C twice.
-
-  [BA] smartctl: printing of the selective self-test log is now
-       controlled by a new option: -l selective
-
-  [BA] Added entries for Samsung firmware versions -25 to -39 based
-       on latest info about firmware bug fixes.
-
-  [PW] Added Seagate U Series X family, Seagate U8 family, and Seagate
-       Medalist 8641 family to knowndrives table.
-
-  [CF] smartd: Added exit values 5/6 for missing/unreadable config file.
-
-  [BA] smartd: now monitor the Current Pending Sector count (Attribute 197)
-       and the Offline Pending Sector Count (Attribute 198).  Log a
-       warning (and send an email, if so configured) if the raw count
-       is nonzero.  These are controlled by new Directives: -C and -U.
-       Currently they are enabled by default.
-
-  [CF] Added option -c FILE, --configfile=FILE to smartd to specify
-       an alternate configuration FILE or '-' for standard input.
-
-  [KS] configure.in now searches for -lnsl and -lsocket for Solaris.
-
-  [CF] Win32/native smartd: Added thread to combine several syslog output
-       lines into one single event log entry.
-
-  [CF] Win32 smartd: Added DEVICESCAN for SCSI/ASPI devices.
-
-  [GG] Use gethostbyname() the get the DNS domain since getdomainname() 
-       returns the NIS domain when sending mails from smartd.
-
-  [GG] smartd.init.in: pass smartd_opts to smartd on startup, read distribution
-       specific configuration files if found
-
-  [SS] smartctl: added NetBSD support for Selective Self-tests.
-
-  [BA] smartd.conf example configuration file now has all examples
-       commented out except for 'DEVICESCAN'.
-
-  [CF] Win32/native smartd: Added ability to display warning "emails"
-       as message box by "-m msgbox" directive. With "-m sysmsgbox",
-       a system modal (always on top) message box is shown.
-
-  [BA] smartctl: printing of self-test log for disks that support
-       Selective self-testing now shows the status of the (optional)
-       read-scan after the selective self test.  Also, changed format
-       in printing self-test log to print failing LBA in base 10 not
-       base 16 (more compatible with kernel error messages).  Also,
-       in printing SMART error log, print timestamps in format
-       days+hours+minutes+seconds.
-
-  [CF] Win32 smartd: Added ability to log to stdout/stderr
-       (-l local1/2). Toggling debug console still works
-       if stdout is redirected.
-
-  [BA] smartctl: selective self-test log, print current status
-       in a  more detailed way.  Allow writing of selective self-test
-       log provided that no other self-test is underway.
-
-  [BA] Linux: eliminated dependency on kernel tree hdreg.h.
-
-  [BA] smartctl: -l selftest option now prints Selective self-test
-       log in addition to the normal self-test log.
-       Added additional options (-t pending, -t afterselect) to
-       control remaining Selective Self-test capabilities.  Tested
-       with several Maxtor disks. Modified error message printing
-       so that munged option messages print at the end not the
-       start of output.
-
-  [CF] Added daemon support to Win32 native version of smartd.
-       The daemon can be controlled by commands similar to initd
-       scripts: "smartd status|stop|reload|restart|sigusr1|sigusr2".
-
-  [CF] Added minor support for option "-l local[0-7]" to Win32 native
-       (not Cygwin) version of smartd. If specified, the log output
-       is written to file "./smartd[1-7]?.log" instead of event log.
-
-  [BA] Added Selective Self-test to smartctl (-t selective,M-N).
-       Currently only supported under Linux; Solaris, NetBSD, FreeBSD
-       and Windows developers must add WRITE LOG functionality to
-       os_*.c
-
-  [BA] Added workaround for an annoying glibc bug: if you change
-       timezones, (eg, flying with a laptop from USA to Europe)
-       localtime() does not notice this in a running
-       executable, so time that appears in the system log (syslog!)
-       will be incorrect.  See
-       http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48184
-       for additional examples of this bug.
-
-  [DG] Set explicit timeouts for SCSI commands (most default to 6 seconds).
-       Previously a 0 second timeout was meant to be interpreted as a 
-       default timeout but the FreeBSD port had a problem in this area.
-
-  [CF] Fixed un-thread-safe exit signal handler for Win32
-
-  [BA] Fixed un-thread-safe exit signal handler pointed out
-       by CF.
-
-  [BA] Changed configure script to eliminate warnings under
-       Solaris from sys/int_type.h conflicts with int64.h
-       Added header files for umask to smartd.c.
-
-  [BA] Man page format change from Werner LEMBERG.  " " changed to \&
-
-  [CF] Added os_win32/syslogevt.* event message file tool for Win32
-       smartd (native+cygwin). May also be useful for other cygwin
-       programs writing to syslog().
-
-  [CF] Added Win32 version of smartd
-
-  [CF] Merged RELEASE_5_26_WIN32_BRANCH
-
-  [BA] Made some changes to man page markup suggested by
-       Richard Verhoeven to work around bugs in man2html.
-       Tested not to break anything under Linux and Solaris.
-
-  [CF] Moved PrintOut() from utility.c to smart{ctl,d}.c to avoid
-       syslog() output of smartctl.
-
-  [BA] Grew worried that some time-zone names could be very long (eg,
-       Mitteleuropaische Zeit) and put date string lengths into a
-       single macro in utility.c
-
-  [EM] Updated os_freebsd.c to handle older versions of FreeBSD in a 
-       more appropriate/obvious fashion.
-
-  [EM] Modified autogen.sh as FreeBSD installs automake 1.7 as 
-       'automake17' and NOT 'automake-1.7'
-
-smartmontools 5.30
-
-  [PW] Added QUANTUM FIREBALLlct15 30, QUANTUM FIREBALLlct20 40, and
-       Maxtor 6Y060P0 (DiamondMax Plus 9 60GB) to knowndrives table.
-
-  [PW] Added Maxtor MaXLine II family to knowndrives table (thanks to
-       Brett Russ for submitting the patch).
-
-  [BA] Added remaining read/write commands to detailed list of
-       error log commands that have text descriptions of problem
-       printed.  For commands that support it, print number of failed
-       sectors at problem LBA.
-
-  [BA] Made SuSE section of smartd init script more SuSE 9 compatible.
-       Thanks to Hans-Peter Jansen.
-
-  [CF] Windows smartd: Added IDE/ATA device scan
-       Added windows device names to smartctl.8.in, smartd.8.in
-   
-  [BA] smartctl/smartd: user-provided '-F samsung' and '-F samsung2'
-       command line options/Directives did NOT over-ride preset values
-       unless user specified '-P ignore'.  Now they will always over-ride
-       preset values from the database.
-
-  [BA] Added error decoding for a few more READ and WRITE commands.
-
-  [PW] Added Maxtor MaXLine Plus II, Western Digital Caviar SE (Serial ATA)
-       series, Hitachi Deskstar 7K250 series, and Ultra ATA 66 models of
-       the Maxtor DiamondMax Plus 40 series to knowndrives table.
-
-  [BA] Added Maxtor Diamondmax 250 GB drives to database.  Note that
-       these model numbers are not listed in Maxtor documentation, but
-       they exist.
-
-  [BA] Removed the 'contact developers' phrase from the Samsung disk
-       warning messages.
-
-  [PW] Added TOSHIBA MK2017GAP, IBM Deskstar 14GXP and 16GP series,
-       Fujitsu MPC series, Seagate Barracuda ATA III family, and missing
-       Seagate Barracuda U Series drives to knowndrives table
-
-  [BA] smartd: wrong loglevel for message: Configuration file
-       /etc/smartd.conf parsed.  Changed to LOG_INFO from LOG_CRIT.
-       Thanks to  Emmanuel CHANTREAU for the report.
-
-  [CF] Checked in development version of windows code base.
-
-smartmontools 5.29 (note: there was NO 5.28 release)
-
-  [BA] smartd: configure script did not set correct directory to search for
-       smartd.conf based on --prefix argument to ./configure.  Thanks to
-       GG for identifying the problem and fix.
-
-  [BA] make clean now removes man pages (generated from *.in) files as well
-       as object files.
-
-  [EM] Correct copying of sense data in FreeBSD SCSI implementation. Thanks
-       to Sergey Svishchev for noticing the bug.
-
-  [BA] On solaris, wrong warning message if no ATA support.  Warning message
-       concerns 3ware controller, not ATA.
-
-  [SS] Added SCSI support for NetBSD.
-
-  [BA] on big-endian linux machines, fixed interpretation of HDIO_GET_IDENTITY
-       to correctly identify ATAPI bit (was byte swapped).  This should
-       eliminate some SYSLOG noise if user queries a packet device (eg, CD
-       ROM or DVD reader).
-
-  [PW] Removed warning for IBM Deskstar 40GV & 75GXP series drives with
-       A5AA/A6AA firmware.  Thanks to Gerald Schnabel.
-
-  [PW] Added Toshiba TOS MK3019GAXB SUN30G to knowndrives table
-
-  [PW] Added Western Digital Caviar AC12500, AC24300, AC25100, AC36400,
-       and AC38400 to knowndrives table
-
-  [BA] When printing ATA error log, print the LBA at which READ
-       or WRITE commands failed.
-
-  [BA] Changed syntax of error message in smartctl
-
-  [BA] Added versioning info (-V options to smartd/smartctl) for
-       Solaris ATA module.
-
-smartmontools 5.27
-
-  [KS] Added ATA/IDE support for Solaris/SPARC (ATA/IDE not yet for
-       Solaris/x86).
-
-  [BA] 3ware controllers: documented that one can monitor any of the
-       physical disks from any of the 3ware /dev/sd? logical devices.
-       Better warnings if querying a disk that does not exist.
-
-  [PW] Added Hitachi Travelstar DK23DA series, Maxtor DiamondMax Plus 40
-       series, Western Digital Caviar WDxxxAA, WDxxxBA, and WDxxxAB series
-       to knowndrives table
-
-  [BA] missing 'pragma pack' on ATA IDENTIFY DEVICE structure may have
-       caused odd or incorrect results on 64-bit machines.
-
-  [BA] smartctl/smartd allow inspection of self-test and error logs even
-       if disk firmware claims that these don't exist.  This is needed
-       for some Maxtor disks whose firmware does not indicate log support
-       even though the disk DOES support it.
-
-  [BA] Improved porting instructions and documentation in os_generic.c
-
-  [PW] Add Western Digital Caviar WD136AA and SAMSUNG SP40A2H (RR100-07
-       firmware) to knowndrives table.
-
-  [EM] FreeBSD:        remove extra definition of FreeNonZero
-
-  [BA] smartctl: the -q silent option was printing output for some
-       error conditions.  Fixed.  Will rename relevant variables to help
-       avoid these errors in the future.
-
-  [SS] NetBSD port added.
-
-  [BA] more sensible error messages for devfs and devfs-like systems.
-       Instead of saying that the DIRECTORY does not exist, say that
-       the DEVICE does not exist.
-
-  [BA] smartd: added -n Directive, to prevent disk spin-up depending
-       upon the power mode (SLEEP, STANDBY, or IDLE).
-
-  [PW] Added Maxtor DiamondMax 20 VL series, Fujitsu MPF series,
-       Maxtor DiamondMax 36 series, Maxtor DiamondMax 4320 series, and
-       Maxtor DiamondMax 536DX series to knowndrives table.
-
-  [BA] many warning messages now give the file name AND VERSION
-
-  [BA] smartd: when the user provides multiple address recipients
-       to the '-m' Directive in a comma-delineated list, the commas
-       are stripped out before passing the list of addresses to the
-       mailer program. (Thanks to Calin A. Culianu for pointing this out
-       and providing a patch.)
-
-  [BA] smartd: when the '-M exec path' Directive is used, any stdout OR
-       stderr output from the executable "path" is assumed to indicate a
-       problem, and is echoed to SYSLOG.
-
-  [BA] Added all missing IBM/Hitachi Deskstar 180GXP models to knowndrives
-       table.
-
-  [PW] Added some missing IBM/Hitachi Deskstar 120GXP models to knowndrives
-       table.
-
-  [PW] Added IBM Travelstar 14GS to knowndrives table.
-
-  [PW] Modified knowndrives table to match entire Hitachi Travelstar
-       DK23BA and DK23EA series of drives (thanks to Norikatsu Shigemura
-       for submitting the patch).
-
-  [PW] Added some missing Fujitsu MPE series drives to knowndrives table.
-
-  [PW] Added TOSHIBA MK4019GAX, TOSHIBA MK6409MAV, and QUANTUM
-       FIREBALLlct15 20 to knowndrives table.
-
-  [EM] Fixup example command output for FreeBSD
-
-  [PW] Added Maxtor DiamondMax 80 family to knowndrives table.
-
-  [EM] Catch up FreeBSD code to switch PROJECTHOME to PACKAGE_HOMEPAGE
-       macros.
-
-  [BA] smartd: now watches stdout/stderr when trying to run mail, mailx
-       or mail warning script, and reports any output to SYSLOG.  This
-       gives a clearer error message if something is wrong.
-
-  [BA] smartd: Solaris init script modified to accomodate grep that
-       lacks '-q' quiet option.  Also check for running process to kill
-       on stop.
-
-  [PW] Added some missing Seagate Barracuda 7200.7 and 7200.7 Plus drives
-       to knowndrives table.
-
-  [PW] Added Maxtor DiamondMax Plus 60 family and Seagate U Series 5 20413
-       to knowndrives table.
-
-  [BA] smartd: under Solaris, made default mailer be 'mailx' not
-       'mail', since Solaris 'mail' does not accept a '-s' argument.
-       A workaround for Solaris users of earlier versions is to
-       have '-M exec /bin/mailx' in their smartd.conf config file.
-
-  [DG] some SCSI controllers don't like odd length transfers so make
-       sure LOG SENSE transfers are rounded up to an even number when
-       and odd length is reported (i.e. there is a double fetch, the
-       first to find the length, the second gets the data)
-
-  [BA] smartd man pages: under Solaris, correct section numbers in the
-       'See also' section.
-
-  [KS/BA] smartd man page: describe how to set Solaris syslog.conf
-       file to catch all messages.  Give correct Solaris SYSLOG default
-       path /var/adm/messages in man pages.
-
-  [BA] smartd: incorporated Debian startup script submitted by user.
-
-  [BA] smartctl: modified printing of self-test log entry number.  Seagate
-       firmware can leave 'holes' in the self-test log while a test is
-       actually running.  We now print entry numbers consistently in this
-       case, not assuming that entries are contiguous.
-
-  [PW] Added QUANTUM FIREBALL CX10.2A and Western Digital Caviar AC23200L
-       to knowndrives table.
-
-  [PW] Added QUANTUM FIREBALLlct20 20 to knowndrives table.
-
-  [PW] Added Maxtor DiamondMax Plus D740X family to knowndrives table.
-
-  [PW] Added IBM Travelstar 32GH, 30GT, and 20GN family to knowndrives
-       table.
-
-  [BA] Slackware init script modified to search for /etc/slackware-version
-       rather than /etc/slackware-release.
-
-  [PW] Added Seagate Barracuda ATA II family and TOSHIBA MK4019GAXB to
-       knowndrives table.
-
-  [GG] explain howto use autoreconf in autogen.sh
-
-  [KS] Makefile.am/configure.in: changed manual page sections for
-       Solaris.
-
-  [BA] smartd: reduced number of scheduled self-test messages if
-       test already run in current hour.
-
-  [PW] Added Maxtor DiamondMax Plus 8 family to knowndrives table.
-
-  [BA] linux: check for linux/hdreg.h.  If it's there, use it. If
-       not, provide the necessary definitions ourselves.
-
-  [PW] Removed warning for IBM Deskstar 40GV & 75GXP series drives
-       with TXAOA5AA firmware
-
-  [PW] Added IBM Travelstar 25GS, 18GT, and 12GN family to knowndrives
-       table.
-
-  [PW] Added IBM/Hitachi Travelstar 60GH & 40GN family to knowndrives
-       table.
-
-  [BA] smartd: made '-s' Directive more efficient.  Now store
-       compiled regex, and re-use.  If device lacks certain self-test
-       capabilities, track it and don't try again.
-
-  [BA] smartd: made memory allocation for device lists completely
-       dynamic (eliminating compile-time maximum length constants).
-
-  [PW] Removed warning for SAMSUNG SP0802N with TK100-23 firmware
-
-  [PW] Added Seagate Barracuda ATA IV family to knowndrives table.
-
-  [BA] smartd: reduce per-device memory footprint by making
-       mail-warning info dynamically allocated.  Also remove
-       potential memory leak if use has -m Directive twice and
-       keeps reloading the config file (highly unlikely this would
-       ever be noticed!)  
-
-  [DG] smartd: added SCSI scheduled self-tests (Background
-       short or extended).
-
-  [BA] smartd: can now run scheduled offline immediate and
-       self-tests.  See man page and -s Directive for details.
-
-  [GG] don't include manpages in make-dist-tarball.
-
-  [BA] smartctl: on-line examples given with -h are now correct
-       for solaris and linux, but wrong for freebsd.  Ed?
-
-  [BA] smartd: man page now explains device scanning for solaris as
-       well as linux and freebsd.
-
-  [BA] smartd/smartctl: man pages now report correct CVS tag release
-       date, and executables '-V' options reports more build info.
-
-smartmontools 5.26
-
-  [BA] Improved user messages that appear from 'make install'
-
-  [PW] Removed warning for SAMSUNG SP1213N with firmware TL100-23
-
-  [BA] incorporated SuSE init script from user.
-
-  [DG] if SCSI device is read only, then open it read only.
-
-  [BA] when compiled on non-supported system (NOT linux, freebsd or solaris) then
-       the run-time error messages now clearly say 'your system is not supported'
-       and give clear directions.
-
-  [BA] ./configure script now works correctly on SuSE linux boxes
-
-  [BA] minor improvements to man pages
-
-  [BA] simplified detection of packet (ATAPI, CD) devices.
-
-  [BA] init script (redhat, mandrake, yellowdog) now uses correct
-       strings for translation and is slightly more standard.
-
-  [DG] smartctl: output scsi Seagate vendor pages for disks (not tapes)
-
-smartmontools 5.25
-
-Note: there was no '5.24' release. From this point on, even numbered
-releases will be 'stable' ones and odd numbered releases will be
-unstable/testing/development ones.
-
-  [DG] smartd/smartctl: changed scsiClearControlGLTSD() to
-       scsiSetControlGLTSD() with an 'enabled' argument so '-S on'
-       and '-S off' work for SCSI devices (if changing GLTSD supported).
-
-  [BA] smartd/smartctl: wired in scsiClearControlGLTSD(). Could still
-       use a corresponding Set function.  Left stubs for this purpose.
-
-  [DG] scsicmds: added scsiClearControlGLTSD() [still to be wired in]
-
-  [BA] smartctl: make SCSI -T options behave the same way as the
-       ATA ones.
-
-  [DG] smartctl: output scsi transport protocol if available
-
-  [DG] scsi: stop device scan in smartd and smartctl if badly formed
-       mode response [heuristic to filter out USB devices before we
-       (potentially) lock them up].
-
-  [BA] smartd: deviceclose()->CloseDevice(). Got rid of SCSIDEVELOPMENT
-       macro-enabled code.  Added -W to list of gcc specific options to
-       always enable. Made code clean for -W warnings.
-
-  [PW] Added Maxtor DiamondMax VL 30 family to knowndrives table.
-
-  [DG] scsi: add warning (when '-l error' active) if Control mode page
-       GLTSD bit is set (global disable of saving log counters)
-
-  [DG] scsi: remember mode sense cmd length. Output trip temperature
-       from IE lpage (IBM extension) when unavailable from temp lpage.
-
-  [BA] smartd: for both SCSI and ATA now warns user if either
-       the number of self-test errors OR timestamp of most
-       recent self-test error have increased.
-
-  [DG] smartctl: output Seagate scsi Cache and Factory log pages (if
-       available) when vendor attributes chosen
-
-  [DG] smartd: add scsiCountFailedSelfTests() function.
-
-  [DG] Do more sanity checking of scsi log page responses.
-
-  [BA] smartd: now warns user if number of self-test errors has
-       increased for SCSI devices.
-
-  [BA] smartd: warn user if number of ATA self-test errors increases
-       (as before) OR if hour time stamp of most recent self-test
-       error changes.
-
-  [DG] More checks for well formed mode page responses. This has the side
-       effect of stopping scans on bad SCSI implementations (e.g. some
-       USB disks) prior to sending commands (typically log sense) that
-       locks them up.
-
-  [PW] Added Western Digital Caviar family and Caviar SE family to
-       knowndrives table.
-
-  [BA] smartd: added -l daemon (which is the default value if -l
-       is not used).
-
-  [PW] Added Seagate Barracuda ATA V family to knowndrives table.
-
-  [BA] smartd: added additional command line argument -l FACILITY
-       or --logfacility FACILITY.  This can be used to redirect
-       messages from smartd to a different file than the one used
-       by other system daemons.
-
-  [PW] Added Seagate Barracuda 7200.7, Western Digital Protege WD400EB,
-       and Western Digital Caviar AC38400 to knowndrives table.
-
-  [BA] smartd: scanning should now also work correctly for
-       devfs WITHOUT traditional links /dev/hd[a-t] or /dev/sd[a-z].
-  
-  [PW] Added Maxtor 4W040H3, Seagate Barracuda 7200.7 Plus,
-       IBM Deskstar 120GXP (40GB), Seagate U Series 20410,
-       Fujitsu MHM2100AT, MHL2300AT, MHM2150AT, and IBM-DARA-212000
-       to knowndrives table.
-
-  [PW] Added remaining Maxtor DiamondMax Plus 9 models to knowndrives
-       table.
-
-  [EM] smartd: If no matches found, then return 0, rather than an error
-       indication, as it just means no devices of the given type exist.
-       Adjust FreeBSD scan code to mirror Linux version.
-
-  [BA] smartd: made device scan code simpler and more robust. If
-       too many devices detected, warn user but scan as many
-       as possible.  If error in scanning, warn user but don't
-       die right away.
-
-  [EM] smartd: To keep as consistent as possible, migrate FreeBSD
-       devicescan code to also use glob(3). Also verified clean 
-       compile on a 4.7 FreeBSD system.
-
-  [BA] smartd: Modified device scan code to use glob(3). Previously
-       it appeared to have trouble when scanning devices on an XFS
-       file system, and used non-public interface to directory
-       entries. Problems were also reported when /dev/ was on an
-       ext2/3 file system, but there was a JFS partition on the same
-       disk.
-
-  [BA] Clearer error messages when device scanning finds no suitable
-       devices.
-
-  [EM] FreeBSD:        Fixup code to allow for proper compilation under 
-       -STABLE branch.
-
-smartmontools 5.23
-
-  [BA] smartd: didn't close file descriptors of ATA packet devices
-       that are scanned. Fixed.
-
-  [BA] Added reload/report targets to the smartmontools init script.
-       reload: reloads config file
-       report: send SIGUSR1 to check devices now
-
-smartmontools 5.22
-
-  [EM] Fix compile issues for FreeBSD < 5-CURRENT.
-
-  [PW] Added Fujitsu MHM2200AT to knowndrives table.
-
-  [BA] To help catch bugs, clear ATA error structures before all
-       ioctl calls.  Disable code that attempted to time-out on SCSI
-       devices when they hung (doesn't work).
-  [BA] Documented STATUS/ERROR flags added by [PW] below.
-
-  [BA] Improved algorithm to recognize ATA packet devices. Should
-       no longer generate SYSLOG kernel noise when user tries either
-       smartd or smartctl on packet device (CD-ROM or DVD).  Clearer
-       warning messages from smartd when scanning ATA packet device.
-
-  [PW] Added TOSHIBA MK4025GAS to knowndrives table.
-
-  [PW] Added a textual interpretation of the status and error registers
-       in the SMART error log (ATA).  The interpretation is
-       command-dependent and currently only eight commands are supported
-       (those which produced errors in the error logs that I happen to
-       have seen).
-
-  [BA] added memory allocation tracking to solaris code.
-       Fixed solaris signal handling (reset handler to default
-       after first call to handler) by using sigset. Added
-       HAVE_SIGSET to configure.in
-
-  [CD] solaris port: added SCSI functionality to solaris
-       stubs.
-
-  [BA] smartd: attempt to address bug report about smartd
-       hanging on USB devices when scanning:
-       https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=107615
-       Set a timeout of SCSITIMEOUT (nominally 7 seconds) before
-       giving up.
-
-  [EM] smartd: DEVICESCAN will follow links in a devfs filesystem and
-       make sure the end point is a disc.  Update documentation, added
-       note about FreeBSD scanning
-
-  [BA] smartd: DEVICESCAN also looks for block devices in
-       /dev.  Updated documentation.  Now scans for up to
-       20 ATA devices /dev/hda-t rather than previous 12
-       /dev/hda-l.
-
-  [EM] smartd: mirror the FreeBSD DEVICESCAN logic for Linux,
-       so that smartd now scans only devices found in /dev/. Also,
-       make utility memory functions take a line number and file so
-       that we report errors with the correct location.
-  [GG] add a note about Debian bug #208964 to WARNINGS.
-
-  [BA] smartctl: -T verypermissive option broken.  Use
-       -T verpermissive until the next release, please.
-
-  [BA] Syntax mods so that code also compiles on Solaris using
-       Sun Workshop compiler.  Need -xmemalign 1i -xCC flags
-       for cc.
-
-smartmontools 5.21
-
-  [DK] Changed configure.in so -Wall is only included if gcc
-       is used (this is a gcc specific flag) and -fsignedchar
-       is not used at all (this is a gcc specific compiler 
-       flag).
-
-  [BA] Modifications so that code now compiles under solaris. Now
-       all that's needed (:-) is to fill in os_solaris.[hc].  Added
-       os_generic.[hc] as guide to future ports.  Fixed -D option
-       of smartd (no file name).  Modified -h opt of smartd/smartctl
-       to work properly with solaris getopt().
-
-  [EM] Update MAN pages with notes that 3ware drives are NOT supported
-       under FreeBSD. Cleanup FreeBSD warning message handling.
-
-  [EM] FreeBSD only: Fix first user found bug....I guess I was making
-       the wrong assumption on how to convert ATA devnames to
-       channel/unit numbers.
-  
-  [EM] Allow for option --enable-sample to append '.sample' to installed
-       smartd.conf and rc script files. Also, let rc script shell setting
-       be determined by configure
-
-  [EM] Minor autoconf update to include -lcam for FreeBSD
-
-  [EM] Add conditional logic to allow FreeBSD to compile pre-ATAng.
-       -- note, not tested
-       Add some documentation to INSTALL for FreeBSD.
-
-  [EM] Implement SCSI CAM support for FreeBSD.  NOTE: I am not an expert
-       in the use of CAM.  It seems to work for me, but I may be doing
-       something horribly wrong, so please exercise caution.
-
-  [EM] Switch over to using 'atexit' rather than 'on_exit' routine. This also
-       meant we needed to save the exit status elsewhere so our 'Goodbye'
-       routine could examine it.
-
-  [EM] Move the DEVICESCAN code to os specific files. Also moved some of the
-       smartd Memory functions to utility.c to make available to smartctl.
-
-  [EM] Code janitor work on os_freebsd.c.
-
-  [EM] Added os_freebsd.[hc] code.  Additional code janitor
-       work.
-
-  [BA] Code janitor working, moving OS dependent code into
-       os_linux.[hc].
-
-  [GG] conditionally compile os_{freebsd,linux}.o depending on
-       host architecture
-
-  [PW] Print estimated completion time for tests
-
-  [BA] Added -F samsung2 flag to correct firmware byte swap.
-       All samsung drives with *-23 firmware revision string.
-
-smartmontools 5.20
-
-  [GG] Fixed broken Makefile.am (zero length smartd.conf.5
-       was being created), fix broken uninstall/distcheck targets
-
-  [FM] Improved Slackware init script added to /etc/smartd.initd
-
-smartmontools 5.19 [NOTE CHANGE OF RELEASE NUMBERING]
-
-  [BA] smartctl: added '-T verypermissive' option which is
-       equivalent to giving '-T permissive' many times.
-
-  [BA] Try harder to identify from IDENTIFY DEVICE structure
-       if SMART supported/enabled.  smartd now does a more
-       thorough job of trying to assess this before sending
-       a SMART status command to find out for sure.
-
-  [BA] smartctl: it's now possible to override the program's
-       guess of the device type (ATA or SCSI) with -d option.
-
-  [BA] try hard to avoid sending IDENTIFY DEVICE to packet
-       devices (CDROMS).  They can't do SMART, and this generates
-       annoying syslog messages. At the same time, identify type
-       of Packet device.
-
-  [BA] smartctl: Can now use permissive option more
-       than once, to control how far to go before giving up.
-
-  [BA] smartd: if user asked to monitor either error or self-test
-       logs (-l error or -l selftest) WITHOUT monitoring any of the
-       Attribute values, code will SEGV.  For 5.1-18 and earlier,
-       a good workaround is to enable Auto offline (-o on).
-
-  [BA] smartctl: If enable auto offline command given, update auto
-       offline status before printing capabilities.
-
-  [GG] Make autotools build the default, remove autotools.diff
-
-  [GG] Add auto{conf,make} support, not enabled by default. 
-
-  [BA] Eliminated #include <linux/hdreg.h> from code. This
-       should simplify porting to solaris, FreeBSD, etc. The
-       only linux-specific code is now isolated to three routines,
-       one for SCSI, one for Escalade, one for ATA.
-
-smartmontools 5.1-18
-
-  [BA] smartd: fixed serious bug - Attributes not monitored unless
-       user told smartd to ignore at least one of them!
-
-smartmontools 5.1-17
-
-  [BA] Default runlevels for smartd changed from 3 and 5 to
-       2, 3, 4, and 5.
-
-  [BA] Removed as much dynamic memory allocation as possible from
-       configuration file parsing. Reloading config file, even in
-       presence of syntax errors etc. should not cause memory leaks.
-
-  [PW] It is no longer permissible for the integer part (if any) of
-       arguments to --report and --device to be followed by non-digits.
-       For example, the "foo" in --report=ioctl,2foo was previously
-       ignored, but now causes an error.
-
-  [BA] smartd: added -q/--quit command line option to specify
-       under what circumstances smartd should exit.  The old
-       -c/--checkonce option is now obsoleted by this more
-       general-purpose option.
-
-  [BA] smartd now responds to a HUP signal by re-reading its
-       configuration file /etc/smartd.conf.  If there are
-       errors in this file, then the configuration file is
-       ignored and smartd continues to monitor the devices that
-       it was monitoring prior to receiving the HUP signal.
-
-  [BA] Now correctly get SMART status from disks behind 3ware
-       controllers, thanks to Adam Radford. Need 3w-xxxx driver
-       version 1.02.00.037 or later. Previously the smartmontools
-       SMART status always returned "OK" for 3ware controllers.
-
-  [BA] Additional work on dynamic memory allocation/deallocation.
-       This should have no effect on smartctl, but clears that way
-       for smartd to dynamically add and remove entries.  It should
-       also now be easier to modify smartd to re-read its config
-       file on HUP (which is easy) without leaking memory (which is
-       harder). The philosophy is that memory for data structures in
-       smartd is now allocated only on demand, the first time it
-       is needed.
-
-  [BA] smartd: finished cleanup.  Now use create/rm functions for
-       cfgentries and dynamic memory allocation almost everywhere.
-       Philosophy: aggresively try and provoke SEGV to help find
-       bad code.
-
-  [BA] Added SAMSUNG SV0412H to knowndrives table.
-
-  [BA] smartd: if DEVICESCAN used then knowndrives table might not set
-       the -v attributes correctly -- may have been the same for all
-       the drives.  Cleaned up some data structures and memory
-       allocation to try and ensure segvs if such problems are 
-       introduced again.
-
-  [BA] Now allow -S on and -o on for the 3ware device type.  For these
-       commands to be passed through, the stock 3ware 3w-xxxx driver
-       must be patched (8 lines).  I'll post a patch on the smartmontools
-       home page after it's been tested by a few other people and 3ware
-       have had a chance to look it over.
-
-smartmontools-5.1-16
-
-  [BA] smartd - can now monitor ATA drives behind 3ware controllers.
-
-  [BA] smartd - changed some FATAL out of memory error messages from
-       syslog level LOG_INFO to LOG_CRIT.
-
-  [BA] smartctl - added code to look at ATA drives behind 3ware RAID
-       controllers using the 3w-xxxx driver.  Note that for technical
-       reasons related to the 3w-xxxx driver, the "Enable Autosave",
-       "Enable Automatic Offline" commands are not implemented.
-       I will add this to smartd shortly.
-
-  [BA] smartd - modified sleep loop, so that smartd no longer comes
-       on the run queue every second.  Instead, unless interrupted,
-       it sleeps until the next polling time, when it wakes up. Now
-       smartd also tries to wake up at exactly the right
-       intervals (nominally 30 min) even if the user has been sending
-       signals to it.
-
-  [GG] add Fujitsu MHN2300AT to vendoropts_9_seconds.
-
-  [EB] Fujitsu change in knowndrives ... match the whole MPD and
-       MPE series for vendoropts_9_seconds.
-
-  [BA] smartd bug, might cause segv if a device can not be opened. Was
-       due to missing comma in char* list.  Consequence is that email
-       failure messages might have had the wrong Subject: heading for
-       errorcount, FAILEDhealthcheck, FAILEDreadsmartdata, FAILEDreadsmarterrorlog,
-       FAILEDreadsmartsefltestlog, FAILEDopendevice were all displaced by
-       one.  And FAILEDopendevice might have caused a segv if -m was being
-       used as a smartd Directive.
-
-smartmontools-5.1-15
-
-  [BA] Cleaned up smartmontools.spec so that upgrading, removing
-       and other such operations correctly preserve running behavior
-       and booting behavior of smartd.
-
-  [BA] Improved formatting of ATA Error Log printout, and added
-       listing of names of commands that caused the error. Added
-       obsolete ATA-4 SMART feature commands to table, along with
-       obsolete SFF-8035i SMART feature command.
-
-  [PW] Added atacmdnames.[hc], which turn command register &
-       feature register pairs into ATA command names.
-
-  [BA] Added conveyance self-test.  Some code added for selective
-       self-tests, but #ifdefed out.
-
-  [BA] Modified smartd exit status and log levels.  If smartd is
-       "cleanly" terminated, for example with SIGTERM, then its
-       exit messages are now logged at LOG_INFO not LOG_CRIT
-
-  [BA] Added Attribute IDs  (Fujitsu) 0xCA - 0xCE.  This is decimal
-       202-206. Added -v switches for interpretation of Attributes
-       192, 198 and 201. 
-
-  [BA] Made smartmontools work with any endian order machine for:
-       - SMART selftest log
-       - SMART ATA error log
-       - SMART Attributes values
-       - SMART Attributes thesholds
-       - IDENTIFY DEVICE information
-       - LOG DIRECTORY
-       Smartmontools is now free of endian bias and works correctly
-       on both little- and big-endian hardware.  This has been tested by
-       three independent PPC users on a variety of ATA and SCSI hardware.
-
-  [DG] Check that certain SCSI command responses are well formed. If
-       IEC mode page response is not well formed exit smartctl. This
-       is to protect aacraid. smartd should ignore a aacraid device.
-
-smartmontools-5.1-14
-
-  [BA] smartctl: added column to -A output to show if Attributes are
-       updated only during off-line testing or also during normal
-       operation.
-
-smartmontools-5.1-13
-
-  [BA] smartd: attempt to enable/disable automatic offline testing even
-       if the disk appears not to support it.  Now the same logic
-       as smartctl.
-
-  [BA] Added definition of Attribute 201, soft read error rate.
-
-  [BA] Added IBM/Hitachi IC35L120AVV207-1 (GXP-180) and corresponding
-       8MB Cache GXP-120 to drive database.
-
-  [BA] smartd: if DEVICESCAN Directive used in smartd.conf, and
-       -I, -R or -r Directives used in conjunction with this, got
-       segv errors.  Fixed by correcting memory allocation calls.
-
-  [BA] smartd: enable automatic offline testing was broken due
-       to cut-and-paste error that disabled it instead of
-       enabling it.  Thanks to Maciej W. Rozycki for pointing
-       out the problem and solution.
-
-  [BA] Fixed "spelling" of some Attribute names to replace spaces
-       in names by underscores. (Fixed field width easier for awk
-       style parsing.)
-
-  [BA,GF] Added mods submitted by [GF] to support Attribute 193 being
-       load/unload cycles. Add -v 193,loadunload option, useful for
-       Hitachi drive DK23EA-30, and add this drive to knowndrive.c
-       Add meaning of attribute 250 : Read error retry rate
-
-smartmontools-5.1-12
-
-  [BA] Added another entry for Samsung drives to knowndrive table.
-
-  [DG] Refine SCSI log sense command to do a double fetch in most cases
-       (but not for the TapeAlert log page). Fix TapeAlert and Self Test
-       log page response truncation.
-
-  [PW] Added 'removable' argument to -d Directive for smartd.  This indicates
-       that smartd should continue (rather than exit) if the device does not 
-       appear to be present.
-
-  [BA] Modified smartmontools.spec [Man pages location] and
-       smartd.initd [Extra space kills chkconfig!] for Redhat 6.x
-       compatibility (thanks to Gerald Schnabel).
-
-smartmontools-5.1-11
-
-  [EB] Add another Fujitsu disk to knowndrives.c
-
-  [GG] match for scsi/ and ide/ in case of devfs to exclude false postives
-
-  [BA] If SCSI device listed in /etc/smartd.conf fails to open or do
-       SMART stuff correctly, or not enough space
-       to list all SCSI devices, fail with error unless
-       -DSCSIDEVELOPMENT set during compile-time.
-
-  [BA] Added automatic recognition of /dev/i* (example: /dev/ide/...)
-       as an ATA device.
-
-  [DG] Add "Device type: [disk | tape | medium changer | ...] line to
-       smartctl -i output for SCSI devices.
-
-  [PW] Fixed bug in smartd where test email would be sent regularly (for
-       example, daily if the user had specified -M daily) instead of just
-       once on startup.
-
-  [KM] More TapeAlert work. Added translations for media changer
-       alerts. TapeAlert support reported according to the log page
-       presence. ModeSense not attempted for non-ready tapes (all
-       drives do not support this after all). Get peripheral type from
-       Inquiry even if drive info is not printed. Add QUIETON()
-       QUIETOFF() to TapeAlert log check.
-
-  [BA] Stupid bug in atacmds.c minor_str[] affected ataVersionInfo().
-       Two missing commas meant that minor_str[] had two few elements,
-       leading to output like this:
-       Device Model:     Maxtor 6Y120L0
-       Serial Number:    Y40BF74E
-       Firmware Version: YAR41VW0
-       Device is:        Not in smartctl database [for details use: -P showall]
-       ATA Version is:   7
-       ATA Standard is:  9,minutes
-                         ^^^^^^^^^
-       Missing commas inserted.
-
-  [BA] Fixed smartd bug.  On device registration, if ATA device did
-       not support SMART error or self-test logs but user had asked to
-       monitor them, an attempt would be made to read them anyway,
-       possibly generating "Drive Seek" errors.  We now check that
-       the self-test and error logs are supported before trying to
-       access them the first time.
-
-  [GG/BA] Fixed bug where if SMART ATA error log not supported,
-       command was tried anyway. Changed some error printing to use
-       print handlers.
-
-  [GG] Makefile modifications to ease packaging
-
-  [DG] Did work for TapeAlerts (SCSI). Now can detect /dev/nst0 as a
-       SCSI device. Also open SCSI devices O_NONBLOCK so they don't
-       hang on open awaiting media. The ATA side should worry about
-       this also: during a DEVICESCAN a cd/dvd device without media
-       will hang. Added some TapeAlert code suggested by Kai Makisara.
-
-smartmontools-5.1-10
-
-  [PW] Extended the -F option/Directive to potentially fix other firmware
-       bugs in addition to the Samsung byte-order bug.  Long option name is
-       now --firmwarebug and the option/Directive accepts an argument
-       indicating the type of firmware bug to fix.
-
-  [BA] Fixed a bug that prevented the enable automatic off-line
-       test feature from enabling.  It also prevented the enable Attribute
-       autosave from working.  See CVS entry for additional details.
-
-  [PW] Modified the -r/--report option (smartctl and smartd) to allow the
-       user to specify the debug level as a positive integer.
-
-  [BA] Added --log directory option to smartctl.  If the disk
-       supports the general-purpose logging feature set (ATA-6/7)
-       then this option enables the Log Directory to be printed.
-       This Log Directory shows which device logs are available, and
-       their lengths in sectors.
-
-  [PW] Added -P/--presets option to smartctl and -P Directive to smartd.
-
-  [GG] Introduce different exit codes indicating the type of problem
-       encountered for smartd.
-
-  [DG] Add non-medium error count to '-l error' and extended self test
-       duration to '-l selftest'. Get scsi IEs and temperature changes
-       working in smartd. Step over various scsi disk problems rather
-       than abort smartd startup.
-
-  [DG] Support -l error for SCSI disks (and tapes). Output error counter
-       log pages.
-
-  [BA] Added -F/--fixbyteorder option to smartctl.  This allows us to read
-       SMART data from some disks that have byte-reversed two- and four-
-       byte quantities in their SMART data structures.
-
-  [BA] Fixed serious bug: the -v options in smartd.conf were all put
-       together and used together, not drive-by-drive.
-
-  [PW] Added knowndrives.h and knowndrives.c.  The knowndrives array
-       supersedes the drivewarnings array.
-
-  [GG] add {-p,--pidfile} option to smartd to write a PID file on
-       startup. Update the manpage accordingly.
-
-  [DG] Fix scsi smartd problem detecting SMART support. More cleaning
-       and fix (and rename) scsiTestUnitReady(). More scsi renaming.
-
-  [BA] Fixed smartd so that if a disk that is explictily listed is not
-       found, then smartd will exit with nonzero status BEFORE forking.
-       If a disk can't be registered, this will also be detected before
-       forking, so that init scripts can react correctly.
-
-  [BA] Replaced all linux-specific ioctl() calls in atacmds.c with
-       a generic handler smartcommandhandler().  Now the only routine
-       that needs to be implemented for a given OS is os_specific_handler().
-       Also implemented the --report ataioctl. This provides 
-       two levels of reporting.  Using the option once gives a summary
-       report of device IOCTL transactions.  Using the option twice give
-       additional info (a printout of ALL device raw 512 byte SMART
-       data structures).  This is useful for debugging.
-
-  [DG] more scsi cleanup. Output scsi device serial number (VPD page
-       0x80) if available as part of '-i'. Implement '-t offline' as
-       default self test (only self test older disks support).
-
-  [BA] Changed crit to info in loglevel of smartd complaint to syslog
-       if DEVICESCAN enabled and device not found.
-
-  [BA] Added -v 194,10xCelsius option/Directive. Raw Attribute number
-       194 is ten times the disk temperature in Celsius.
-
-  [DG] scsicmds.[hc] + scsiprint.c: clean up indentation, remove tabs.
-       Introduce new intermediate interface based on "struct scsi_cmnd_io"
-       to isolate SCSI generic commands + responses from Linux details;
-       should help port to FreeBSD of SCSI part of smartmontools.
-       Make SCSI command builders more parametric.
-
-smartmontools-5.1-9
-  
-  [BA] smartctl: if HDIO_DRIVE_TASK ioctl() is not implemented (no
-       kernel support, then try to assess drive health by examining
-       Attribute values/thresholds directly.
-
-  [BA] smartd/smartctl: added -v 200,writeerrorcount option/Directive
-       for Fujitsu disks.
-
-  [BA] smartd: Now send email if any of the SMART commands fails,
-       or if open()ing the device fails.  This is often noted
-       as a common disk failure mode.
-
-  [BA] smartd/smartctl: Added -v N,raw8 -v N,raw16 and -v N,raw48
-       Directives/Options for printing Raw Attributes in different
-       Formats.
-
-  [BA] smartd: Added -r ID and -R ID for reporting/tracking Raw
-       values of Attributes.
-
-  [BA] smartd/smartctl: Changed printing of spin-up-time attribute
-       raw value to reflect current/average as per IBM standard.
-
-  [BA] smartd/smartctl: Added -v 9,seconds option for disks which
-       use Attribute 9 for power-on lifetime in seconds.
-
-  [BA] smartctl: Added a warning message so that users of some IBM
-       disks are warned to update their firmware.  Note: we may want
-       to add a command-line flag to disable the warning messages.
-       I have done this in a general way, using regexp, so that we
-       can add warnings about any type of disk that we wish...
-
-smartmontools-5.1-7
-
-  [BA] smartd: Created a subdirectory examplescripts/ of source
-       directory that contains executable scripts for the -M exec PATH
-       Directive of smartd.
-
-smartmontools-5.1-5
-
-  [BA] smartd: DEVICESCAN in /etc/smartd.conf
-       can now be followed by all the same Directives as a regular
-       device name like /dev/hda takes.  This allows one to use
-       (for example):
-       DEVICESCAN -m root@example.com
-       in the /etc/smartd.conf file.
-
-  [BA] smartd: Added -c (--checkonce) command-line option. This checks
-       all devices once, then exits.  The exit status can be
-       used to learn if devices were detected, and if smartd is
-       functioning correctly. This is primarily for Distribution
-       scripters.
-
-  [BA] smartd: Implemented -M exec Directive for
-       smartd.conf.  This makes it possible to run an
-       arbitrary script or mailing program with the
-       -m option.
-
-  [PW] smartd: Modified -M Directive so that it can be given
-       multiple times.  Added -M exec Directive.
-
-smartmontools-5.1-4
-
-  [BA] Fixed bug in smartctl pointed out by Pierre Gentile.
-       -d scsi didn't work because tryata and tryscsi were
-       reversed -- now works on /devfs SCSI devices.
-
-  [BA] Fixed bug in smartctl pointed out by Gregory Goddard
-       <ggoddard@ufl.edu>.  Manual says that bit 6 of return
-       value turned on if errors found in smart error log.  But
-       this wasn't implemented.
-
-smartmontools-5.1-3
-
-  [BA] Modified printing format for 9,minutes to read
-       Xh+Ym not X h + Y m, so that fields are fixed width.
-
-  [BA] Added Attribute 240 "head flying hours"
-
-smartmontools-5.1.1
-
-  [BA] As requested, local time/date now printed by smartctl -i
-
-  [PW] Added "help" argument to -v for smartctl
-
-  [PW] Added -D, --showdirectives option to smartd
-
-  [DG] add '-l selftest' capability for SCSI devices (update smartctl.8)
-
-  [BA] smartd,smartctl: added additional Attribute modification option
-       -v 220,temp and -v 9,temp.
-
-  [PW] Renamed smartd option -X to -d
-
-START OF SMARTMONTOOLS 5.1 series
-
-smartmontools-5.0.50
-
-  [PW] Changed smartd.conf Directives -- see man page
-
-  [BA/DG] Fixed uncommented comment in smartd.conf
-
-  [DG] Correct 'Recommended start stop count' for SCSI devices
-
-  [PW] Replaced smartd.conf directive -C with smartd option -i
-
-  [PW] Changed options for smartctl -- see man page.
-
-  [BA] Use strerror() to generate system call error messages.
-
-  [BA] smartd: fflush() all open streams before fork().
-
-  [BA] smartctl, smartd simplified internal handling of checksums
-  for simpler porting and less code.
-
-smartmontools-5.0.49
-
-  [PW] smartd --debugmode changed to --debug
-
-  [BA] smartd/smartctl added attribute 230 Head Amplitude from
-  IBM DPTA-353750.
-
-  [PW] Added list of proposed new options for smartctl to README.
-
-  [PW] smartd: ParseOpts() now uses getopt_long() if HAVE_GETOPT_LONG is
-  defined and uses getopt() otherwise.  This is controlled by CPPFLAGS in
-  the Makefile.
-
-  [BA] smartd: Fixed a couple of error messages done with perror()
-  to redirect them as needed.
-
-smartmontools-5.0.48
-
-  [BA] smartctl: The -O option to enable an Immediate off-line test
-  did not print out the correct time that the test would take to
-  complete.  This is because the test timer is volatile and not
-  fixed.  This has been fixed, and the smartctl.8 man page has been
-  updated to explain how to track the Immediate offline test as it
-  progresses, and to further emphasize the differences between the
-  off-line immediate test and the self-tests.
-
-  [BA] smartd/smartctl: Added new attribute (200) Multi_Zone_Error_Rate
-
-  [BA] smartctl: modified so that arguments could have either a single -
-  as in -ea or multiple ones as in -e -a.  Improved warning message for
-  device not opened, and fixed error in redirection of error output of
-  HD identity command.
-
-  [PW] smartd: added support for long options.  All short options are still
-  supported; see manpage for available long options.
-
-  [BA] smartctl.  When raw Attribute value was 2^31 or larger, did
-  not print correctly.
-
-smartmontools-5.0.46
-
-  [BA] smartd: added smartd.conf Directives -T and -s.  The -T Directive
-  enables/disables Automatic Offline Testing.  The -s Directive
-  enables/disables Attribute Autosave. Documentation and
-  example configuration file updated to agree.
-
-  [BA] smartd: user can make smartd check the disks at any time
-  (ie, interrupt sleep) by sending signal SIGUSR1 to smartd.  This
-  can be done for example with:
-  kill -USR1 <pid>
-  where <pid> is the process ID number of smartd.
-
-  [EB] scsi: don't trust the data we receive from the drive too
-  much. It very well might have errors (like zero response length).
-  Seen on Megaraid logical drive, and verified in the driver source.
-
-  [BA] smartd: added Directive -m for sending test email and
-  for modifying email reminder behavior.  Updated manual, and sample
-  configuration file to illustrate & explain this.
-
-  [BA] smartd: increased size of a continued smartd.conf line to
-  1023 characters.
-
-  [BA] Simplified Directive parsers and improved warning/error
-  messages.
-
-smartmontools-5.0.45
-
-  [EB] Fixed bug in smartd where testunitready logic inverted
-  prevented functioning on scsi devices.
-  The bug in question only affects smartd users with scsi devices.
-  To see if your version of smartd has the testunitready() bug, do
-     smartd -V
-  If the version of the module smartd.c in a line like:
-     Module: smartd.c      revision: 1.66   date: 2002/11/17
-  has a revision greater than or equal to 1.30, and less than or equal to
-  1.64, then your version of the code has this problem.
-  This problem affected releases starting with RELEASE_5_0_16 up to and
-  including RELEASE_5_0_43.
-
-  [BA] Added testunitnotready to smartctl for symmetry with smartd.
-
-  [SB] added Czech descriptions to .spec file
-  [SB]  corrected comment in smartd.conf example
-
-  [BA] Changed way that entries in the ATA error log are printed,
-  to make it clearer which is the most recent error and
-  which is the oldest one.
-
-  NOTE: All changes made prior to this point were done by Bruce Allen
-  [BA] although several of them had been suggested by earlier postings
-  by Stanislav Brabec [SB].
-
-smartmontools-5.0.43
-
-  Changed Temperature_Centigrade to Temperature_Celsius.
-  The term "Centigrade" ceased to exist in 1948.  (c.f
-  http://www.bartleby.com/64/C004/016.html).
-
-smartmontools-5.0.42
-
-  Modified SCSI device check to also send warning emails if
-  requested in directives file.
-
-  Added a new smartd configuration file Directive: -M ADDRESS.
-  This sends a single warning email to ADDRESS for failures or
-  errors detected with the -c, -L, -l, or -f Directives.
-
-smartmontools-5.0.38
-
-  Modified perror() statements in atacmds.c so that printout for SMART
-  commands errors is properly suppressed or queued depending upon users
-  choices for error reporting modes.
-
-  Added Italian descriptions to smartmontools.spec file.
-
-  Started impementing send-mail-on-error for smartd; not yet enabled.
-
-  Added -P (Permissive) Directive to smartd.conf file to allow SMART
-  monitoring of pre-ATA-3 Rev 4 disks that have SMART but do not have
-  a SMART capability bit.
-  Removed charset encodings from smartmontools.spec file for non-English
-  fields.
-
-smartmontools-5.0.32
-
-  Added manual page smartd.conf.5 for configuration file.
-
-  smartctl: Missing ANSI prototype in failuretest(); fixed.
-
-  smartctl: Checksum warnings now printed on stdout, or are silent,
-  depending upon -q and -Q settings.
-
-smartmontools-5.0.31
-
-  Changed Makefile so that the -V option does not reflect file state
-  before commit!
-
-  smartctl: added new options -W, -U, and -P to control if and how the
-  smartctl exits if an error is detected in either a SMART data
-  structure checksum, or a SMART command returns an error.
-
-  modified manual page to break options into slightly more logical
-  categories.
-
-  reformatted 'usage' message order to agree with man page ordering
-
-  modified .spec file so that locale information now contains
-  character set definition.   Changed pt_BR to pt since we do not use any
-  aspect other than language.  See man setlocale.
-
-smartmontools-5.0.30
-  smartctl: added new options -n and -N to force device to be ATA or SCSI
-  smartctl: no longer dies silently if device path does not start/dev/X
-  smartctl: now handles arbitrary device paths
-
-smartmontools-5.0.29
-  Modified .spec file and Makefile to make them more compliant with
-  the "right" way of doing things.
-
-smartmontools-5.0.26
-  Fixed typesetting error in man page smartd.8
-
-  Removed redundant variable (harmless) from smartd.c
-
-smartmontools-5.0.25
-
-  Added a new directive for the configuration file.  If the word
-  DEVICESCAN appears before any non-commented material in the
-  configuration file, then the confi file will be ignored and the
-  devices wil be scanned.
-
-smartmontools-5.0.24
-
-    Note: it has now been confirmed that the code modifications between
-    5.0.23 and 5.0.24 have eliminated the GCC 3.2 problems.  Note that
-    there is a GCC bug howerver, see #8404 at
-    http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=query
-    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8404
-
-      Added new Directive for Configuration file:
-      -C <N> This sets the time in between disk checks to be <N>
-      seconds apart.  Note that  although  you  can  give
-       this Directive multiple times on different lines of
-       the configuration file, only the final  value  that
-       is  given  has  an  effect,  and applies to all the
-       disks.  The default value of <N> is 1800  sec,  and
-       the minimum allowed value is ten seconds.
-
-    Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net>
-    sent me a gcc 3.2 build and I ran it under a debugger.  The
-    problem seems to be with passing the very large (2x512+4) byte
-    data structures as arguments.  I never liked this anyway; it was
-    inherited from smartsuite.  So I've changed all the heavyweight
-    functions (ATA ones, anyone) to just passing pointers, not hideous
-    kB size structures on the stack.  Hopefully this will now build OK
-    under gcc 3.2 with any sensible compilation options.
-
-smartmontools-5.0.23
-
-    Because of reported problems with GCC 3.2 compile, I have gone
-    thorough the code and explicitly changed all print format
-    parameters to correspond EXACTLY to int unless they have to be
-    promoted to long longs.  To quote from the glibc bible: [From
-    GLIBC Manual: Since the prototype doesn't specify types for
-    optional arguments, in a call to a variadic function the default
-    argument promotions are performed on the optional argument
-    values. This means the objects of type char or short int (whether
-    signed or not) are promoted to either int or unsigned int, as
-    appropriate.]
-
-smartmontools-5.0.22
-
-    smartd, smartctl now warn if they find an attribute whose ID
-    number does not match between Data and Threshold structures.
-
-    Fixed nasty bug which led to wrong number of arguments for a
-    varargs statement, with attendent stack corruption.  Sheesh!
-    Have added script to CVS attic to help find such nasties in the
-    future.
-
-smartmontools-5.0.21
-
-    Eliminated some global variables out of header files and other
-    minor cleanup of smartd.
-
-smartmontools-5.0.20
-
-    Did some revision of the man page for smartd and made the usage
-    messages for Directives 100% consistent.
-
-smartmontools-5.0-19
-
-    smartd: prints warning message when it gets SIGHUP, saying that it
-    is NOT re-reading the config file.
-
-    smartctl: updated man page to say self-test commands -O,x,X,s,S,A
-    appear to be supported in the code.  [I can't test these,  can anyone
-    report?]
-
-smartmontools-5.0-18
-
-    smartctl: smartctl would previously print the LBA of a self-test
-    if it completed, and the LBA was not 0 or 0xff...f However
-    according to the specs this is not correct.  According to the
-    specs, if the self-test completed without error then LBA is
-    undefined.  This version fixes that.  LBA value only printed if
-    self-test encountered an error.
-
-smartmontools-5.0-17
-
-    smartd has changed significantly. This is the first CVS checkin of
-    code that extends the options available for smartd.  The following
-    options can be placed into the /etc/smartd.conf file, and control the
-    behavior of smartd.
-    Configuration file Directives (following device name):
-    -A     Device is an ATA device
-    -S     Device is a SCSI device
-    -c     Monitor SMART Health Status
-    -l     Monitor SMART Error Log for changes
-    -L     Monitor SMART Self-Test Log for new errors
-    -f     Monitor for failure of any 'Usage' Attributes
-    -p     Report changes in 'Prefailure' Attributes
-    -u     Report changes in 'Usage' Attributes
-    -t     Equivalent to -p and -u Directives
-    -a     Equivalent to -c -l -L -f -t Directives
-    -i ID  Ignore Attribute ID for -f Directive
-    -I ID  Ignore Attribute ID for -p, -u or -t Directive
-    #      Comment: text after a hash sign is ignored
-    \      Line continuation character
-
-    cleaned up functions used for printing CVS IDs.  Now use string
-    library, as it should be.
-
-    modified length of device name string in smartd internal structure
-    to accomodate max length device name strings
-
-    removed un-implemented (-e = Email notification) option from
-    command line arg list.  We'll put it back on when implemeneted.
-
-    smartd now logs serious (fatal) conditions in its operation at
-    loglevel LOG_CRIT rather than LOG_INFO before exiting with error.
-
-    smartd used to open a file descriptor for each SMART enabled
-    device, and then keep it open the entire time smartd was running.
-    This meant that some commands, like IOREADBLKPART did not work,
-    since the fd to the device was open.  smartd now opens the device
-    when it needs to read values, then closes it.  Also, if one time
-    around it can't open the device, it simply prints a warning
-    message but does not give up.  Have eliminated the .fd field from
-    data structures -- no longer gets used.
-
-    smartd now opens SCSI devices as well using O_RDONLY rather than
-    O_RDWR.  If someone can no longer monitor a SCSI device that used
-    to be readable, this may well be the reason why.
-
-    smartd never checked if the number of ata or scsi devices detected
-    was greater than the max number it could monitor.  Now it does.
-
-smartmontools-5.0-16
-
-    smartd on startup now looks in the configuration file /etc/smartd.conf for
-    a list of devices which to include in its monitoring list.  See man page
-    (man smartd) for syntax.
-
-    smartd: close file descriptors of SCSI device if not SMART capable
-    Closes ALL file descriptors after forking to daemon.
-
-    added new temperature attribute (231, temperature)
-
-    smartd: now open ATA disks using O_RDONLY
-
-smartmontools-5.0-11
-
-    smartd now prints the name of a failed or changed attribute
-    into logfile, not just ID number
-
-    Changed name of -p (print version) option to -V
-
-    Minor change in philosophy: if a SMART command fails or the device
-    appears incapable of a SMART command that the user has asked for,
-    complain by printing an error message, but go ahead and try
-    anyway.  Since unimplemented SMART commands should just return an
-    error but not cause disk problems, this should't cause any
-    difficulty.
-
-    Added two new flags: q and Q.  q is quiet mode - only print: For
-    the -l option, errors recorded in the SMART error log; For the -L
-    option, errors recorded in the device self-test log; For the -c
-    SMART "disk failing" status or device attributes (pre-failure or
-    usage) which failed either now or in the past; For the -v option
-    device attributes (pre-failure or usage) which failed either now
-    or in the past.  Q is Very Quiet mode: Print no ouput.  The only
-    way to learn about what was found is to use the exit status of
-    smartctl.
-
-    smartctl now returns sensible values (bitmask).  See smartctl.h
-    for the values, and the man page for documentation.
-
-    The SMART status check now uses the correct ATA call.  If failure
-    is detected we search through attributes to list the failed ones.
-    If the SMART status check shows GOOD, we then look to see if their
-    are any usage attributes or prefail attributes have failed at any
-    time.  If so we print them.
-
-    Modified function that prints vendor attributes to say if the
-    attribute has currently failed or has ever failed.
-
-    -p option now prints out license info and CVS strings for all
-    modules in the code, nicely formatted.
-
-    Previous versions of this code (and Smartsuite) only generate
-    SMART failure errors if the value of an attribute is below the
-    threshold and the prefailure bit is set.  However the ATA Spec
-    (ATA4 <=Rev 4) says that it is a SMART failure if the value of an
-    attribute is LESS THAN OR EQUAL to the threshold and the
-    prefailure bit is set.  This is now fixed in both smartctl and
-    smartd.  Note that this is a troubled subject -- the original
-    SFF 8035i specification defining SMART was inconsistent about
-    this.  One section says that Attribute==Threshold is pass,
-    and another section says it is fail.  However the ATA specs are
-    consistent and say Attribute==Threshold is a fail.
-
-    smartd did not print the correct value of any failing SMART attribute.  It
-    printed the index in the attribute table, not the attribute
-    ID. This is fixed.
-
-    when starting self-tests in captive mode ioctl returns EIO because
-    the drive has been busied out.  Detect this and don't return an eror
-    in this case.  Check this this is correct (or how to fix it?)
-    fixed possible error in how to determine ATA standard support
-    for devices with no ATA minor revision number.
-
-    device opened only in read-only not read-write mode.  Don't need R/W 
-    access to get smart data. Check this with Andre.
-
-    smartctl now handles all possible choices of "multiple options"
-    gracefully.  It goes through the following phases of operation,
-    in order: INFORMATION, ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS.
-    Documentation has bee updated to explain the different phases of
-    operation.  Control flow through ataPrintMain()
-    simplified.
-
-    If reading device identity information fails, try seeing if the info
-    can be accessed using a "DEVICE PACKET" command.  This way we can
-    at least get device info.
-
-    Modified Makefile to automatically tag CVS archive on issuance of
-    a release
-
-    Modified drive detection so minor device ID code showing ATA-3 rev
-    0 (no SMART) is known to not be SMART capable.
-
-    Now verify the checksum of the device ID data structure, and of the
-    attributes threshold structure.  Before neither of these
-    structures had their checksums verified.
-
-    New behavior vis-a-vis checksums.  If they are wrong, we log
-    warning messages to stdout, stderr, and syslog, but carry on
-    anyway.  All functions now call a checksumwarning routine if the
-    checksum doesn't vanish as it should.
-
-    Changed Read Hard Disk Identity function to get fresh info from
-    the disk on each call rather than to use the values that were read
-    upon boot-up into the BIOS.  This is the biggest change in this
-    release.  The ioctl(device, HDIO_GET_IDENTITY, buf ) call should
-    be avoided in such code.  Note that if people get garbled strings
-    for the model, serial no and firmware versions of their drives,
-    then blame goes here (the BIOS does the byte swapping for you,
-    apparently!)
-    
-    Function ataSmartSupport now looks at correct bits in drive
-    identity structure to verify first that these bits are valid,
-    before using them.
-    
-    Function ataIsSmartEnabled() written which uses the Drive ID state
-    information to tell if SMART is enabled or not.  We'll carry this
-    along for the moment without using it.
-
-    Function ataDoesSmartWork() guaranteed to work if the device
-    supports SMART.
-
-    Replace some numbers by #define MACROS
-
-    Wrote Function TestTime to return test time associated with each
-    different type of test.
-
-    Thinking of the future, have added a new function called
-    ataSmartStatus2().  Eventually when I understand how to use the
-    TASKFILE API and am sure that this works correctly, it will
-    replace ataSmartStatus().  This queries the drive directly to
-    see if the SMART status is OK, rather than comparing thresholds to
-    attribute values ourselves. But I need to get some drives that fail
-    their SMART status to check it.
-
-
-smartmontools-5.0-10
-    Removed extraneous space before printing in some error messages
-    Fixed additional typos in documentation
-    Fixed some character buffers that were too short for their contents.
-
-smartmontools-5.0-9
-
-    Put project home path into all source files near the top
-    Corrected typos in the documentation
-    Modified Makefile so that Mandrake Cooker won't increment version number
-    (unless they happen to be working on my machine, which I doubt!)
-
-smartmontools-5.0-8:
-
-    For IBM disks whose raw temp data includes three temps. print all
-    three
-
-    print timestamps for error log to msec precision
-
-    added -m option for Hitachi disks that store power on life in
-    minutes
-
-    added -L option for printing self-test error logs
-
-    in -l option, now print power on lifetime, so that one can see
-    when the error took place
-
-    updated SMART structure definitions to ATA-5 spec
-
-    added -p option
-
-    added -f and -F options to enable/disable autosave threshold
-    parameters
-
-    changed argv parsing to use getops -- elminate buffer overflow
-    vulnerability
-
-    expanded and corrected documentation
-
-    fixed problem with smartd.  It did not actually call
-    ataSmartEnable()!  Since the argument was left out, the test
-    always suceeded because it evaluated to a pointer to the function.
-
-    smartd: closed open file descriptors if device does not support
-    smart. Note: this still needs to be fixed for SCSI devices
-
-
-smartmontools-5.0-0  STARTED with smartsuite-2.1-2
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..40fd918
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,507 @@
+$Id: ChangeLog 3812 2013-04-20 18:59:19Z chrfranke $
+
+2013-04-20  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - InnoDisk InnoLite SATADOM D150QV-L SSDs
+       - Intel 313 Series SSDs
+       - Intel 330 Series SSDs: 240GB
+       - JMicron based SSDs: Kingston V200 (ticket #267)
+       - Samsung based SSDs: SM843T Series
+
+2013-04-20  Christian Franke  <franke@computer.org>
+
+       configure.ac: Linux: Try 'hostname -y' if 'nishostname' is missing.
+
+2013-04-18  Christian Franke  <franke@computer.org>
+
+       configure.ac, smartd_warning.sh.in: Add platform specific commands for
+       host and domain names.
+       os_win32/smartd_warning.cmd: Use WMI for DNS domain name.
+
+2013-04-18  Christian Franke  <franke@computer.org>
+
+       scsicmds.cpp, scsiprint.cpp: Silence -Wmaybe-uninitialized warning
+       (g++ 4.8.0 with -flto).
+
+2013-03-29  Christian Franke  <franke@computer.org>
+
+       os_darwin.cpp: Silence -Wself-assign warning (ticket #266).
+       os_darwin.cpp, os_netbsd.cpp, os_os2.cpp, os_qnxnto.cpp, os_solaris.cpp:
+       Remove dummy functions no longer called since r3192.
+
+2013-03-27  Christian Franke  <franke@computer.org>
+
+       os_win32.cpp: Silence -Wunused-local-typedefs warning.
+
+2013-03-24  Christian Franke  <franke@computer.org>
+
+       dev_areca.cpp: Add casts to silence C++11 -Wnarrowing warning
+       from g++ 4.8.
+
+2013-03-24  Christian Franke  <franke@computer.org>
+
+       Windows: Compile fixes for 64-bit Cygwin.
+       It uses LP64 model instead of LLP64 (64-bit MSVC, MinGW).
+
+2013-03-16  Christian Franke  <franke@computer.org>
+
+       smartmontools 6.1
+
+2013-03-15  Christian Franke  <franke@computer.org>
+
+       os_win32.cpp: Support device names /dev/sd[a-z][a-z] (ticket #240).
+       Enhance DEVICESCAN to 128 drives.  Add '-d [TYPE,]pd' option.
+       smartctl.8.in, smartd.8.in: Document these enhancements.
+
+2013-03-14  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - Seagate Barracuda 7200.14: Fix regex for new firmware version.
+
+2013-03-13  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - USB: Prolific PL3507 (0x067b:0x3507): works with '-d usbjmicron,p'
+
+2013-03-13  Christian Franke  <franke@computer.org>
+
+       Create branch RELEASE_6_0_DRIVEDB with last drivedb.h file
+       compatible with smartmontools 6.0.
+
+2013-03-13  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - SandForce Driven SSDs: Fix format of attribute 198 (ticket #258).
+       - SandForce Driven SSDs: Corsair Force GS
+       - Indilinx Barefoot_2/Everest/Martini based SSDs: OCZ VERTEX PLUS R2
+       - Samsung/Seagate SpinPoint M8: 320GB, 640GB
+       - Seagate Momentus Thin
+       - Quantum Fireball EX: 10.2GB
+
+2013-03-07  Christian Franke  <franke@computer.org>
+
+       ataidentify.cpp, ataprint.cpp: ACS-3 updates.
+       ataprint.cpp: Improve device statistics error messages.
+
+2013-03-06  Christian Franke  <franke@computer.org>
+
+       smartd_warning.sh.in: Support BSD variant of 'hostname' command
+       which prints FQDN.  Add Windows domain name (Cygwin).
+
+2013-03-01  Douglas Gilbert  <dgilbert@interlog.com>
+
+       scsicmds.h, scsicmds.cpp, scsiprint.cpp:
+       - for SCSI disks prefer READ DEFECT(12) for finding the
+         grown defect list length (previously used READ DEFECT(10)
+         only)
+
+2013-03-01  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - SandForce Driven SSDs: Transcend SSD320
+       - Intel 520 Series SSDs: OEM variant
+       - JMicron based SSDs: Transcend SSD25 IDE
+       - HGST Travelstar 7K1000
+       - Seagate Desktop HDD.15
+       - Seagate LD25.2
+       - Western Digital RE4 (SATA 6Gb/s)
+       - USB: Fujitsu/Zalman ZM-VE300 (0x04c5:0x2028)
+
+2013-02-23  Christian Franke  <franke@computer.org>
+
+       drivedb.h: Crucial/Micron RealSSD C300: Remove bogus trailing '|' from
+       regex (Regression from r3772).
+
+2013-02-16  Douglas Gilbert  <dgilbert@interlog.com>
+
+       scsicmds.h, scsicmds.cpp, scsiprint.h, scsiprint.cpp:
+       - for SCSI disks, in 'smartctl --info' report physical
+         block size and lowest LBA alignement (if PB size
+         different from LB size); logical block provisioning
+         status (if any); and disk protection (a.k.a. DIF) type
+
+2013-02-19  Alex Samorukov  <samm@os2.kiev.ua>
+
+       atacmds.cpp: fixed scttemphist on LE machines, including PPC. Patch
+       and report provided by Roger Roehrig.
+
+2013-02-16  Douglas Gilbert  <dgilbert@interlog.com>
+
+       scsicmds.h, scsicmds.cpp, scsiprint.h, scsiprint.cpp:
+       - SCSI VPD work; improve rotation rate reporting and add form factor
+
+2013-02-14  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - SandForce Driven SSDs: Kingston V+ 200, Mushkin Chronos deluxe,
+         OCZ Talos 2
+       - Plextor M3 (Pro) Series SSDs
+
+2013-02-13  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - Crucial/Micron RealSSD C300: new separate entry
+       - Crucial/Micron RealSSD m4/C400: firmware bug warning
+
+2013-02-10  Alex Samorukov  <samm@os2.kiev.ua>
+
+       os_freebsd.cpp: adding device type fix for devices on MPT controllers.
+
+2013-02-06  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - Seagate Samsung SpinPoint M8U (USB)
+       - Hitachi/HGST Travelstar Z5K500
+       - Hitachi/HGST Travelstar 5K750
+       - Hitachi/HGST Deskstar 7K4000
+       - Toshiba 2.5" HDD MK..37GSX
+       - Toshiba 2.5" HDD MK..65GSX: GSXN variant
+       - Toshiba 2.5" HDD MQ01ABD...
+       - Seagate Momentus 7200.5
+       - Western Digital Caviar Green (AF, SATA 6Gb/s): 2TB
+       - USB: Samsung M3 Portable USB 3.0 (0x04e8:0x61b6)
+       - USB: LaCie Rugged Mini USB 3.0 (0x059f:0x1051)
+       - Change short attribute names required before r3343.
+
+2013-02-05  Christian Franke  <franke@computer.org>
+
+       smartd.cpp: Fix allocation of buffer passed to putenv().
+       Using putenv("NAME") to unset NAME is not portable.
+
+2013-02-05  Christian Franke  <franke@computer.org>
+
+       do_release: New Signing Key.
+
+2013-01-31  Christian Franke  <franke@computer.org>
+
+       dev_areca.h: Use the C++ way to specify unused arguments.
+       This silences -Wself-assign warning from clang++.
+
+2013-01-30  Christian Franke  <franke@computer.org>
+
+       configure.ac: Use AC_CHECK_TOOL for winmc and windres.
+
+2013-01-30  Christian Franke  <franke@computer.org>
+
+       Windows smartd: Install service with delayed auto start enabled.
+
+2013-01-26  Christian Franke  <franke@computer.org>
+
+       Windows smartd: Add eventlog MESSAGETABLE resource.
+       Install/remove smartd.exe as event message file.
+       Remove syslogevt.exe tool.
+
+2013-01-26  Christian Franke  <franke@computer.org>
+
+       Windows: Add required string CompanyName to VERSIONINFO.
+
+2013-01-23  Christian Franke  <franke@computer.org>
+
+       Windows: Add VERSIONINFO resource to exe files.
+
+2013-01-23  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - Crucial/Micron RealSSD C300/C400/m4: m4 mSATA variant
+       - Indilinx Barefoot 3 based SSDs
+       - Intel DC S3700 Series SSDs
+       - Samsung based SSD: Samsung SSD 840 Series
+
+2013-01-18  Christian Franke  <franke@computer.org>
+
+       AUTHORS: Convert to UTF-8.  Sort names.  Replace tabs.
+
+2013-01-18  Christian Franke  <franke@computer.org>
+
+       Rename configure.in to configure.ac to silence warning from
+       new automake.
+       autogen.sh: automake 1.12.5 is OK.
+
+2013-01-16  Christian Franke  <franke@computer.org>
+
+       atacmds.cpp: Fix assignment of BYTEORDER from -v option
+       (Regression from r3719).
+
+2013-01-13  Ole Jørgen LegÃ¥rd  <ole@smartautomation.no>
+
+       os_qnxnto.cpp: Fix include of errno.h.
+
+2013-01-12  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - SandForce Driven SSDs: Mushkin Callisto deluxe, SuperSSpeed S301
+       - Intel 320 Series SSDs: 'B' (7mm) variant (ticket #257)
+       - SAMSUNG SpinPoint F1 EG
+       - SAMSUNG SpinPoint P80: SP0401N/TJ100-30
+       - Western Digital Caviar Black: 4TB
+       - Western Digital Caviar Black (AF): Remove non-AF models
+       - Western Digital My Passport (USB, AF): 5000L, 10J variants
+       - USB: WD My Passport USB 3.0 (0x1058:0x07a8)
+       - USB: WD My Book Studio II (0x1058:0x1105)
+
+2013-01-02  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - SandForce Driven SSDs: ADATA S396, Kingston 3K, V+
+       - Indilinx Everest/Martini based SSDs: OCZ VERTEX PLUS
+       - Samsung based SSD: Samsung SSD 840 PRO Series
+
+2013-01-02  Christian Franke  <franke@computer.org>
+
+       Add '-d usbjmicron,p' device type for Prolific USB bridges.
+       Based on patch provided by Edward Sheldrake.
+
+2013-01-01  Christian Franke  <franke@computer.org>
+
+       smartd: Use Attribute 190 for temperature (-W) if 194 is not present.
+
+2013-01-01  Christian Franke  <franke@computer.org>
+
+       Happy New Year! Update copyright year in version info.
+
+2012-12-16  Alex Samorukov  <samm@os2.kiev.ua>
+
+       os_freebsd.cpp: WRITE LOG on LSI/Megaraid should work fine, disable
+       check, problem was linux related.
+       os_linux.cpp: Implemented autoscan for the megaraid SAS controolers.
+       os_linux.cpp: fix WRITE LOG command in SAT layer for -d megaraid.
+       Reason was direction flag always set to READ.
+       os_linux.cpp: unblock autodetection for the SAT drives in -d megaraid.
+
+2012-12-14  Christian Franke  <franke@computer.org>
+
+       man pages: Fix usage of Hyphen (-) and Minus sign (\-).
+
+2012-12-13  Christian Franke  <franke@computer.org>
+
+       man pages: Update EXPERIMENTAL notes.
+       Fix spelling (Red Hat Bugzilla 665028).
+
+2012-12-13  Christian Franke  <franke@computer.org>
+
+       ataprint.cpp: Print Additional Product Identifier (OEM Id).
+
+2012-12-13  Stanislav Brabec  <sbrabec@suse.cz>
+
+       Update FSF postal address in all files.
+
+2012-12-12  Christian Franke  <franke@computer.org>
+
+       smartctl.cpp: Remove include <new> for QNXNTO.
+       Should only be needed if placement new is used.
+       smartd.cpp: Remove very old _GNU_SOURCE define.
+       It was added 10 years ago in r147.  It is not (or no longer) needed
+       and has an unwanted side effect (__USE_MINGW_ANSI_STDIO) on MinGW.
+
+2012-12-11  Christian Franke  <franke@computer.org>
+
+       smartd.cpp: Add '-w PATH, --warnexec=PATH' option.
+       smartd.8.in: Document this option.
+
+2012-12-11  Christian Franke  <franke@computer.org>
+
+       smartd.cpp: Add '-d ignore' directive.
+       smartd.conf.5.in: Document '-d ignore'.  Add DEVICESCAN example.
+       Remove duplicate and outdated info about device scanning.
+       smartd.8.in: Add notes about RAID controllers to device scanning info.
+
+2012-12-11  Stanislav Brabec  <sbrabec@suse.cz>
+
+       * smartd.initd.in: SUSE: Added sysconfig options to disable
+       persistent state writes, attribute log and set arbitrary smartd
+       options.
+
+2012-12-03  Christian Franke  <franke@computer.org>
+
+       Avoid usage of strcpy(), strcat(), sprintf().
+       Use snprintf() instead or change type to std::string.
+       Use array references instead of char pointers for parameters.
+
+2012-12-03  Christian Franke  <franke@computer.org>
+
+       smartd.cpp: Ignore a device from DEVICESCAN if a preceding smartd.conf
+       entry for the same device exists.
+
+2012-11-28  Christian Franke  <franke@computer.org>
+
+       smartd.conf.5.in: Document smartd_warning.sh/cmd scripts and
+       the new environment variables.
+       Makefile.am: Replace smartd_warning.* paths on man pages.
+       Reformat long sed commands.
+
+2012-11-27  Christian Franke  <franke@computer.org>
+
+       smartd.cpp: Remove trailing newlines from some MailWarning() strings.
+       os_win32/smartd_warning.cmd: Fix SMARTD_MESSAGE with parentheses.
+
+2012-11-25  Alex Samorukov  <samm@os2.kiev.ua>
+
+       OpenBSD: remove dummy functions
+
+2012-11-24  Christian Franke  <franke@computer.org>
+
+       Windows: Add tool wtssendmsg.exe based on no longer
+       used module os_win32/wtssendmsg.cpp.
+       os_win32/smartd_warning.cmd: Fix wtssendmsg call.
+       os_win32/installer.nsi: Install smartd_warning.cmd
+       and wtssendmsg.exe.  Fix uninstall of old ChangeLog.
+
+2012-11-23  Christian Franke  <franke@computer.org>
+
+       Move MSVC10 project files to new directory os_win32/vc10.
+
+2012-11-22  Christian Franke  <franke@computer.org>
+
+       smartd: Move warning message formatting and mailer/command
+       startup to new script SYSCONFDIR/smartd_warning.sh
+       (Windows: smartd_warning.cmd).
+       Add environment variables SMARTD_PREVCNT and SMARTD_NEXTDAYS.
+       Remove host/domainname related code from smartd.cpp
+       and configure.in
+
+2012-11-22  Alex Samorukov  <samm@os2.kiev.ua>
+
+       smartctl: implemeted support for -g/-s rcache and -g/-s wcache for SCSI
+       devices to control read/write device cache.
+
+2012-11-19  Alex Samorukov  <samm@os2.kiev.ua>
+
+       smartctl: supports progress indicator on selftests
+       smartctl: prints rotation speed for SCSI drives, if supported
+       smartctl: add headers to SCSI output, fix data blocks formatting,
+       trim identification data
+       os_linux.cpp: add autodetection for PERC H700 array
+       smartd: trim SCSI vendor/model/serial before creating state files
+
+2012-11-18  Alex Samorukov  <samm@os2.kiev.ua>
+
+       smartd.cpp: implement error counters and temperature saving to the
+       attrlog file for SCSI devices.
+       smartd.cpp: added reset_warning_mail() if device is working for SCSI
+
+2012-11-18  Christian Franke  <franke@computer.org>
+
+       drivedb.h: Western Digital Caviar Green: Add -F xerrorlba
+
+2012-11-17  Alex Samorukov  <samm@os2.kiev.ua>
+
+       smartd.cpp: print lu_id for SPC devices, it is supported by standard
+       smartd.cpp: added initial state file support for the SCSI devices
+       smartd.cpp: add S/N to SCSI device identifier, lu_id is not available
+       on some drives.
+       smartd.cpp: fix warning for SCSI drives with self test in progress (#249)
+       drivedb.h: added -F xerrorlba flag Seagate Barracuda LP/CC32
+
+2012-11-09  Christian Franke  <franke@computer.org>
+
+       Windows smartd: Allow quoting of '-M exec' argument
+       to support path names with spaces.
+
+2012-11-09  Christian Franke  <franke@computer.org>
+
+       ataprint.cpp: Rework smartctl -l directory output.
+       Add R/W, R/O info.  Report identical logs in one line.
+
+2012-11-09  Alex Samorukov  <samm@os2.kiev.ua>
+
+       os_freebsd.cpp: adding handling of SCSI devices exported with mfip
+       driver. FreeBSD changing PDT code to 0x1f and we are changing it back
+       to 0x00 (direct-access block device).
+       os_freebsd.cpp: improved error handling for the ATA devices
+
+2012-11-04  Christian Franke  <franke@computer.org>
+
+       drivedb.h:
+       - SandForce Driven SSDs: Mushkin Chronos
+       - Indilinx Everest/Martini based SSDs: OCZ AGILITY4
+       - Intel 710 Series SSDs: Add attribute 174
+       - JMicron based SSDs: KINGSTON SSDNOW 30GB
+       - Hitachi Deskstar 7K1000.C: *CLA330
+       - Seagate DiamondMax 23, Barracuda 7200.12, 7200.14 (AF),
+         LP, Green (AF): no warnings for newer firmware versions
+       - Western Digital Caviar Green (AF, SATA 6Gb/s): rename, add 1TB
+       - USB: Toshiba Stor.E (0x0930:0x0b1[9a])
+       - USB: Verbatim Store'n'Go (0x18a5:0x022b)
+
+2012-11-02  Alex Samorukov  <samm@os2.kiev.ua>
+
+       os_freebsd.cpp: disabling 48bit commands on legacy ATA controllers
+       in ATACAM mode because of kernel bug.
+
+2012-10-31  Christian Franke  <franke@computer.org>
+
+       atacmdnames.cpp: Update for ATA-8-ACS, ACS-2, ACS-3.
+       ataidentify.cpp: Mark retired/obsolete values.
+       ataprint.cpp: Add new ACS-3 logs, mark obsolete logs.
+
+2012-10-27  Alex Samorukov  <samm@os2.kiev.ua>
+
+       os_freebsd.cpp: Have smartd prefer real device names over passN.
+       Patch provided by dnelson, see ticket #21
+       os_freebsd.cpp: fix 48-bit support for ATA legacy controllers in
+       ATACAM mode, patch provided by Alexander Motin
+
+2012-10-25  Christian Franke  <franke@computer.org>
+
+       atacmds.cpp: Return error for get SCT ERC if ATA registers are
+       unchanged after SMART_WRITE_LOG command (see ticket #245).
+
+2012-10-24  Christian Franke  <franke@computer.org>
+
+       dev_areca.cpp: Add missing parameter check to ata_pass_through().
+       Update Areca info on man pages.
+
+2012-10-24  Christian Franke  <franke@computer.org>
+
+       dev_interface: Rework ATA parameter checks, use new flags
+       ata_device::supports_* for new ata_cmd_is_supported().
+       Replace ata_cmd_is_ok() by ata_cmd_is_supported() in scsiata.cpp
+       and os_win32.cpp.
+
+2012-10-19  Alex Samorukov  <samm@os2.kiev.ua>
+
+       os_freebsd.cpp - fixed 3ware twe controller support broken
+       by inerface migration.
+
+2012-10-18  Christian Franke  <franke@computer.org>
+
+       utility.cpp: Add missing errno clear in split_selective_arg()
+       (Debian bug 690108).
+       Remove unused function split_report_arg2().
+
+2012-10-18  Christian Franke  <franke@computer.org>
+
+       os_win32.cpp: define _WIN32.  This fixes build on
+       Cygwin with new w32api-headers.
+
+2012-10-18  Alex Samorukov  <samm@os2.kiev.ua>
+
+       Compile fixes for Areca patch on FreeBSD.
+       Added support for the /dev/twsX (3ware 9750) controller on FreeBSD.
+       Manual pages updated with /dev/twsX device
+       FreeBSD: Migrate 3ware interface to ata_pass_through()
+       FreeBSD: fix missing drives detection on -d 3ware
+       FreeBSD: 3ware - do not pass buffers direcly, use memcpy() instead
+       FreeBSD: improved detection of 3ware/LSI controllers
+
+2012-10-16  Christian Franke  <franke@computer.org>
+
+       Compile fixes for Areca patch:
+       Add missing includes.  Add GPL header.
+       Add dev_areca.* to configure.in and Makefile.am.
+
+2012-10-16  Hank Wu  <hank@areca.com.tw>
+
+       Move common Areca code from os_freebsd.cpp, os_linux.cpp, os_win32.cpp
+       to new files dev_areca.h, dev_areca.cpp.
+       Add SAS support for FreeBSD and Linux.
+
+2012-10-10  Christian Franke  <franke@computer.org>
+
+       Rename old CHANGELOG to ChangeLog-5.0-6.0.
+       Start new ChangeLog.
+
+2012-10-10  Christian Franke  <franke@computer.org>
+
+       smartmontools 6.0
diff --git a/ChangeLog-5.0-6.0 b/ChangeLog-5.0-6.0
new file mode 100644 (file)
index 0000000..a468937
--- /dev/null
@@ -0,0 +1,5235 @@
+CHANGELOG for smartmontools 5.0 to 6.0
+
+$Id: ChangeLog-5.0-6.0 3645 2012-10-10 16:15:26Z chrfranke $
+
+Maintainers / Developers Key (alphabetic order):
+[AS]  Alex Samorukov
+[BA]  Bruce Allen
+[OB]  Oliver Bock
+[EB]  Erik Inge Bolsø
+[SB]  Stanislav Brabec
+[PC]  Peter Cassidy
+[MC]  Matthieu Castet
+[YD]  Yuri Dario
+[CD]  Casper Dik
+[CF]  Christian Franke
+[GF]  Guilhem Frézou
+[DG]  Douglas Gilbert
+[GG]  Guido Guenther
+[JPH] Jordan Powell Hargrave
+[JH]  Joerg Hering
+[GK]  Geoff Keating
+[DK]  Dr. David Kirkby
+[DL]  Dan Lukes
+[KM]  Kai Mäkisara
+[EM]  Eduard Martinescu
+[FM]  Frédéric L. W. Meunier
+[GP]  Gabriele Pohl
+[AR]  Adam Radford
+[KS]  Keiji Sawada
+[MS]  Manfred Schwarb
+[TS]  Tomas Smetana
+[DS]  David Snyder
+[SS]  Sergey Svishchev
+[PW]  Phil Williams
+[LW]  Leon Woestenberg
+[SZ]  Shengfeng Zhou
+[RZ]  Richard Zybert
+
+<DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
+
+smartmontools 6.0 2012-10-10
+
+  [CF] do_release: Fix for minor rev number 0.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Corsair Force 115GB
+       - Hitachi Ultrastar 7K4000
+       - Seagate Barracuda 7200.7 and 7200.7 Plus: IBM OEM variants
+       - Western Digital Caviar Black (AF)
+
+  [CF] man pages: Update introduction. Update ATA standards.
+       Remove some outdated info.
+
+  [CF] man pages: Unify license headers.
+
+  [CF] smartctl: Do not abort SCT status output on unknown temperature
+       history format version.
+
+  [CF] smartctl: Remove duplicate note about selective self-test log
+       version.
+
+  [CF] smartctl: Add '-l devstat' to '-x, --xall' output.
+
+  [CF] smartctl: Rework ATA error messages and 'not supported' messages.
+       Avoid misleading warnings on unsupported features (ticket #182).
+       Avoid duplicate error messages.
+
+  [CF] atacmds.h: Remove nonexistent functions.
+
+  [CF] Windows installer: Add support for /S(ilent) install/uninstall.
+
+  [CF] Windows installer: Update examples.  Remove some doc shortcuts.
+
+  [CF] Prepare release 6.0.  Change Copyright output line.
+       Change AUTHORS sections on man pages.
+
+  [CF] smartctl: Rework "ATA Version" output.  Print major and minor
+       revision in one output line.  Remove "ATA Standard" line.
+
+  [CF] drivedb.h updates:
+       - Add firmware warnings for various Seagate series (ticket #239):
+         DiamondMax 23, Barracuda 7200.12, 7200.14 (AF), LP, Green (AF)
+       - Seagate Barracuda 7200.14 (AF): 2.5TB
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: SanDisk Extreme
+       - Indilinx Everest/Martini based SSDs: OCZ-VERTEX4,
+         fix Attribute 232
+       - STEC Mach2 CompactFlash Cards
+       - Toshiba 2.5" HDD MK..55GSX: *55GSXF variants
+       - Western Digital VelociRaptor (AF)
+
+  [CF] Windows: Remove EXPERIMENTAL notes for 64-bit version.
+
+  [CF] autogen.sh: automake 1.11.6 and 1.12.3 are OK.
+
+  [CF] smartctl: Fix '--identify' for big-endian CPUs.
+
+  [CF] ataidentify.cpp: Document some older (now obsolete) features.
+
+  [CF] ataidentify.cpp: Add some recent ACS-3 features.
+
+  [CF] smartctl: Support '-l sataphy' also for Packet interface devices.
+
+  [CF] atacmds.cpp: Add new ATA ACS-3 minor revision.
+
+  [CF] smartctl: Print SATA version and speed in '-i' output.
+
+  [CF] drivedb.h: Minor reordering of Seagate entries.
+
+  [CF] drivedb.h: Use "AF" for Advanced Format (4KiB LPS).
+
+  [CF] drivedb.h updates:
+       - Seagate Barracuda SpinPoint F3
+       - SAMSUNG SpinPoint F3 RE
+       - Seagate Barracuda 7200.12: ST3750525AS
+       - Seagate Barracuda 7200.14 (AF): change name, add -v options
+       - Western Digital Red (AF)
+       - USB: Seagate Backup Plus USB 3.0 (0x0bc2:0xa013) (ticket #235)
+       - USB: Seagate Backup Plus Desktop USB 3.0 (0x0bc2:0xa0a4)
+
+  [CF] os_win32.cpp: Add support for SAS disks behind Areca SAS
+       controllers.  This includes SAS/SATA autodetection.
+
+       Patch was provided by Hank Wu from Areca.
+
+  [CF] ataidentify.cpp: Add some recent SATA features.
+
+  [CF] smartctl: Add '--identify[=wnvb]' option.
+       Add new source files ataidentify.h/cpp.
+
+  [CF] Makefile.am: Reformat lists of sources.
+
+  [CF] Do not print HDD/SSD specific default attribute names if identify
+       data reports SSD/HDD device.
+
+  [CF] drivedb.h updates:
+       - Intel 320 and 710 Series SSDs: Set '-F nologdir'
+       - Seagate Barracuda ES.2: Set '-F xerrorlba'
+
+  [CF] Create branches RELEASE_5_4[0-3]_DRIVEDB with last drivedb.h file
+       compatible with smartmontools 5.4[0-3].
+
+  [CF] drivedb.h updates:
+       - SAMSUNG SpinPoint M40/60/80: HM120IC
+       - USB: Oxford (0x0928:0x0010)
+       - USB: Seagate External Drive/Cypress (0x0bc2:0x0503)
+       - USB: 0x1f75:0x0888 is Innostor IS888
+
+  [CF] smartctl: Print nominal media rotation rate in '-i' output (ATA).
+
+  [CF] knowndrives.cpp: Fix missing '-F xerrorlba' in '-P show' output.
+
+  [CF] os_win32.cpp: Use WMI to get serial number if
+       IOCTL_STORAGE_QUERY_PROPERTY is used.
+
+  [CF] os_win32.cpp: Remove more Win9x/ME/NT4 specific code: ATA drive
+       number, GetDevicePowerState() handling.
+
+  [CF] Add '-F xerrorlba' option/directive.
+
+  [CF] Rework '-F' option handling.  Add support for multiple '-F' options
+       and directives.
+
+  [CF] Makefile.am: Fix typo in ACLOCAL_AMFLAGS.
+
+  [CF] smartd.cpp: MailWarning(): Move variable declarations, use sizeof()
+       instead of numbers.
+
+  [CF] smartd.cpp: Rework dnsname().  Print "[None]" instead of "[Unknown]"
+       if domain is not set.  Print NIS domain only if supported.
+
+  [CF] Windows smartd: Use gethostname/gethostbyname() from winsock.
+       Remove os_win32/hostname_win32.*.
+
+  [CF] smartd: Include device identify info in warning emails (ticket #185).
+       Add SMARTD_DEVICEINFO environment variable.
+
+  [CF] Add '-F nologdir' option/directive.
+       Prevents freeze of some Intel SSDs (ticket #214).
+
+  [CF] smartd: Don't log ignored -W directive as critical.
+
+  [CF] drivedb.h updates:
+       - Smart Storage Systems Xcel-10 SSDs: Move entry, change name
+       - Samsung: Remove very old and already commented out entries
+       - Seagate Momentus XT (Adv. Format)
+       - WD My Passport: 3 -> 2 entries, add 2TB
+       - USB: Imation (0x0718:0x1000) (ticket #231)
+       - USB: Initio (0x13fd:0x1040): unsupported
+       - USB: ASMedia USB 3.0 (0x174c:0x55aa): unsupported -> -d sat
+       - USB: PQI H560 (0x3538:0x0902) (ticket #232)
+
+  [CF] smartctl: Override SMART disabled state with '-T permissive'.
+
+  [CF] os_win32/daemon_win32.cpp: Drop remaining WinNT4 compatibility.
+
+  [CF] Windows smartd: Add smartd.conf directives '-m console',
+       '-m active', '-m connected'.  Send warning messages via
+       WTSSendMessage().  Remove use of MessageBox() which does no
+       longer work for services since Vista/2008.
+
+  [CF] Fix 'smartctl -P show'.  Regression from r3249.
+
+  [CF] smartd.cpp: Fix setting of temporary environment in MailWarning().
+       Stack space was passed to putenv() but variable was not unset
+       before return.  Very old bug introduced 2003 in r1114.
+
+  [CF] smartd.cpp: Add fflush() to support redirection of debug output
+       (Debian bug 681349).
+
+  [CF] os_generic.cpp: Add missing int64.h (Debian bug 619208)
+       This obsoletes Debian patch fix-generic.diff.
+
+  [CF] cciss.cpp: Fix build on GNU/kFreeBSD (Debian bug 676142).
+       This obsoletes Debian kfreebsd.patch.
+
+  [CF] Windows: Drop backward compatibility with WinNT4.
+
+  [CF] Windows: Drop backward compatibility with Win9x/ME.
+
+smartmontools 5.43 2012-06-30
+
+  [CF] drivedb.h USB updates:
+       - Toshiba Canvio Basics (0x0480:0xa006)
+       - A-DATA DashDrive (0x125f:0xa94a)
+
+  [CF] drivedb.h: Hitachi Travelstar 7K500: *A362/3 variants
+
+  [CF] Windows: Add Windows Server 2012 to get_os_version_str().
+
+  [CF] drivedb.h updates:
+       - Sandforce Driven SSDs: OWC Mercury Electra 3/6G SSD
+       - Seagate Momentus SpinPoint M8
+       - Hitachi Deskstar 5K4000
+       - Toshiba 2.5" HDD MK..61GSYN
+       - Seagate Barracuda (SATA 3Gb/s, 4K Sectors): 1TB, *DM003-* variant
+
+  [CF] smartctl.8.in: Note performance impact of self-tests.
+
+  [CF] os_win32.cpp: Add support for older Areca drivers which used a
+       different target id.  Patch was provided by Hank Wu from Areca.
+
+  [CF] smartctl.8.in: Add info about HP Smart Array controllers.
+       Original patch was provided by Don Brace from HP.
+
+  [CF] os_freebsd.cpp: add SAT autodetection to '-d cciss,N' device type
+       (ticket #202).
+       Add missing freebsd_areca_device::m_encnum (regression from r3542).
+       Patch was provided by Don Brace from HP.
+
+  [CF] os_linux.cpp: add SAT autodetection to '-d cciss,N' device type
+       (ticket #202).
+
+  [CF] Makefile.am: FIXHTML modified for newer man2html versions.
+
+  [CF] autogen.sh: automake 1.11.5 is OK.
+
+  [CF] man pages: Minor updates and syntax fixes.
+
+  [CF] smartd.service.in: Add ExecReload and StandardOutput.
+       Make EnvironmentFile optional (ticket #194).
+
+  [CF] drivedb.h USB updates:
+       - HP Desktop HD BD07 (0x03f0:0xbd07)
+       - Iomega Prestige Desktop USB 3.0 (0x059b:0x0070)
+       - Prolific PL2507 (0x067b:0x2507): unsupported -> -d usbjmicron,0
+       - WD My Passport USB 3.0 (0x1058:0x0748)
+       - WD My Book Essential USB 3.0 (0x1058:0x1140)
+       - Sharkoon SATA QuickDeck Pro (0x1f75:0x0888): unsupported
+       - Hitachi Touro Desk (0x4971:0x1015)
+
+  [CF] Move function str_starts_with() to utility.h.
+
+  [CF] smartctl.8.in, smartd.conf.5.in: Note required Areca SAS firmware version.
+
+  [CF] INSTALL, smartctl.8.in: Announce OS X SAT SMART Driver (ticket #25).
+
+  [CF] Add smart_device::is_syscall_unsup().
+
+  [CF] os_win32.cpp: Avoid ENOTSUP which is not provided by some versions
+       of MinGW.
+
+  [DG] os_linux.cpp: Fix scsi pass-through SG_INFO_CHECK mask logic
+       (ticket #225)
+
+  [CF] drivedb.h updates:
+       - Sandforce Driven SSDs: OCZ-NOCTI
+       - Intel 330 Series SSDs (ticket #227)
+
+  [CF] smartctl.8.in, smartd.conf.5.in: Document '-d areca N[/E]' support
+       for Windows.
+
+  [CF] os_win32.cpp: Add help text and error messages for '-d areca,N[/E]'.
+
+  [CF] os_win32.cpp win_areca_device: Disable full 48-bit ATA support.
+       Add missing set_err() calls.  Remove unused function and parameter.
+
+  [CF] os_win32.cpp: Add support for SATA disks behind Areca SATA and SAS
+       controllers.  Requires '-d areca,N[/E]' as type and '[/dev/]arcmsrX'
+       as device name.
+
+       Patch was provided by Hank Wu from Areca.
+
+  [CF] Windows installer: Make name of checksum file 32-/64-bit specific.
+
+  [CF] Windows installer: Add support for combined 32-/64-bit installer.
+
+  [CF] Windows installer: Drop support for UBCD4Win.
+
+  [AS] os_freebsd.cpp: sync Areca code with linux version by adding optional 
+       enclosure number.
+
+  [CF] smartctl.8.in, smartd.conf.5.in: Add brief doc for '-d areca N/E'.
+
+  [CF] os_linux.cpp: Add optional enclosure number to '-d areca' option.
+       This adds support for SATA disks behind Areca SAS controllers.
+
+       Patch was provided by Hank Wu from Areca.
+
+  [CF] smartctl: Add log addresses and statistics value from ACS-3 revision 2.
+
+  [CF] drivedb.h updates:
+       - Crucial/Micron RealSSD C300/C400/m4: m4 512GB
+       - Indilinx Everest/Martini based SSDs: OCZ-PETROL
+       - SAMSUNG SpinPoint F4 EG (AFT): Fix link
+       - Seagate Momentus 4200.2: ST960812A
+       - Seagate Momentus 5400.2: ST960821A (from 4200.2)
+       - Seagate Barracuda 7200.12: ST3500413AS
+       - Western Digital RE3 Serial ATA: WD7502ABYS
+       - Western Digital AV-GP: WD....AV[CD]S, split entry
+       - Western Digital AV-GP (Adv. Format): WD10EU[CR]X
+
+  [CF] autogen.sh: Set svn:eol-style=LF to be compatible with Cygwin bash.
+
+  [CF] autogen.sh: automake 1.11.3 is OK.
+
+  [CF] drivedb.h updates:
+       - Sandforce Driven SSDs: Smart Storage Systems XceedSTOR,
+         XceedIOPS2, Xcel-200
+       - Smart Storage Systems XceedSecure2 SSDs
+       - Smart Storage Systems XceedUltraX/Adtron A25FBX SSDs
+       - Smart Storage Systems Adtron A25FB 2xN SSDs
+       - Smart Storage Systems Adtron A25FB 3xN SSDs
+       Original patch was provided by Rusty Carruth
+
+  [CF] drivedb.h updates:
+       - Remove outdated IBM links
+       - Update all links to Seagate Knowledge Base
+       - Hitachi Deskstar 7K1000.D
+
+  [CF] drivedb.h USB update:
+       - Seagate Expansion External (0x0bc2:0x3332) (ticket #223)
+
+  [CF] drivedb.h USB updates:
+       - Samsung Story Station (0x04e8:0x5f05)
+       - Toshiba STOR.E (0x0930:0x0b1b)
+
+  [CF] smartctl: Add options '-f hex' and '-f hex,[id|val]' to print
+       attribute IDs and/or values as hex.
+
+  [CF] smartd.8.in: Fix signal name (Debian bug 661801).
+
+  [CF] Add 'raw56', 'hex56', 'raw24(raw8)' attribute print formats.
+       Change default for Power_On_Hours to 'raw24(raw8)'.
+       This provides more reasonable output for SandForce based devices
+       missing in drivedb.h.
+
+  [CF] configure.in, Makefile.am: Support new SVN 1.7 working copy format.
+
+  [CF] drivedb.h update:
+       - Intel 520 Series SSDs: Add units to attributes 241, 242, 249.
+
+  [AS] drivedb.h: fixed identifier for Seagate SV35 series.
+
+  [CF] Print command duration in ATA debug output.
+       Add smart_interface::get_timer_usec().
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: G.SKILL Phoenix Pro
+       - Intel 520 Series SSDs
+       - SAMSUNG SpinPoint F4 EG: Update firmware download link
+
+  [CF] drivedb.h updates:
+       - Add comment with default settings.
+       - Samsung based SSDs: Fix attribute 240
+
+  [CF] Windows: Add Win8 to get_os_version_str().
+
+  [CF] Windows: Remove MSVC specific pragma, disable warning in project file.
+
+  [CF] Add '-d sat,auto[,N]' option for controller independent SAT detection.
+
+  [CF] dev_interface.h: Replace this_is_ata/scsi(*) by hide_ata/scsi(bool).
+
+  [CF] smartctl: Allow '-d test' in conjunction with other '-d TYPE' options.
+
+  [AS] FreeBSD: sync init script with one from ports repository.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: ADATA S510
+       - JMicron based SSDs: Toshiba THNSNC128GMLJ
+       - Samsung based SSDs: 830 Series
+       - Hitachi Deskstar E7K1000
+       - Hitachi Ultrastar A7K1000: Fix name, allow trailing characters
+       - Hitachi Ultrastar A7K2000: Remove duplicate entry
+       - Toshiba 2.5" HDD MK..55GSX
+       - Western Digital AV-GP: WD..EURS variants
+
+  [CF] drivedb.h USB updates:
+       - Buffalo MiniStation HD-PCTU2 (0x0411:0x01d9) (ticket #211)
+       - Philips SDE3273VC/97 (0x0471:0x2021) (ticket #212)
+       - Samsung M2 Portable 3.0 (0x04e8:0x60c5)
+       - Iomega GDHDU2 (0x059b:0x0475)
+       - LaCie minimus USB 3.0 (0x059f:0x104a)
+       - Seagate FreeAgent GoFlex Desk USB 3.0 (0x0bc2:0x50a5)
+       - Maxtor BlackArmor Portable (0x0d49:0x7550)
+       - WD My Passport Essential SE USB 3.0 (0x1058:0x0742)
+       - Initio (0x13fd:0x1e40)
+       - Verbatim External Hard Drive 2TB (0x18a5:0x022a)
+       - Hitachi Touro Desk (0x4971:0x1011)
+
+  [CF] smartd: Add smartd.conf directive '-e' to set ATA settings on
+       startup: aam, apm, lookahead, security-freeze, standby, wcache.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Corsair Force GT
+       - Indilinx Barefoot based SSDs: Corsair Nova
+       - SAMSUNG SpinPoint M8
+       - Seagate SV35.5
+
+  [CF] smartctl: Change short option for '--set' from '-e' to '-s'.
+       Keep backward compatibility with short option for '--smart'.
+
+  [CF] smartctl: Print description of APM level.
+
+  [CF] smartctl: Add option '-e standby,[N|off|now]' to set standby timer
+       or standby mode.
+
+  [CF] smartctl: Add options '-g security' and '-e security-freeze' to
+       get/freeze ATA security settings.
+
+  [CF] smartctl: Add options '-g/e lookahead' and '-g/e wcache' to get/set
+       read look-ahead and write cache feature.
+
+  [CF] smartctl: Add options '-g aam' and '-e aam,[N|off]' to get/set
+       ATA Automatic Acoustic Management feature.  Add '-g all'.
+
+  [CF] os_win32.cpp: Prevent warnings from gcc option -Wformat-security.
+
+  [CF] smartctl: Add options '-g, --get apm' and '-e, --set apm,[N|off]'
+       to get/set ATA Advanced Power Management feature.
+       Original patch was provided by Marcus Sorensen.
+
+  [AS] os_freebsd.cpp - do not skip ATA devices from cam list. Starting from
+       FreeBSD 9.0 such devices are exported ONLY as camdev`s, so DEVICESCAN
+       was broken. Its possible to get duplicates now on some old systems.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add OCZ Solid 3, OCZ Deneva 2 C/R
+       - Seagate Momentus 5400.7
+
+  [CF] Happy New Year! Update copyright year in version info.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add Patriot Pyro
+       - Intel 320 Series SSDs: Fix 40GB
+       - Seagate Barracuda XT: Add 4TB
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add Corsair Force 3
+       - Hitachi Travelstar 5K320: Add SA00 and SA02 models
+       - Western Digital Caviar SE SATA: Add 300GB
+
+  [CF] Cygwin smartd: Remove SIGQUIT workaround, no longer needed with
+       current Cygwin tty emulation.
+
+  [CF] smartd: Disable auto standby also after start of scheduled
+       self-test.
+
+  [CF] smartd: Add smartd.conf DEFAULT directive.  Allows to set default
+       settings for multiple devices.
+
+  [CF] smartd: Re-enable auto standby if smartd.conf is re-read.
+
+  [AS] drivedb.h update: Seagate Barracuda (SATA 3Gb/s, 4K Sectors)
+
+  [AS] drivedb.h update: Seagate Constellation ES.2 (SATA 6Gb/s)
+
+  [CF] drivedb.h updates:
+       - Sandforce Driven SSDs: Add OCZ Vertex 3 Max IOPS (ticket #209)
+       - Seagate ST1.2 CompactFlash (found in ticket #125)
+
+  [CF] Fix GPL version reported by '-V' option.
+       Now reports GPLv2+ which is consistent with file headers.
+       Patch was provided by Stanislav Brabec.
+
+  [CF] drivedb.h updates:
+       - Sandforce Driven SSDs: Add OCZ Deneva 2 Async variant, 60GB, 480GB
+       - Indilinx Martini based SSDs: OCZ VERTEX-PLUS only
+
+  [CF] smartd: Add '-l offlinests,ns' and '-l selfteststs,ns' directives.
+       dev_interface: Add smart_interface::disable_system_auto_standby().
+       os_win32.cpp: Implement disable_system_auto_standby().
+
+  [CF] dev_interface: Let smart_interface::set_err() return false.
+
+  [CF] drivedb.h updates:
+       - SAMSUNG SpinPoint M8U (USB)
+       - Toshiba 3.5" HDD MKx002TSKB: Fix typo
+
+  [CF] smartctl: Print average temperature from SCT status only if
+       value is reasonable.  Field is not part of ATA-8.
+
+  [CF] smartd: Report ignored '-r' and '-R' directives.
+
+  [CF] smartctl: Use 16-bit value (ATA-8) for extended self-test polling
+       time if 8-bit value is 0xff (ticket #207).
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add OCZ-REVODRIVE3, OCZ Z-DRIVE R4
+       - Hitachi Travelstar Z7K320
+       - Toshiba 2.5" HDD MK..56GSY
+       - Toshiba 2.5" HDD MKx002TSKB
+       - Seagate U9
+       - Seagate U*: sort entries, unify names, remove duplicate
+       - Seagate Constellation ES (SATA 6Gb/s)
+       - Seagate DB35
+       - Seagate DB35.2
+       - Western Digital Scorpio Black: Add 500GB
+       - Western Digital Scorpio Black (Adv. Format)
+
+  [CF] drivedb.h USB updates:
+       - Samsung S2 (0x04e8:0x1f05)
+       - Toshiba Stor.E (0x0939:0x0b16) (ticket #206)
+       - Seagate FreeAgent (0x0bc2:0x5040)
+       - Initio/Thermaltake BlacX (0x13fd:0x0840)
+
+  [DG] [SCSI] smartd: skip non-storage devices (e.g. SES devices)
+
+  [AS] drivedb.h updates: Added Seagate SV35 Series
+
+  [CF] smartctl: Don't start ATA self-test if another test is already
+       running (ticket #40).  Add option '-t force' to allow override.
+
+  [CF] atacmds.h: Remove bogus ataSmart*Test*() prototypes.
+
+  [CF] Define __attribute_format_printf() for functions with printf() style
+       arguments.  Allow MinGW build with __USE_MINGW_ANSI_STDIO enabled.
+
+  [CF] Makefile.am: Replace sed compound command in MAN_FILTER.
+       This fixes build on Solaris (ticket #203).
+
+  [AS] os_freebsd.cpp: Dereference symlinks before guess of device type
+       (problem reported by email).
+
+  [CF] drivedb.h USB updates:
+       - LG Mini HXD5 (0x043e:0x70f1)
+       - Freecom/Intel (0x07ab:0xfc8e)
+       - Dura Micro (0x0c0b:0xb001) (Debian bug 643928)
+       - Initio 6Y120L0 (0x13fd:0x1150): unsupported
+
+  [CF] drivedb.h USB update:
+       - Seagate FreeAgent GoFlex Desk USB 3.0 (0x0bc2:0x50a1):
+         Revert to -d sat,12 (ticket #151).
+
+  [AS] os_freebsd.cpp - fixed crash on FreeBSD9-RC1 caused by r225950
+
+  [AS] smartctl.8 - added information about -d areca on FreeBSD
+
+  [AS] os_freebsd.cpp: backport quirks for the LSI controllers with SATA
+       disks to the FreeBSD. Tested with DELL Perc/6i controller.
+
+  [AS] os_freebsd.cpp: disable SAT autodetection on megaraid controllers
+
+  [AS] drivedb.h update: 
+       - Hitachi Ultrastar 7K2000
+
+  [CF] drivedb.h update:
+       - Seagate Momentus XT: Add bug warning for firmware SD24 and SD25
+
+  [CF] Don't include pkg-config macros in aclocal.m4, copy to m4/pkg.m4
+       instead.  Allow builds from SVN without pkg-config installed
+       but prevent 'make dist' when pkg-config support is missing.
+
+  [CF] Move automake --foreign option from autogen.sh to configure.in.
+       This fixes autoreconf support.
+
+  [CF] Replace COPYING file with current (2010-03-24) version from
+       http://www.gnu.org/licenses/gpl-2.0.txt
+
+smartmontools 5.42 2011-10-20
+
+  [CF] Windows installer: Add install dir to PATH in CMD shortcut.
+
+  [CF] drivedb.h updates:
+       - SAMSUNG SpinPoint MP5
+       - Seagate Barracuda 7200.11: Change warning text, Seagate
+         apparently released fixed firmware without changing version
+         number (Debian bug 632758)
+       - Western Digital RE4 GP
+       - Western Digital VelociRaptor: Add 150GB, 300GB LHX variants
+       - Western Digital Scorpio Blue Serial ATA (Adv. Format):
+         Add 1TB JPVT variant
+
+  [CF] drivedb.h USB update:
+       - WD Elements SE USB 3.0 (0x1058:0x1042)
+
+  [CF] Windows installer: Rework to support UAC.
+       Replace *-run.bat files by runcmd?.exe wrappers.
+       Run drive menu entries elevated (ticket #173).
+
+  [CF] smartctl.8.in: Add example script which prints all status bits
+       (ticket #191).
+
+  [CF] Cygwin smartd: Remove '--service' option, update man page.
+
+  [CF] smartd: Require absolute path name also for '-p' option.
+       Allow relative path names for '-A', '-s', '-p' in Windows
+       version only.
+
+  [CF] smartd: Log model family from drive database if known.
+
+  [CF] drivedb.h update:
+       - SMART Xcel-10 2.5 SATA SSD: Shorten names,
+         document supported default attributes.
+
+  [CF] smartctl -P showall: Report error if attribute name is too long.
+
+  [AS] freebsd: use system ciss header if available, it is added
+       to the base system by recent commit.
+
+  [CF] smartd.conf.5.in: Update Windows 'msgbox' info.
+       Add missing IF/ENDIF for Solaris and Windows.
+
+  [CF] man pages: Remove reference to T13 web site.  It does no
+       longer provide links to the ATA documents.
+
+  [CF] smartctl: Replace '-t scttempint,N[,p]' option
+       by '-l scttempint,N[,p]'.
+
+  [CF] drivedb.h USB update:
+       - Oxford (0x0928:0x0000): unsupported, see
+         https://bugs.freedesktop.org/show_bug.cgi?id=24951
+
+  [CF] Minor cleanup to prevent warnings from new gcc 4.6 options
+       -Wunused-but-set-parameter/variable.
+
+  [CF] Windows smartd: Fix format string for 64-bit version.
+
+  [CF] Remove EXPERIMENTAL notes for features already present in 5.40.
+
+  [CF] smartctl: Add new log addresses from ACS-3 revision 1.
+
+  [CF] smartctl: Print ATA ACS-x versions properly (ticket #183).
+
+  [CF] smartctl: Add option '-l devstat[,PAGE]',
+       print ATA Device Statistics log pages (ticket #106).
+
+       Thanks to David Boreham for providing access to a machine for testing.
+
+  [AS] man pages: trivial man page syntax fixes (ticket #199)
+
+  [CF] drivedb.h update:
+       - SMART Xcel-10 2.5 SATA SSD: Fix syntax error (ticket #200)
+
+  [AS] drivedb.h update:
+       - SMART Xcel-10 2.5 SATA SSD
+
+  [DG] [SCSI] document 'ssd' list option in man page and smartctl usage.
+
+  [CF] Windows: Fix device type detection for Intel ICHxR RAID Volumes.
+
+  [CF] smartd: Resend warning emails if problem reappears (ticket #167).
+
+  [CF] smartd: Add separate directives '-l offlinests' and '-l selfteststs'
+       to enable tracking of status changes.  Disable '-l offlinests' by
+       default to avoid misleading messages (see Debian bug 636078).
+
+  [CF] drivedb.h updates:
+       - Crucial/Micron RealSSD C300/C400: Add m4 series (ticket #192)
+       - SandForce Driven SSDs: Add OCZ-AGILITY3
+       - Indilinx Barefoot based SSDs: Add RENICE Z2
+       - Intel 710 Series SSDs
+
+  [CF] Windows smartd: Fix quoting of service command line.
+
+  [CF] Cygwin smartd: Remove FreeConsole() after fork().
+       No longer needed for recent versions of Cygwin DLL.
+
+  [CF] smartd: Add some sleep() time after machine standby mode.
+       Some drivers (Intel ICHxR Windows driver) report failures if
+       pass-through is accessed immediately after wake up.
+
+  [AS] -d hpt on linux/freebsd - increased max channel number to 16,
+       fixed documentation.
+       (see http://permalink.gmane.org/gmane.linux.utilities.smartmontools/7846)
+
+  [AS] os_linux.cpp - disabling SMART WRITE LOG SECTOR command on 
+       megaraid interface for SATA disks.
+
+  [AS] os_freebsd.cpp: -l scterc was broken on FreeBSD, fixed for atacam and
+       ata drivers (bug #198).
+
+  [CF] drivedb.h updates:
+       - Crucial/Micron RealSSD C300/C400: Add C400
+       - SandForce Driven SSDs: Add Kingston HyperX,
+         OCZ-REVODRIVE, OCZ Deneva 2
+       - Intel X18-M/X25-M/X25-V G2 SSDs: Add 120GB
+       - Hitachi Travelstar 7K200: Match capital letters also
+       - Hitachi Ultrastar 7K3000
+       - Seagate Barracuda Green: Add ST2000DL001-* (ticket #195)
+       - WD My Passport Essential SE: Add WD10TMVW-*
+
+  [CF] drivedb.h USB updates:
+       - Seagate FreeAgent GoFlex USB 3.0 (0x0bc2:0x5071) (ticket #195)
+       - Seagate FreeAgent GoFlex Desk USB 3.0 (0x0bc2:0x50a1):
+         Enable -d sat,16 (ticket #151).
+       - Oyen Digital MiniPro USB 3.0 (0x0dc4:0x020a) (ticket #193)
+       - WD My Passport Essential SE USB 3.0 (0x1058:0x0740)
+
+  [CF] Windows: Add MSVC10 support, remove MSVC8 project files.
+
+  [DG] [SCSI] smartctl output Solid State Media (SSD) percentage used
+       endurance indicator. Add '-l ssd', useful for SATA SSDs?
+
+  [CF] atacmds.cpp: Rework search for temperature min/max values
+       in attributes 190/194.  This fixes temperature tracking
+       for recent WDC drives.
+
+  [CF] drivedb.h USB updates:
+       - LaCie rikiki USB 3.0 (0x059f:0x1057)
+       - Freecom Mobile Drive XXS (0x07ab:0xfc88)
+       - WD Elements SE (0x1058:0x1023)
+
+  [CF] drivedb.h updates:
+       - Indilinx Barefoot based SSDs: Add G.Skill Falcon
+       - JMicron based SSDs (JMF61x): Add Kingston SSDNow V100 Series
+       - Transcend CompactFlash Cards: Add 8, 16GB
+       - Toshiba 1.8" HDD MD..29GSG
+       - SAMSUNG SpinPoint M7U
+       - Western Digital Caviar Green (Adv. Format): Add SATA 6Gb/s variants
+       - Western Digital My Passport USB: Shorten names
+
+  [DG] [SCSI] smartd initial log entry for each drive now shows INQUIRY
+       strings and optionally the LU (logical unit) id and capacity
+
+  [AS] os_freebsd.cpp: fixed return type in autodetect_smart_device.
+
+  [CF] drivedb.h USB updates:
+       - WD My Book Essential (0x1058:0x0910, Debian bug 633724)
+       - Atech (0x11b0:0x6298)
+
+  [CF] drivedb.h update:
+       - Seagate Barracuda ES.2: Add Dell firmware versions (ticket #189)
+
+  [CF] drivedb.h updates:
+       - Seagate Maxtor DiamondMax 21: Add STM380215AS
+       - Seagate Barracuda 7200.12: Add ST3250312AS, ST31000524AS
+       - Toshiba 2.5" HDD MK..50GACY
+       - Toshiba 2.5" HDD MK..76GSX
+
+  [AS] smartd.8 - removed configuration file information from this manual,
+       added reference to smartd.conf.5.
+
+  [AS] smartd.conf.5 - added more platform-specific sections, corrected "areca"
+       device information, corrected sample configuration.
+
+  [AS] os_freebsd.cpp: detecting access to /dev/mfidX devices to show help (#97)
+
+  [CF] Update configure options in INSTALL file, remove outdated info.
+
+  [CF] int64.h: Remove outdated uint64_to_double() workaround for MSVC6.
+
+  [CF] os_win32/update-smart-drivedb.nsi: Add support for /S(ilent) option.
+
+  [CF] configure.in: Don't search for initddir and systemdsystemunitdir
+       when cross-compiling.
+
+  [CF] Makefile.am: Use same syntax also for ENABLE_* man page sections.
+
+  [CF] Add experimental support for platform-specific man pages.
+
+  [CF] Windows: Move '-I os_win32' from configure.in to Makefile.am.
+
+  [CF] configure.in: Fix check for __attribute__((packed)).
+
+  [CF] drivedb.h USB update:
+       - Verbatim Portable Hard Drive (0x18a5:0x0214)
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add OWC Mercury Extreme Pro RE (ticket #168)
+
+  [CF] os_linux.cpp: Let MegaRAID autodetect_open() fail for SATA devices.
+       MegaRAID SAT layer has serious bugs as reported by AS.
+
+  [AS] os_freebsd.cpp: Implement 48bit support for the new "atacam" 
+       interface. Tested on FreeBSD 8.2 and works fine. 
+
+  [CF] os_win32.cpp: Fix USB ID detection if two devices with the same
+       name exist (ticket #178).
+
+  [AS] os_freebsd.cpp: including ciss headers to the base, we can not rely 
+       on the header sources in the build time. Also this file was changed 
+       last time > 2 yrs. ago and it is unlikely that it will be changed in 
+       the feature. This will fix FreeBSD PR 150235.
+
+  [AS] drivedb.h update: Added Samsung Story Station 3.0 USB.
+
+  [AS] os_linux.cpp: Areca code converted to the new interface.
+       Patch is based on os_freebsd.cpp patch and is not tested yet.
+
+  [AS] os_freebsd.cpp: Areca code converted to the new interface.
+
+  [AS] os_freebsd.cpp: Added support for the Areca RAID controllers. 
+       Support is basesd on Linux code, but using IOCTL on areca control
+       device instead of SCSI commands to talk with the drives. Hardware
+       access was provided by Andrej Binder.
+
+  [CF] Don't use isprint() for ASCII character check as it may be affected
+       by setlocale().
+
+  [AS] os_freebsd.cpp: Remove all referenced to the FreeBSD 5.0.
+       It is unsupported for a very long time and probably will not compile
+       and work anyway. Also this will fix bug #154.
+
+smartmontools 5.41 2011-06-09
+
+  [MS] drivedb.h: revert attribute 190 to default for Samsung SSD controllers,
+       some 470 series SSDs seem to have some temperature information at
+       this location.
+
+  [MS] drivedb.h update:
+       add attribute details for Samsung controllers, centralize entries
+
+  [MS] drivedb.h update:
+       add attribute details for JMicron JMF61x controllers
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add OCZ DENEVA
+
+  [CF] os_win32.cpp: Ignore vendor ID "ATA" if returned by
+       IOCTL_STORAGE_QUERY_PROPERTY.
+
+  [CF] Add ATA NCQ commands to error register decoding.
+
+  [CF] Re-enable '--with-initscriptdir=auto' as default.
+       Change search for initddir and systemdsystemunitdir such that
+       default ./configure does never overwrite system files.
+
+  [MS] drivedb.h update:
+       disentangle Transcend SSD versions
+
+  [MS] drivedb.h update:
+       add attribute details for Crucial C300
+
+  [MS] smartd.initd.in:
+       fix for debian, cleanup. Based on patch of CF.
+
+  [AS] --with-initscriptdir default changed to "no" from "auto" to avoid 
+       filesystem pollution.
+
+  [MS] drivedb.h cleanup:
+       harmonize family names, add AF information into name
+
+  [MS] drivedb.h update:
+       - OCZ Vertex 3
+       - Seagate Barracuda Green 1TB variant
+
+  [CF] Windows: Avoid '%n' printf format specifier because it is always
+       disabled in recent versions of msvcrt.dll.  This fixes truncation
+       of smartd warning email (ticket #174).
+
+  [MS] smartd.initd.in:
+       cleanup, provide targets "reload" and "report" for all platforms
+
+  [CF] drivedb.h update:
+       - JMicron based SSD (JMicron JMF602?): rename from
+         Kingston SSDNow V Series, move Transcend IDE and SATA
+         entries to here.
+
+  [CF] Support ':BYTEORDER' for all attribute print formats.
+
+  [CF] drivedb.h update:
+       - Kingston SSDNow V Series SSDs (ticket #171)
+
+  [CF] Increase size of drive database option parse buffer
+       to allow long '-v N,FORMAT:BYTEORDER,NAME' options.
+
+  [MS] drivedb.h update:
+       - Western Digital Scorpio Blue Advanced Format variants
+
+  [MS] drivedb.h update:
+       correct typo for Cowon iAudio X5
+
+  [MS] drivedb.h USB updates:
+       - Maxtor OneTouch 200GB (unsupported)
+       - LaCie Little Disk
+
+  [AS] FreeBSD: Added native rc.conf style script to the package. 
+       Modifications to the configure script to use correct template and
+       path.
+
+  [AS] freebsd_os.cpp:
+       Fix memory leak in the ata detection code (added free())
+       Using bzero in cam code to clear structure (fixing varnish varning)
+
+  [MS] drivedb.h update:
+       Kingston SSDNow S100 Series
+
+  [MS] drivedb.h USB update:
+       - Samsung S1 Portable
+       - LaCie rikiki USB 3.0
+       - Seagate FreeAgent GoFlex USB 3.0
+       - Cowon iAudio X5
+       - Oxford OXU921DS chip (unsupported)
+
+  [CF] Windows: Add debug output of SCSI sense data.
+
+  [CF] Add 'smartd.service' file for systemd.
+       Add configure option '--with-systemdsystemunitdir'.
+       Disable initd script if systemd is used.
+
+  [MS] drivedb.h update:
+       - Western Digital AV-25 family
+
+  [MS] drivedb.h update:
+       JMicron based SSDs: Add
+         Kingston SSDNow V, Kingston SSDNow V+100, TOSHIBA THNS128GG4BBAA,
+         APPLE SSD TS*, ADATA S596 Turbo
+
+  [CF] drivedb.h update:
+       - Intel 510 Series SSDs (ticket #170)
+
+  [CF] smartctl: Don't issue SMART DISABLE command to 3ware controllers
+       when the port number was not specified (ticket #165).
+
+  [CF] Use get_errmsg() from device instead of errno or syserror() for
+       printing error messages.
+
+  [MS] drivedb.h updates:
+       - G.Skill FALCON II SSD (Indilinx)
+       - HP 250GB SATA disk VB0250EAVER
+       - SAMSUNG SpinPoint M5 HM160HC
+       - SAMSUNG SpinPoint MT2 HM100UI
+       - SAMSUNG HM100UX
+       - Hitachi Deskstar 5K3000 Series
+       - Seagate Barracuda Green (Adv. Format)
+       - Seagate Barracuda XT 3TB variant
+       - Western Digital RE4 Serial ATA family
+       - Western Digital Caviar Green WD20EACS
+       - Western Digital Caviar Black family, SATA 3.0 variants
+       - QUANTUM FIREBALLlct20 10
+       - QUANTUM FIREBALLP AS60.0
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add more OCZ SF-1200 and SF-1500 based drives
+
+       Thanks to Sudhir Verman from OCZ Technology for providing this info.
+
+  [CF] drivedb.h USB updates:
+       - Seagate Expansion External (0x0bc2:0x3300) (Debian bug 621411)
+       - ASMedia USB 3.0 (0x174c:0x55aa) (unsupported)
+
+  [CF] smartctl.8.in: Clarify '-t vendor,N' (ticket #169).
+       Update Intel info (ticket #168).
+
+  [CF] drivedb.h update:
+       - Intel 320 Series SSDs (ticket #168)
+
+  [CF] smartctl: Always print sector size in '-i' output (ticket #166).
+
+  [CF] os_linux.cpp: Shorten version string.
+
+  [CF] smartctl: Add option '-f brief' to select new attribute output
+       format.  This format includes additional attribute flags
+       (ticket #109) and fits in 80 columns (ticket #158).
+       This format is now the default for '-x'.
+
+  [CF] smartd: Log changes of offline data collection status if
+       '-l selftest' is specified.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add ADATA S599 64GB,
+         OWC Mercury Extreme Pro
+       - Kingston branded X25-V SSDs (ticket #156)
+       - Transcend SATA Solid State Drive: Truncate attribute name
+
+  [CF] drivedb.h USB updates:
+       - LaCie (0x059f:0x1029) (ticket #153)
+       - WD My Book Office Edition (0x1058:0x1101)
+       - JMicron USB 3.0 (0x152d:0x0539)
+
+  [CF] drivedb.h USB update:
+       - Verbatim Pocket Hard Drive (0x18a5:0x0227) (ticket #159)
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint N3U-3 (USB, 4KiB LLS) (ticket #159)
+
+  [CF] Add support for ATA Long Logical Sectors (LLS) (ticket #159).
+
+  [DG] [SCSI] smartctl: (re-)use capacity formatting in utility.cpp
+
+  [CF] configure.in: Remove '-Wno-format' for MinGW.
+       Recent MinGW versions support MSVCRT printf format strings.
+
+  [CF] Print ATA disk capacity with SI prefix.
+       Add/move capacity formatting to utility.cpp
+
+  [CF] Add error messages if ATA pass-through does not return required
+       ATA output registers (for SMART RETURN STATUS, GET POWER MODE).
+       This prevents misleading 'SMART Status command failed' messages
+       (see ticket #155).
+
+  [CF] Fix WWN support check for older ATA-7 disks.
+
+  [DG] [SCSI] smartctl: add 'Logical Unit id' from the Device
+       Identification VPD page (0x83)
+
+  [DG] [SCSI] smartctl: add 'User Capacity' (disk size) in human
+       readable form
+
+  [CF] smartctl, smartd: Print World Wide Name (WWN) of ATA device.
+
+  [CF] smartctl: Print more specific error message if IDENTIFY DEVICE
+       failed (ticket #61).  Add check for empty IDENTIFY data.
+
+  [CF] Windows installer: Add help message box.
+
+  [CF] Windows installer: Request admin rights, select 'All Users'
+       section.  This fixes shortcut removal under Vista and later.
+       Add '/SO' option to select components for unattended install.
+       Patch was provided by József Fejes.
+
+  [CF] Windows: Add update-smart-drivedb.nsi NSIS script to build
+       drivedb.h update tool.
+
+  [CF] Windows: Move search for NSIS compiler from Makefile.am to
+       configure.in.
+
+  [CF] update-smart-drivedb.in: Move DRIVEDB_BRANCH name creation
+       from script to configure.in.
+
+  [CF] os_linux.cpp: Replace printf() by pout().  Disable unused
+       function dumpdata().
+
+  [CF] Windows: Include CSMI (for Intel RAID) in default DEVICESCAN.
+
+  [CF] configure.in: Remove info messages about old defaults.
+
+  [CF] drivedb.h: Set unneeded USB bcdDevice patterns to empty.
+
+  [CF] Rework USB ID drivedb search.  Stop search at first matching
+       entry with empty bcd_device pattern.
+
+  [CF] Move handling of '-F swapid' from formatting to identity read
+       function.  Remove unneeded 'fix_swapped_id' parameters.
+
+  [CF] smartd: Log warning from drive database if present.
+       smartctl: Do not search drive database twice.
+
+  [MS] drivedb.h USB updates:
+       - Samsung S2 Portable variant (0x04e8:0x1f08)
+       - Lacie rikiki (0x059f:0x102a)
+       - Toshiba Stor.E Steel series (0x0930:0x0b11)
+       - Super Top generic enclosure (0x14cd:0x6116)
+
+  [CF] Let constructor of regular_expression throw on error by default.
+
+  [CF] smartd: Preserve last selective self-test span in '.state' file
+       and use it if the selective self-test log was cleared (ticket #88).
+
+  [CF] smartctl --scan-open: Make output compatible with smartd.conf
+       (ticket #108).  Fix possible crash if autodetect_open() returns
+       new object.
+
+  [CF] do_release: Re-add signing of tarball.
+
+  [CF] os_linux.cpp: Change '-d sat' to '-d sat,12' for USB only if
+       kernel is older than 2.6.29.  Add kernel release to version info.
+
+  [CF] smartd: Add '-l scterc,READTIME,WRITETIME' directive (ticket #150).
+
+  [CF] smartctl: Fix exit status of '-l xerror' and '-l xselftest'
+       (ticket #144).
+
+  [CF] smartd: Use '-M daily' as default if state persistence is enabled.
+       This avoids that emails are suppressed forever (ticket #35).
+
+  [CF] smartd: Log identify information of each ATA device.
+
+  [CF] smartd: Disable '-C' and '-U' monitoring if raw values are
+       very large (ticket #148).
+
+  [CF] smartd: Write reserved attribute byte to '.state' file
+       (ticket #118).
+
+  [MS] drivedb.h USB updates:
+       - Seagate FreeAgent Go Flex Desk USB 3.0
+       - Toshiba Canvio 500GB
+
+  [MS] drivedb.h USB updates:
+       - Freecom HD 500GB (0x07ab:0xfcda)
+       - Generic JMicron adapter (0x152d:0x2337)
+       - RaidSonic ICY BOX IB-110StU3-B (0x1759:0x500[02])
+       - Connectland BE-USB2-35BP-LCM (0x040d:0x6204)
+       - Freecom Classic HD 120GB (0x07ab:0xfccd)
+       - OCZ THROTTLE OCZESATATHR8G (0x152d:0x0602)
+       - Vantec NST-400MX-SR (0x1a4a:0x1670)
+       - Intenso Memory Station 2.5" (0x13fd:0x1840)
+
+  [CF] Don't report failed self-tests outdated by a newer successful
+       extended self-test as errors (ticket #147).
+       This affects smartctl exit status and smartd syslog output and
+       warning email.  Only implemented for ATA.
+
+  [CF] os_linux.cpp: Don't use buffer of size PATH_MAX for the result
+       of realpath().  This also fixes compilation on Debian Lenny.
+
+  [CF] smartd man pages: Add some missing [ATA only].
+
+  [CF] os_linux.cpp: Dereference symlinks before guess of device type
+       (ticket #146).  Minor rework of autodetect_smart_device().
+
+  [CF] smartctl -l scterc: Don't get ERC if only set is requested.
+       This prevent misleading error messages if ATA output registers
+       are not supported.
+
+  [CF] Windows: Prevent warnings from gcc 4.5.1.
+
+  [CF] os_netbsd.cpp, os_openbsd.cpp: Add missing <errno.h>
+
+  [CF] os_freebsd.cpp: Add missing <errno.h>
+
+  [CF] dev_legacy.cpp: Add missing <errno.h>
+
+  [CF] Linux megaraid: Fix pass-through of non-data ATA commands
+       (ticket #149).
+       Only reject commands which require ATA output registers.
+
+  [CF] configure.in: Remove '-fno-strict-aliasing' from CXXFLAGS.
+       This reverts r2992 (see ticket #23).
+
+  [CF] Linux megaraid: Avoid strict-aliasing warnings.
+       Patch was provided by Stanislav Brabec (2009-06-03).
+
+  [MS] Make functions without prototypes static.
+
+  [MS] Remove unnecessary includes, move inclusion of errno.h from scsicmds.h
+       to the appropriate *.cpp files. Add cciss.h to cciss.cpp.
+
+  [MS] os_linux.cpp: rename variables to please "-Wshadow"
+       utility.cpp: remove unused variable "start"
+       os_win32/syslogevt.c: plug resource leak
+
+  [CF] Rename variables to prevent warnings if '-Wshadow' is set.
+       Remove unnecessary includes.  Fix some comments.
+
+  [CF] drivedb.h updates:
+       - Intel X18-M/X25-M/X25-V G2 SSDs: Add firmware bug warning
+       - Samsung SpinPoint M6
+       - Samsung SpinPoint M7E (AFT)
+       - Samsung PM800 SSDs
+       - Samsung PM810 (470 series) SSDs
+
+  [CF] Windows: Add experimental CSMI support for disks behind Intel Matrix
+       RAID driver. Accessed through new device names '/dev/csmi[0-9],N'.
+       Experimental DEVICESCAN can be enabled by '-d csmi'.
+
+  [MS] - ataprint.cpp: adjust print format for insanely large
+           offline data collection times (e.g. WD drives).
+       - getopt: change config.h #include format from angle brackets to quotes
+
+  [MS] drivedb.h update:
+       - Fujitsu MJA2 BH series
+       - Toshiba MK..59GSXP series (Adv. Format)
+       - Toshiba MK..59GSM series (Adv. Format)
+       - Western Digital Caviar Blue SATA 3.0 variants
+       - Seagate Barracuda XT
+
+  [CF] smartctl: Print help message if no option is specified (ticket #39).
+       Don't issue any other ATA command if only '-n POWERMODE' is specified.
+
+  [CF] smartd: Output multiple lines via separate syslog(3) calls
+       (ticket #135).
+
+  [CF] smartctl: Add new ATA minor revisions and log addresses from ACS-2
+       revision 4a.  Replace runtime asserts by compile time asserts.
+
+  [CF] smartd: Remove "default: /var/log/messages" hint from warning mail.
+       This obsoletes Debian patch 60_remove-redhatism.diff.
+
+  [CF] Windows: Include USB devices in DEVICESCAN (ticket #116).
+
+  [CF] Windows: Use direct WMI access to detect USB IDs (ticket #115).
+       This replaces 'wmic' runs and speeds up USB detection.
+
+  [CF] configure.in: Rework platform-specific settings.
+
+  [CF] configure.in: Remove some no longer used settings:
+       -lselinux (duplicate), NEED_SOLARIS_ATA_CODE, OS_FREEBSD.
+
+  [CF] Makefile.am: Remove SUBDIRS. Recursive targets are no longer used.
+
+  [CF] Use log directory to check for old error and self-test log
+       support (ticket #89).
+
+  [CF] drivedb.h USB update:
+       - WD My Book Essential 3TB USB 3.0
+
+  [CF] Fix usb header includes for DragonFly BSD (ticket #141).
+
+  [CF] smartctl: Print physical and logical sector sizes (ticket #62).
+
+  [CF] drivedb.h updates:
+       - Fujitsu MHT: Add AC variant
+       - Fujitsu MHW2 AC
+       - Samsung SpinPoint T166: Needs '-v 197,increasing'
+       - Seagate Barracuda 7200.11: Add firmware SD81 as buggy
+       - WD Scorpio Blue EIDE: Add 320GB
+
+  [CF] drivedb.h USB updates:
+       - Samsung S2 Portable (ticket #136)
+       - Move Verbatim 0x152d:0x2351 to JMicron section
+
+  [AS] drivedb.h updates:
+       - Verbatim Portable Hard Drive eSATA & USB 2.0 Combo 500GB
+
+  [CF] Happy New Year! Update copyright year in version info.
+
+  [CF] drivedb.h updates:
+       - Hitachi Deskstar 7K3000
+       - Hitachi Travelstar 7K320: Add ...362 variant
+       - Seagate Maxtor DiamondMax 21: Add STM3250310AS
+       - Toshiba 2.5" HDD MK..65GSX
+       - WD Caviar Green (Adv. Format): Add 750GB, 2.5TB, 3TB
+
+  [CF] drivedb.h USB updates:
+       - Micron USB SSD (unsupported, ticket #133)
+       - Samsung G2 Portable (ticket #132)
+       - Samsung Story Station 3.0 (ticket #130)
+       - Seagate FreeAgent GoFlex (ticket #131)
+
+  [CF] update-smart-drivedb.in: Add workaround for OpenBSD shell bug:
+       'set -e; if eval false; ...' aborts script (ticket #128).
+
+  [CF] update-smart-drivedb.in: Add platform specific download tools:
+       'fetch' on FreeBSD (ticket #127), 'ftp' on OpenBSD.
+
+  [CF] drivedb.h USB updates:
+       - JMicron 0x152d:0x2509
+       - WD My Passport 0730
+
+  [CF] drivedb.h updates:
+       - Samsung SpinPoint F3 EG: Add 2TB
+       - SandForce Driven SSDs: Add ADATA S599, SuperTalent TeraDrive CT
+       - Seagate Constellation (SATA)
+       - Seagate Constellation ES (SATA)
+       - WDC My Passport: Add WD5000BMVW
+
+  [CF] drivedb.h update:
+       - Samsung SpinPoint F4 EG: Add 1.5TB, update firmware bug warning.
+
+  [DG] [SCSI] Fix log page sanity check problem if the DS bit set
+       in response. Caused '-l background' to fail.
+
+  [CF] drivedb.h updates:
+       - Samsung SpinPoint F4 EG: Warning about bad blocks
+
+  [CF] update-smart-drivedb.in: Replace ERE by BRE.  Script does no
+       longer require GNU sed (Ticket #126).
+
+  [DG] In '-r ioctl' show vendor specific SCSI commands as such rather
+       than 'unknown'.
+
+  [CF] Add check for CompactFlash Signature in ATA IDENTIFY data.
+       This avoids that older CF microdrives are detected as ATAPI
+       devices (Ticket #125).
+
+  [CF] drivedb.h updates:
+       - Apple SSDs TS*
+       - Crucial RealSSD C300 Series
+       - Kingston SSDNow V Series
+       - Indilinx Barefoot based SSDs: Add OCZ-ONYX
+       - SandForce Driven SSDs: Add OCZ VERTEX2-PRO
+       - Transcend CompactFlash Cards: Add TS4GCF133
+
+  [CF] Windows installer: Add missing quotes in smartctl-run.bat
+       and smartd-run.bat (Ticket #124).
+
+  [CF] OpenBSD: Fix DEVICESCAN for OpenBSD >= 4.8 (Ticket #123).
+
+  [CF] daemon_win32.cpp: Remove duplicate assignment (Ticket #120).
+
+  [CF] Makefile.am: Do not overwrite existing smartd.conf file
+       (Ticket #122).  If smartd.conf exists and differs from the
+       default then smartd.conf.sample is installed instead
+       If smartd.conf.sample exists on uninstall then smartd.conf is
+       preserved.
+
+  [CF] Linux megaraid: Fix segfault on non-data commands (Ticket #78).
+       The /dev/megaraid_sas_ioctl_node driver does not allow
+       sge_count = 1 and sgl[0].iov_len = 0.
+
+  [CF] Remove EXPERIMENTAL notes for features already present
+       in 5.39.
+
+  [CF] Rework '-d TYPE' documentation on man pages.
+
+  [CF] drivedb.h updates:
+       - Seagate Maxtor DiamondMax 21: Add 80GB
+       - Western Digital Caviar Black: Add 1TB/64MB
+
+  [CF] drivedb.h USB updates:
+       - iRiver iHP-120/140 (Ticket #119)
+       - ASMedia ASM1051
+
+  [CF] Makefile.am: Handle examplescripts in main Makefile.
+       Remove 'examplescripts/Makefile.am'.
+
+  [CF] configure.in: New option '--with-exampledir' allows to change
+       path of 'DOCDIR/examplescripts' directory.
+       (Debian package uses '/usr/share/doc/smartmontools/examples')
+
+  [CF] Replace global 'con->dont_print/...' variables by 'printing_is_*'.
+       Remove global 'con'trol pointer.  Remove file 'extern.h'.
+
+  [CF] Replace global 'con->reportata/scsiioctl' variables by '*_debugmode'.
+
+  [CF] Replace global 'con->conservative/permissive' variables by
+       'failuretest_*'.  Move failuretest() function to smartctl.cpp.
+
+  [CF] Remove unused CONTROLLER_* defines.
+
+  [CF] Remove unused controller support from dev_legacy adapter module.
+
+  [CF] Make 'debugmode' variable local to smartd.cpp.
+
+smartmontools 5.40 2010-10-16
+
+  [CF] examplescripts/Example3: Use stdin to pass message to 'wall'
+       command (ticket #114).
+
+  [CF] smartd: Fix setting of SMARTD_DEVICE and SMARTD_DEVICETYPE
+       environment variables (ticket #113).
+       Regression was introduced by rework of smartd data structures.
+       SMARTD_DEVICE is now set to the plain device name.
+       SMARTD_DEVICETYPE is now set to 'auto' if no '-d' directive is
+       specified.  Smartctl now accepts '-d auto' for this purpose.
+
+  [CF] Remove "Lifetime" from Min/Max temperature attribute output
+       (ticket #111).  Interval is device specific.
+
+  [CF] configure.in: Print resource/message compiler info for Windows only.
+
+  [CF] FreeBSD: Rework get_dev_names_cam() to support more than 26 devices.
+
+  [CF] drivedb.h updates:
+       - Seagate Barracuda 7200.10: Add 360GB
+       - USB: Iomega MDHD-UE
+       Patch provided by Rob Marissen.
+
+  [DL] Standby mode not detected properly on FreeBSD (ticket #91).
+
+  [MS] os_linux.cpp: fix "gcc -flto" build error by including stddef.h
+
+  [CF] drivedb.h update:
+       - Indilinx Barefoot based SSDs: Add OCZ-VERTEX 1199 and -TURBO
+
+  [CF] TODO file: Move open entries to tickets #106, #107, #108, #109, #110.
+       Remove outdated entries.
+
+  [CF] drivedb.h USB update:
+       - SunPlus 0x04fc:0x0c05
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add Corsair Force, fix typo
+
+  [CF] Print hex values of unknown self-test type or status.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Fix regex for Unigen UG99SGC
+       - Seagate Momentus XT series
+       - Quantum Bigfoot: Add 12.7GB
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add 11 attributes of new FW,
+         add Unigen UG99PGC
+       - WD AV ATA family: Add 250GB, 320GB
+       - WD AV SATA family
+
+  [CF] Windows: Build syslogevt.exe with MinGW.  Now possible because
+       binutils provides windmc.
+
+  [CF] Makefile.am: Remove install message about smartd startup.
+       It might be misleading because it is not correct for all platforms.
+
+  [CF] configure.in: Minor fix of '--enable-drivedb' new defaults
+       detection.
+
+  [CF] Update links, configure and OS info in INSTALL file.
+       Replace tabs by spaces.
+
+  [CF] configure.in: Fix '--enable-sample' and '--with-selinux'.
+       Fix obsolete use of AC_DEFINE().
+
+  [CF] drivedb.h updates:
+       - IBM Deskstar 60GXP, 40GV & 75GXP: Update link (ticket #99)
+       - Seagate Barracuda 7200.12: Add ST31000523AS and others
+       - WD Caviar Black: Add 2TB
+       - WD VelociRaptor: Add 6 Gb/s models
+
+  [CF] Windows installer: Fix smartctl-run.bat for drive menu (ticket #31).
+
+  [CF] Windows: Create md5/sha1/sha256 checksums of the binaries.
+       Add checksums.txt file to binary distribution.
+
+  [CF] Windows: Include drivedb.h into binary distribution.
+
+  [CF] drivedb.h updates:
+       - Intel X18-M/X25-M/X25-V G2: Add X25-V 40GB
+       - Transcend CompactFlash Cards
+
+  [CF] drivedb.h updates:
+       - Seagate Momentus 7200 FDE.2: Add ST9160414ASG
+       - Seagate Pipeline HD 5900.1 and 5900.2
+       Based on patch provided by Marcin Falkiewicz.
+
+  [CF] Remove unused variable 'reportbug'.
+
+  [CF] Make function PrintOut() local to smartd.cpp, remove it from
+       smartctl.cpp.
+
+  [CF] Windows: Improve compatibility with MinGW variants.
+       Add configure check for DDK include files.
+       Drop support for '-mno-cygwin' from old Cygwin gcc.
+
+  [AS] smartctl.8.in minor update: adding FreeBSD ahci/scsi device hints
+
+  [CF] Fix build if SVN Id keywords are not expanded (ticket #94).
+
+  [CF] Windows: Remove "." from DLL search path to prevent DLL
+       preloading attacks.
+
+  [CF] drivedb.h USB update:
+       - JMicron 0x152d:0x0551 (ticket #95)
+       Add note about port multipliers to smartctl man page.
+
+  [CF] drivedb.h updates:
+       - SandForce Driven SSDs: Add Unigen drives
+       - Indilinx Barefoot based SSDs: Add ASAX Leopard Hunt II
+
+  [CF] drivedb.h update:
+       - Intel X18-M/X25-M G2: Add names of timed workload attributes.
+       Document attribute clear command '-t vendor,0x40' on smartctl
+       man page.
+
+       Thanks to Artem Danielov from Intel for providing the
+       required information and drives for testing.
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs: Add OCZ drives with form factor info.
+
+  [CF] drivedb.h update:
+       - Intel X25-E, X18-M/X25-M (add X18-M, update attributes)
+
+  [CF] configure.in: '--enable-drivedb' is now the default.
+
+  [CF] drivedb.h update:
+       - Indilinx Barefoot based SSDs
+         (combine and update 5 SSD entries using this controller)
+
+  [CF] drivedb.h update:
+       - SandForce Driven SSDs (Demo Drive, OCZ-Agility2/Vertex2/Vertex-LE)
+
+       Thanks to Jeremy Werner (jwerner@sandforce.com) from SandForce for
+       providing the required information and a demo drive for testing.
+
+  [CF] drivedb.h update:
+       - Add 1.5TB drive to SAMSUNG SpinPoint F3 EG series
+
+  [CF] Add print formats '-v ID,msec24hour32' and '-v ID,raw24/raw32'.
+       Used by SSDs with SandForce controller.
+
+  [CF] Allow SMART threshold entries at positions different from
+       attribute table. This fixes attribute output for recent
+       SSDs with SandForce controller.
+
+  [CF] smartctl: Add option '-t vendor,N' to issue ATA
+       command SMART EXECUTE OFF-LINE IMMEDIATE with
+       a vendor specific subcommand.
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint V80 series (ticket #85)
+
+  [CF] Linux: Support SATA drives on LSI 3ware 9750 controllers.
+       Patch provided by Victor Payno (ticket #86).
+       Modified to avoid duplicate code.
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint M7 series
+
+  [CF] drivedb.h USB update:
+       - Buffalo JustStore Portable HD-PVU2
+
+  [CF] drivedb.h USB updates:
+       - Iomega LDHD-UP (ticket #83)
+       - WD Elements Desktop 2TB
+       - Maxtor OneTouch (0x0d49:0x7300)
+
+  [MS] drivedb.h updates:
+       - Intel X25-M SSD first Generation
+       - ExcelStor J8160
+       - OCZ Agility2
+
+  [CF] drivedb.h updates:
+       - Transcend Solid State Drives (ticket #80)
+
+  [CF] drivedb.h USB update:
+       - LaCie Rugged Hard Drive
+
+  [CF] smartctl: Add options '--scan, --scan-open'.
+
+  [CF] Windows: Use also VendorId from IOCTL_STORAGE_QUERY_PROPERTY.
+
+  [CF] smartd: Change defaults of '-C' and '-U' directives to 0 (disabled)
+       if attribute name is changed by '-v 19[78],...' directive.
+
+  [CF] configure.in: Fix include path for MinGW.
+
+  [CF] Move 'posix/reg*' to 'regex/reg*'.
+       Add configure check for regex.
+
+  [MS] cciss.cpp: avoid redefining be32toh
+       megaraid.h: replace use of undefined preprocessor macro BITS_PER_LONG
+                   by union construct (thanks to [DL]).
+                   Add assert for sizeof(ptr_t) == 8 (thanks to [CF]).
+
+  [CF] Makefile.am: Add os_qnxnto.* to EXTRA_smart*_SOURCES.
+
+  [MS] drivedb.h update:
+       - WD My Passport Essential SE 1TB variant (USB interface)
+
+  [CF] Use getopt_long() from getopt/getopt* if necessary.
+       Add missing cast to os_qnxnto.cpp.
+       This fixes build on QNX (ticket #1).
+       Thanks to Stefan (stevestereo) for testing.
+
+  [CF] drivedb.h update:
+       - WD Caviar Green (Adv. Format) family
+
+  [CF] drivedb.h USB update:
+       - Verbatim External Hard Drive 47519
+
+  [DL] Fix regression in smartctl option '-t select,M-N' which prevents
+       that more than one test span can be specified (ticket #75).
+
+  [CF] drivedb.h updates:
+       - Add raw64 attributes 1, 210-213 to all SSD drives with
+         64-bit attribute format.
+
+  [CF] Support smartd '-l xerror' also for disks which use reserved
+       byte as log index.
+
+  [CF] Fix initialization of values missing in smartd '.state' files.
+
+  [CF] Add smartd directive '-l xerror' to check error count from
+       the Extended Comprehensive SMART Error Log (ticket #34).
+
+  [CF] Fix max number of cciss devices, 128 devices are supported
+       again (ticket #49). Regression was introduced during migration
+       to new interface.
+
+  [CF] Update man pages (include Debian patch
+       60_remove-redhatism.diff and Debian Bug 570892).
+
+  [CF] Add SVN revision number to man pages.
+
+  [CF] Windows: Read default drivedb.h and smartd.conf from exe
+       directory instead of current directory.
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint M series
+
+  [CF] Replace runtime check of byte ordering by compile time check.
+
+  [CF] drivedb.h USB updates:
+       - ALi M5621 (unsupported)
+       - LaCie with JMicron (ticket #69)
+       - JMicron (0x2352)
+       - Enable 48-bit commands for Hitachi drive
+
+  [CF] Read USB ID info from drivedb.h (ticket #44).
+
+  [CF] Create branch RELEASE_5_39_DRIVEDB with last drivedb.h file
+       compatible with smartmontools 5.39[.1].
+
+  [MS] drivedb.h updates:
+       - WD Raptor 80GB variant
+       - correct Regex for some WD AV-GP variants
+       - Hitachi Ultrastar A7K2000
+       - Hitachi Travelstar 5K500.B
+       - Hitachi Deskstar 7K1000.C
+       - adjust naming of Hitachi Travelstar and Deskstar drives
+
+  [CF] Move 'posix/getopt*' to 'getopt/getopt*'.  Can be used for
+       platforms with regex() but without getopt_long() (QNX, ticket #1).
+
+  [CF] smartd '-l selftest' directive: Print info if error count
+       decreased.  Avoid misleading warning if error count decreased
+       to zero (ticket #67).
+
+  [CF] smartctl: Rework ataPrintMain().  Issue ATA SMART commands only if
+       necessary.  Improve handling of SMART STATUS command failure when
+       ATA output registers are missing (ticket #27).
+
+  [CF] USB ID updates:
+       - A-DATA SH93
+       - Hitachi/SimpleTech 1TB
+
+  [CF] configure.in: Print configuration summary.
+
+  [CF] smartctl -l xselftest,selftest: Print old log if extended self-test
+       log index is out of range.  Workaround for bad log data from Intel
+       X25-M G2 (ticket #66).
+
+  [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)
+
+  [CF] Makefile.am: Avoid duplication of man page filter script.
+
+  [CF] smartd: Add option '-C, --capabilities' if libcap-ng is available
+       (ticket #45).
+       Support is added if libcap-ng is found during build. This can
+       be overridden by configure option '--with-libcap-ng=[auto|yes|no]'.
+
+       Based on Debian patch:
+       http://patch-tracker.debian.org/patch/series/view/smartmontools/5.39-3/62_lowcap.patch
+       Modified to fix regression (ticket #41, Debian bug 564876).
+
+  [CF] Bugfix release 5.39.1.
+
+  [CF] Linux: Fix spin-up of SATA drive if '-n standby' is used
+       (ticket #37).  For some reason, this happens if the SCSI/SAT
+       device is opened with O_RDWR instead of O_RDONLY.
+
+  [CF] Windows: Fix parsing of 'tw_cli' output for 3ware 9.5.x release
+       (ticket #43).
+
+  [CF] Add USB IDs of Seagate FreeAgent Go, Seagate Expansion Portable
+       and WD My Passport (IDE).
+
+  [CF] autogen.sh: Fix version regexp, allow automake 1.11.1.
+
+  [CF] Linux: Allow smartd 'DEVICESCAN -d sat' (ticket #13).
+       Detects (S)ATA devices behind a standard SAT layer
+       (Vendor ID: "ATA     "), but not USB bridges with SAT support.
+       Only added for backward compatibility with 5.38.
+       No longer needed as 'DEVICESCAN' without '-d' includes these devices.
+
+  [CF] Add USB ID of Seagate FreeAgent Desktop.
+
+  [CF] smartd: Fix directive '-l selftest' (ticket #36)
+       Regression was introduced with r2773.
+
+  [CF] smartd: Don't disable attribute tracking if read thresholds fails.
+       Windows: Don't return dummy thresholds if IOCTL_STORAGE_QUERY_PROPERTY
+       or 3ware CLI is used to read SMART data.
+
+  [CF] Windows: Print warning if admin rights are missing.
+
+  [CF] Replace some 'EXIT(status)' calls by 'return status'.
+       Remove unnecessary casts from 'nonempty()' calls.
+
+  [CF] Windows: Set ata_device::ata_identify_is_cached() return value
+       according to I/O-control actually used.
+
+  [CF] Print ATA output registers if SMART status command returns bogus
+       register values.
+
+  [CF] Windows: Don't return false ATA version info if IDENTIFY data
+       is build from IOCTL_STORAGE_QUERY_PROPERTY result or from 3ware CLI
+       output.
+       smartctl: Handle missing info about ATA version in '-i' output.
+
+  [CF] smartctl: Don't print log directory if '-q errorsonly' is specified.
+
+  [CF] smartctl: Fix option '-q, --quietmode' (ticket #11).
+       Regression was introduced with r2807.
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint F2 EG series
+
+  [CF] Add USB ID of Samsung Story Station.
+
+  [MS] drivedb.h update:
+       - Hitachi Travelstar 5K320: some EA models miss last 2 "0" 
+         in model string
+       - Seagate Barracuda LP series
+
+  [CF] drivedb.h update:
+       - Crucial M225 SSD
+
+  [CF] drivedb.h updates:
+       - WDC Scorpio Blue Serial ATA (640GB, 750GB, 1TB)
+       - WDC My Passport Essential SE
+
+  [CF] Add USB ID of Toshiba PX1270E-1G16.
+
+  [CF] Happy New Year! Update copyright year in version info.
+
+  [CF] drivedb.h update:
+       - SAMSUNG SpinPoint M40/60/80 series
+
+  [CF] Add direct access to 48-bit LBA register in 'ata_in/out_regs_48bit'.
+
+  [DL] drivedb.h updates:
+       - WDC My Passport Essential/USB (capacity 250GB, 400GB & 500GB)
+
+  [DL] -r ataioctl,2: print text representation of data also (ticket #32)
+
+  [DL] FreeBSD: freebsd_ata_device::ata_pass_through implemented (part of ticket #18)
+
+  [CF] drivedb.h updates:
+       - Hitachi Travelstar 7K320 (ticket #28)
+       - Hitachi Travelstar 7K500
+
+  [DL] -l gpllog,...: print text representation of data also (ticket #30)
+
+  [DL] FreeBSD: check reallocf() result for failures
+
+  [AS] FreeBSD: fixing crash on kFreeBSD (#29), patch provided by Petr Salinger
+
+  [CF] Makefile.am: 'make check' now tests the syntax of drivedb.h.
+
+  [CF] Cygwin: Open drive database files in text mode.
+
+  [CF] Cygwin: Check for 'syslogd' and 'syslog-ng' in initd script.
+
+  [CF] Windows: Disable Win9x/ME specific code if no longer supported
+       by compiler.
+
+  [CF] Add '-v ID,FORMAT:BYTEORDER[,NAME]' to specify byte order
+       of attribute raw value.
+
+  [CF] configure.in: Change --with-docdir default from
+       'PREFIX/share/doc/smartmontools-VERSION' to
+       'DATADIR/doc/smartmontools' to make it consistent with
+       --docdir option added in autoconf 2.6x (ticket #24).
+       Autoconf 2.5x is still supported.
+
+  [CF] Move drive database entries from 'knowndrives.cpp' to new file
+       'drivedb.h'.  This allows to update the drive database from SVN
+       if installation was configured with '--enable-drivedb'.
+       Remove the Makefile target to create 'drivedb.h'.
+
+  [CF] do_release: Add support to release from a dir below 'branches'.
+       Accept partial checkouts.
+
+smartmontools 5.39.1 2010-01-28
+
+  [CF] Linux: Fix spin-up of SATA drive if '-n standby' is used
+       (ticket #37).  For some reason, this happens if the SCSI/SAT
+       device is opened with O_RDWR instead of O_RDONLY.
+
+  [CF] Windows: Fix parsing of 'tw_cli' output for 3ware 9.5.x release
+       (ticket #43).
+
+  [CF] Linux: Allow smartd 'DEVICESCAN -d sat' (ticket #13).
+       Detects (S)ATA devices behind a standard SAT layer
+       (Vendor ID: "ATA     "), but not USB bridges with SAT support.
+       Only added for backward compatibility with 5.38.
+       No longer needed as 'DEVICESCAN' without '-d' includes these devices.
+
+  [CF] smartd: Fix directive '-l selftest' (ticket #36)
+       Regression was introduced with r2773.
+
+  [CF] smartctl: Don't print log directory if '-q errorsonly' is specified.
+
+  [CF] smartctl: Fix option '-q, --quietmode' (ticket #11).
+       Regression was introduced with r2807.
+
+  [CF] Happy New Year! Update copyright year in version info.
+
+  [DL] FreeBSD: check reallocf() result for failures
+
+  [AS] FreeBSD: fixing crash on kFreeBSD (#29), patch provided by Petr Salinger
+
+  [CF] do_release: Add support to release from a dir below 'branches'.
+       Accept partial checkouts.
+
+smartmontools 5.39 2009-12-09
+
+  [CF] do_release: Commit CHANGELOG and NEWS also. Allow to review changes.
+
+  [CF] Linux: Add workaround for Adaptec series 2, 5 and 5Z controllers
+       with firmware >= 17380.  Patch was provided by Phil Wilson, see:
+       http://linux.adaptec.com/2009/07/24/using-smartmontools-538-with-series-255z-controllers-with-firmware-17380-onwards
+
+  [CF] configure.in: Add '-fno-strict-aliasing' to CXXFLAGS if supported.
+       This suppresses gcc 4.4.1 warnings on Linux and avoids possible
+       unsafe optimizations (ticket #23).
+       Patch was provided by Manfred Schwarb.
+
+  [CF] Avoid truncation of configure arguments in '-V' output.
+
+  [AS] Added USB IDs of WD Passport USB Portable
+
+  [CF] Linux: Fix segfault in 3ware interface (ticket #22).
+
+  [MS] knowndrives.cpp updates:
+       - Hitachi Deskstar 7K2000
+       - Seagate Momentus 7200 FDE.2 series
+
+  [CF] Add USB ID of WD My Passport 070A.
+       knowndrives.cpp update:
+       - WD My Passport hard drive (USB interface)
+
+  [CF] smartd: Write 'worst' attribute value to '.state' file also.
+       This allows to use state persistence with 'raw64' attributes.
+
+  [CF] Rework ATA SMART attribute check in smartctl and smartd.
+       smartd: Ignore normalized attribute value and threshold
+       if 'raw64' or 'hex64' format is selected.
+
+  [CF] Add USB IDs of Iomega LPHD080-0, 2 Genesys Logic bridges and
+       Initio 316000.
+
+  [MS] knowndrives.cpp update: Hitachi Travelstar 5K320 series
+
+  [CF] smartctl: Ignore normalized attribute value and threshold
+       if 'raw64' or 'hex64' format is selected.
+
+  [CF] knowndrives.cpp updates:
+       - add OCZ-Vertex raw64 attributes
+       - add OCZ-Agility
+       Thanks to Marcin Marszalek for the patch.
+
+  [CF] Add '-v ID,hex*' print formats. Fix '-v N,FORMAT,NAME' parsing.
+
+  [CF] Add '-v ID,raw64[,...]' print format based on a patch provided
+       by Marcin Marszalek.
+
+  [CF] Add '-v ID,RAW_FORMAT[,ATTR_NAME]' option. This allows to add new
+       attributes without the need to enhance the '-v' option.
+       Rework attribute name and raw value formatting.
+
+  [CF] Fix auto_ptr initialization in linux_scsi_device::autodetect_open().
+
+  [CF] Remove duplicate function smart_device_list::add().
+       Replace calls with push_back().
+
+  [MS] attribute update:
+       trim attribute names to 23 chars
+
+  [CF] Add smart pointer class template to manage device object pointers.
+       Remove related 'delete' calls and 'try/catch' blocks.
+
+  [CF] do_release: Replace generation of '*.asc' by '*.md5' and '*.sha1'.
+
+  [MS] attribute updates:
+       - change attributes 202,204,205 to the meanings as found in wdidle3.exe
+         retain old entries as comments (possible Fujitsu use)
+       - add attribute 240 as found in Fujitsu MHY2xxxBH
+
+  [MS] attributes updates:
+       - attributes 225, 232 and 233 for Intel X25-E SSD
+       - non-conflicting attributes extracted from wdidle3.exe
+         (thanks to Franc Zabkar and Dan Lukes)
+
+  [CF] Update Windows and ./configure info in INSTALL file.
+
+  [CF] Update 'do_release' script for SVN.
+
+  [MS] knowndrives.cpp updates:
+       - Western Digital MyPassport Essential hard drive (USB interface)
+       - Seagate Momentus 7200.4 series
+       - Western Digital Raptor X
+       - Intel X25-E SSD
+
+  [CF] knowndrives.cpp updates:
+       - New Seagate 7200.11 firmware version
+       - Update IBM link
+
+  [CF] smartctl: Use printf() instead of pout() for exception error
+       messages to avoid access to bogus 'con->dont_print'.
+
+  [CF] smartd: Add missing help texts for '-A', '-B' and '-s'.
+
+  [CF] Add missing check for log page 0x11 support to smartctl
+       '-l sataphy' option.
+
+  [CF] Add USB ID of Freecom Hard Drive XS.
+
+  [AS] Linux: Autodetect DELL PERC and MegaRAID controllers.
+       Hiding debug messages coming from megaraid code.
+
+  [AS] Linux: Fixed SATA drives support on megaraid device (see ticket #15).
+
+  [AS] FreeBSD: Removed all old detection code, moving everything to
+       the objects. Now we are using CAM/ATA enumerators to guess device
+       type.
+
+  [AS] FreeBSD: Added autodetection for the ada disks (untested).
+       Code for USB device detection refactored.
+
+  [AS] FreeBSD: cam_get_umassno rewritten using XPT_PATH_INQ
+
+  [AS] FreeBSD: do not open/close cam device on every request for SCSI
+       disks. Use com->camdev both for SCSI and ATAPICAM.
+
+  [AS] FreeBSD: added support for the ada disks, based on agapon patch
+
+  [CF] Add names for attributes 184 and 188, see ticket #17.
+
+  [CF] configure.in: Change configure date syntax.
+       Add message to '-mno-cygwin' option check.
+
+  [GK] Add names for some attributes used in MLC flash drives:
+       175, 176, 177, 181, 182
+
+  [CF] Windows: Check support of gcc '-mno-cygwin' option in configure.
+       This option has been removed in Cygwin gcc 4.x.  Update INSTALL
+       instructions accordingly.
+
+  [CF] Increase SCSI_TIMEOUT_DEFAULT from 6 to 20 seconds to avoid
+       timeouts when a disk spins up from standby mode.
+
+  [CF] Add USB ID of AcomData 504 (OnSpec USB bridge).
+
+  [AS] Correcting manual pages (FreeBSD related)
+
+  [AS] FreeBSD: fix FTBFS on GNU/kFreeBSD (reported by derevko).
+
+  [AS] FreeBSD: Add USB autodetection to smartd DEVICESCAN directive.
+
+  [CF] Add USB ID of Myson Century CS8818, add some comments.
+
+  [CF] Return info strings from 'smart_interface::get_*()' functions as
+       'std::string' instead of 'const char *'. Static buffers are no
+       longer needed.
+
+  [SZ] FreeBSD: Fix highpoint type detection and ioctl failed for parameter
+       error.
+
+  [CF] Linux: Add USB autodetection to smartd DEVICESCAN directive.
+
+  [CF] Add USB IDs of Maxtor Basics Desktop and ISD-300A1.
+
+  [AS] Use malloc() to ensure that the read buffer lands on a single
+       page.  This avoids some bugs seen on LSI controlers under
+       FreeBSD.
+
+  [CF] Add missing help text for '-d usb*' options.
+
+  [CF] Linux: Dereference '/dev/disk/by-*/*' symlink before device type
+       autodetection.
+
+  [AS] FreeBSD: Support SATA disks attached to a SAS controller (based on
+       patch from freebsd ports tree).
+
+  [AS] FreeBSD: Added FreeBSD 8 libusb2 device autodetecion, new
+       configure check for -lusb.
+
+  [AS] FreeBSD: Added USB device autodetection and fixed -d switch behavior.
+
+  [AS] FreeBSD: Migrate os_freebsd.cpp to new interface.
+
+  [CF] Fix max number of 3ware devices, 128 devices are supported again.
+       Regression was introduced during migration to new interface.
+       Thanks to Michael Holweg for the problem report.
+
+  [CF] Windows installer: Add 'DisplayVersion' to uninstall registry key.
+
+  [MS] knowndrives.cpp updates:
+       - Marvell SSD SD88SA024BA0
+       - Fujitsu MHZ2 BH series
+       - Fujitsu MHZ2 BJ series
+       - Seagate Maxtor DiamondMax 23
+       - WD Caviar Green: Add some 32MB cache variants
+       - relax OCZ-Vertex pattern
+
+  [CF] Add USB ID of Verbatim FW/USB160.
+
+  [CF] Fix data type bug in checksum test for multi sector logs.
+
+  [CF] Add USB ID of Seagate FreeAgent Go.
+
+  [MS] Add experimental feature to log attribute values at each check 
+       cycle (ATA only), activated with the smartd option 
+       "-A PREFIX" / "--attributelog=PREFIX".
+       Introduce configure options "--enable-attributelog" and
+       "--with-attributelog=PREFIX" to enable feature by default.
+
+  [DG] [SAT] Heads up about a non backwardly compatible change
+       introduced in draft SAT-2 (sat2r8b.pdf) that will break our
+       existing SAT processing code. Action needed if change stands.
+
+  [MS] smartd.cpp: Adjust umask
+
+  [CF] Makefile.am: Remove 'uninstall-docsDATA' target to fix
+       'make distcheck' with automake 1.11. The 'make uninstall'
+       of examplescripts fails if docdir does no longer exist.
+
+  [CF] Remove 'scsiata.h'. The 'scsiata.cpp' module now implements
+       parts of 'dev_interface.h'.
+
+  [CF] smartctl: Don't report an attribute as failed if threshold is 0.
+
+  [CF] Print only one warning on checksum errors in multi sector log.
+       Remove casts from calls of checksum().
+
+  [DG] minor changes to SCSI background scan strings
+
+  [MS] knowndrives.cpp updates:
+       - Fujitsu MHW2 BJ series
+       - WD Caviar Black family
+
+  [MS] Makefile.am: Make creation of svnversion.h independent of
+       locale settings
+
+  [CF] Require to specify PORT parameter of '-d usbjmicron' if two disks
+       are connected.
+
+  [CF] smartctl: Limit default number of printed entries for
+       '-l xerror' to 8, for '-l xselftest' to 25.
+
+  [CF] smartctl: Fix number of entries in '-l xselftest' output.
+
+  [CF] Add USB IDs of a SunplusIT bridge, three WD drives, and an
+       unsupported Iomega drive.
+
+  [CF] Makefile.am: Use 'svnversion' instead of 'svn info' to get
+       the revision number. This also checks for mixed and modified
+       working copies.
+
+  [CF] Remove CVS Id strings from '-V, --version' output.
+
+  [CF] Update CONTRIBUTORS section on man pages.
+
+  [CF] Makefile.am: 'make maintainer-clean' now removes also files
+       generated by './autogen.sh'.
+
+  [CF] Invalidate 'do_release' script, it needs some rework for SVN.
+
+  [CF] Update documentation files for SVN.
+
+  [CF] Rename trunk/sm5 to trunk/smartmontools.
+
+  [CF] Print SVN revision number instead of time in version info line.
+       Get SVN revision number from svn (if available) or guess from
+       Id strings. Rename generated file to svnversion.h.
+
+  [CF] Makefile.am: Modify generation of cvsversion.h for SVN.
+
+  [GP] Convert CVS repository to SVN.
+
+  [CF] smartd: Fix size of monitor flag array from previous commit.
+
+  [CF] Makefile.am: Add missing 'megaraid.h'.
+
+  [CF] smartd: Add '!' flag to '-r' and '-R' directives. If specified,
+       message is logged as LOG_CRIT and warning mail is sent if
+       attribute normalized or raw value changes.
+
+  [CF] Replace global 'con->...' variables used for selective self-tests
+       by local variables.
+
+  [GK] Add names for some attributes used in Samsung MLC drives:
+       178-180 & 183
+
+  [CF] smartctl: Add option '-x, --xall' to print all info including
+       extended SMART logs and non-SMART info.
+
+  [CF] smartctl: Add '-l xerror,error' and '-l xselftest,selftest' to print
+       the old logs if the extended logs are not supported.
+
+  [MS] knowndrives.cpp updates:
+       - Western Digital AV-GP series
+       - Transcend Solid-State Drive and Transcend Solid-State Drive V series
+       - Seagate Momentus 5400.5 series
+
+  [CF] Disable 48-bit ATA commands for JMicron USB bridges by default
+       because these commands do not work with all devices.
+       Add '-d usbjmicron,x' to enable 48-bit commands.
+       Thanks to Alexander Shaduri for the problem report.
+
+  [CF] smartd: Don't ignore the '-n' directive when a self-test is
+       scheduled. Start the self-test later when the disk is active
+       again.
+
+  [DG] SCSI (SAS): implement '-l sasphy,reset' (reset part was stub
+       prior to this)
+
+  [DG] add 'ATA, SCSI command sets and SAT' section to smartctl.8 .
+       [SCSI] add 'number of background medium scans' field
+
+  [DG] SCSI (SAS): add '-l sasphy' and '-l sasphy,reset' into smartctl
+       to output SAS device phy information (from the Protocol specific
+       log page)
+
+  [CF] autogen.sh: Remove 'CYGWIN=check_case:strict', this does no
+       longer work on Cygwin 1.7.  Print warning if Automake version
+       cannot handle case insensitive filesystems.
+
+  [CF] Remove '#define TRUE/FALSE', use 'bool' and 'true/false'.
+
+  [CF] Add 'options' parameter to SCSI printing routine. Move global
+       'con->...' smartctl variables to 'options' parameters of
+       printing routines.
+
+  [CF] Windows: Remove outdated entry about undocumented system calls
+       from WARNINGS file.
+
+  [CF] Print General Purpose Logs even if GPL feature bit is missing.
+       Needed for some older disks which implement READ LOG EXT but
+       do not report the GPL feature set.
+       Change order of the extended log outputs ('-l xerror',
+       '-l xselftest', '-l sataphy'). Extended logs are now printed
+       before their old versions.
+
+  [CF] autogen.sh: automake 1.10.2 and 1.11 are OK.
+
+  [CF] Fix syntax error in prototype of 'safe_snprintf()'.
+       Thanks to Alexander Shaduri for bug report and patch.
+
+  [DG] SCSI: Fetch load-unload cycle counts.
+
+  [CF] Windows: Add Win-7 and Win2008 to get_os_version_str().
+
+  [CF] smartd: Fix '-M test' directive in conjunction with '-s' option.
+       Thanks to Matthias Becher for the problem report.
+
+  [MS] knowndrives.cpp updates:
+       - Add Seagate Barracuda 7200.12 series
+       - Add Seagate Momentus 5400.4 series
+       - Add Hitachi Deskstar 7K1000.B series
+       - Add Transcend SSD TS32GSSD25-M
+       - Add OCZ Vertex 1199
+
+  [CF] knowndrives.cpp updates:
+       Add Samsung S250 series.
+       Add '-v 198,increasing' to Samsung P80.
+       Replace '#if/#endif' by comment to fix configure option
+       '--enable-drivedb'.
+
+  [CF] knowndrives.cpp update:
+       Add Seagate 7200.11 with 'CC' firmware which is unaffected
+       by the bug. Thanks to Bas Mevissen for the patch.
+
+  [CF] Replace global 'con->...' variables used for drive presets
+       by local variables.
+
+  [CF] Simplify '-v' vendor attribute option parsing.
+       Add '-v 197,increasing' and '-v 198,increasing' options
+       to specifiy that an uncorrectable count is never reset.
+       This modifies the printed attribute names and smartd's
+       default setting of '-C' and '-U' directives.
+       Both '-v' options can also be preset in the drive database.
+
+  [CF] Add '+' modifier to smartd '-C' and '-U' directives.
+       If specified, a warning is only printed if the raw value
+       increases.
+
+  [CF] Add smartctl option '-l xselftest[,NUM]' to print
+       ATA SMART Extended Self-test Log (GP Log 0x07).
+
+  [CF] Add experimental option '-d usbsunplus' for drives behind
+       SunplusIT USB bridges. Tested on WinXP with SPIF215(?) in
+       TrekStor DataStation maxi m.u.. Many thanks to SunplusIT
+       tech support for providing the required information.
+
+  [CF] Windows: Provide a non-console version of smartctl.exe
+       as smartctl-nc.exe. This prevents that a new console is
+       opened when smartctl is run from a GUI program with
+       stdio redirected.
+       Used by GSmartControl (http://gsmartcontrol.berlios.de/).
+
+  [CF] Remove support for platforms without getopt_long() in
+       smartctl.cpp and smartd.cpp. If getopt_long() is missing,
+       ./configure aborts with an explanatory message.
+       For now, short option help texts are only removed from
+       os_linux.cpp and os_win32.cpp. HAVE_GETOPT_LONG is still
+       defined in config.h.
+
+  [CF] Add smartctl '-d test' option to print the result of the
+       device type detection.
+
+  [CF] Enhance USB device type autodetection, use bcdDevice if known.
+       Add Cypress CY7C68300B/C (AT2LP) to the table.
+
+  [CF] Linux: Add experimental USB device type autodetection.
+       Uses USB ID info found through symlink "/sys/block/sdX/device".
+
+  [CF] Windows: Add experimental USB device type autodetection.
+       Uses WMI command line tool 'wmic' to query USB ID.
+
+  [CF] Add function smart_interface::get_usb_dev_type_by_id() to map
+       USB vendor:product IDs to '-d type' names. Can be used by
+       platform dependent layer to autodetect USB devices if ID of
+       USB bridge is known.
+
+  [CF] smartd: Log changes of self-test execution status if
+       '-l selftest'is specified.
+
+  [CF] knowndrives.cpp update:
+       Samsung SpinPoint F1 RE series
+
+  [MS] knowndrives.cpp update:
+       Seagate Momentus 5400.6 series
+
+  [CF] Add forgotten SCSI sense checks to class usbjmicron_device.
+
+  [CF] Add new SMART STATUS check command for JMicron USB bridges.
+       Should support also older chip versions and prevents a race
+       condition.
+
+  [CF] Windows: Fix win_scsi_device::scsi_pass_through() for single byte
+       data transfers. Required for JMicron SMART STATUS check.
+
+  [MS] knowndrives.cpp update:
+       Add Hitachi Travelstar C4K60 family (1.8" slim drives)
+
+  [MS] Workaround for huge raw values of attribute 9, needed
+       for Hitachi Travelstar C4K60. For the Power_On_Minutes case,
+       clip the display to 4 bytes and show the remaining part,
+       if existent, in parens.
+
+  [CF] Add experimental option '-d usbjmicron[,PORT]' for drives
+       behind JMicron USB bridges. Tested on WinXP with JM20336 in
+       AixCase AIX-ESU35CD. Many thanks to JMicron tech support
+       for providing the required information.
+
+  [MS] knowndrives.cpp update:
+       Add WD Caviar Green 8MB and 32MB cache variants, stretch to 2TB.
+  [CF] knowndrives.cpp updates: Add more entries for Samsung P80 disks
+       with old and unknown firmware. Remove old entries which would
+       match any new Samsung model reusing old firmware version number.
+
+  [CF] Windows: Add a workaround for missing multi-sector support
+       for ATA READ LOG EXT command.
+
+  [CF] Fix Extended Comprehensive Error Log index base.
+       Add workaround for Samsung disks using reserved byte as index.
+
+  [CF] knowndrives.cpp updates: Update bug warnings for
+       Seagate 7200.11, ES.2 and DiamondMax 22. Add new entries
+       for fixed firmware versions.
+
+  [CF] Add smartctl option '-l xerror[,NUM]' to print
+       ATA SMART Extended Comprehensive Error Log (GP Log 0x03).
+
+  [MS] knowndrives.cpp update:
+       Added remaining WD Scorpio Blue SATA II drives
+
+  [CF] Minor fix to remove ID 0 from 'smartctl -l sataphy ...' output.
+
+  [CF] knowndrives.cpp updates: Add warnings about possible firmware
+       bugs to Seagate 7200.11, ES.2 and DiamondMax 22 entries.
+
+  [CF] knowndrives.cpp updates: Add Samsung SpinPoint F1 series.
+
+  [CF] Windows: Fix return value of scsi_pass_through(). Regression
+       was introduced during migration to new interface. SAT over USB
+       now works on XP (both '-d sat,12' and '-d sat,16').
+
+  [MS] knowndrives.cpp updates:
+       - Added Western Digital RE2-GP family
+       - Added Hitachi Travelstar E5K160 family
+       - Allow uppercase variants of Hitachi 5K160 drives
+
+  [CF] Fix smartctl crash on '-l directory,[gs]'. Allow to override
+       missing GPL feature bit or missing log dir entry with
+       '-T permissive' option.
+
+  [SZ] os_freebsd.cpp, os_freebsd.h updates:
+       Support HighPoint RocketRAID controller under FreeBSD
+
+  [MS] knowndrives.cpp updates:
+       - Added Western Digital RE3 32MB cache variants
+       - Added WD Caviar Green 32MB cache variant (WD10EADS)
+       - Added WD Scorpio Black family
+
+  [DG] Accept half healthy (and half unhealthy) indication from the
+       SMART RETURN STATUS. This makes allowance for SAT implementations
+       (e.g. via USB) that truncate the SCSI sense buffer to 18 bytes.
+       This truncation causes the SMART RETURN STATUS indication to be
+       half health or unhealthy. If the half indication is used, then
+       warn if '-r ioctl' is given.
+
+  [MS] knowndrives.cpp updates:
+       - Added Apple SSD
+       - Added Seagate U8 family
+
+  [DL] os_freebsd.cpp:
+       Added support for CHECK_POWER_MODE and WRITE_LOG commands
+
+  [MS] knowndrives.cpp update:
+       There seem to exist WD Raptors with SATA II interface, add them.
+
+  [MS] knowndrives.cpp updates:
+       - Added remaining Seagate Barracuda 7200.11 drives
+       - Added HP 1TB SATA disk
+
+  [MS] knowndrives.cpp updates:
+       - Added Maxtor 92040U6 (DiamondMax Plus 6800)
+       - Added Seagate Maxtor DiamondMax 21 500GB version
+       - Added QUANTUM FIREBALLlct15 22
+       - Added QUANTUM FIREBALL CR6.4A
+       - Added QUANTUM FIREBALLP LM20.4
+       - Added SUN branded Toshiba MK4019GAX
+       - Added TOSHIBA MK1016GAP and relatives: MK1[05]1[67]GAP
+       - Added Western Digital WD800AB and WD2500AB
+       - Some Hitachi 7K160 drives have garbage at end of name: permit it
+
+  [CF] Add smartd '-n powermode,N' directive parameter to limit the
+       number of skipped checks. Thanks to Michal Hlavinka for the patch.
+
+  [MS] knowndrives.cpp updates:
+       - Added Hitachi Endurastar J4K30/N4K30
+       - Added Hitachi Travelstar 4K120 series
+       - Some Hitachi 7K80 drives have garbage at end of name: permit it
+       - IBM Travelstar 6GN series
+
+  [MS] knowndrives.cpp updates:
+       - Added Quantum Fireball ST4300A
+       - Added Asus-Phison SSD (solid state disk)
+       - Added Seagate DB35.3 Series
+       - Added remaining disks of the Seagate SV35.2 Series
+
+  [MS] Fix trivial compile error with "-pedantic"
+
+  [MS] Workaround for huge raw values of Reallocated_Sector_Ct and
+       Reallocated_Event_Ct for newer Fujitsu disks (only the lower
+       16 bits seem to be meaningful). Clip the display to 16 bits
+       and show the remaining part, if existent, in parens. Patch by [CF].
+
+  [CF] smartd DEVICESCAN: Fix autodetection of SAT devices.
+       Thanks to Stanislav Brabec for bug report and testing.
+
+  [MS] knowndrives.cpp update:
+       Convert file to full string regex: remove "^$" from pattern
+
+  [MS] knowndrives.cpp updates:
+       - Added Seagate Momentus 5400 PSD series (hybrid drives)
+       - Added Seagate Momentus 7200.3 series
+       - Added Hitachi Deskstar 7K250 (SUN branded)
+       - There are Hitachi Travelstar 5K250 drives with capital "HITACHI"
+       - Correct regex for Maxtor VL 30 drives
+
+  [CF] Add configure options '--enable-savestates' and
+       '--with-savestates=PREFIX' to enable smartd persistence
+       ('-s' option) by default.
+
+  [CF] smartd: Add '-s ([cnr]/../.././..)' directive to run scheduled
+       selective self-tests. Useful to perform full tests of large disks
+       not running 24x7.
+
+  [CF] Allow to read local drive database entries from optional file
+       '${sysconfdir}/smart_drivedb.h'.
+       Add configure options '--enable-drivedb' and '--with-drivedbdir=DIR'.
+       If specified, drive database is read from '${drivedbdir}/drivedb.h'.
+       (default '${prefix}/share/smartmontools/drivedb.h'). This file
+       is build from knowndrives.cpp.
+
+  [MS] knowndrives.cpp updates:
+       - Added 640GB variants of Western Digital AAKS and AACS drives
+       - Added Western Digital AV ATA family
+       - Added 160GB variant of Hitachi P7K500
+       - Added 500GB variant of Hitachi 7K1000
+       - Some cleanup for Quantum disks
+       - Added Seagate Maxtor DiamondMax 22 family
+
+  [CF] Use full string match for regexp in drive database.
+
+  [CF] Add option '-d sat+TYPE' to use SAT with controllers which
+       require option '-d TYPE'. Should work with '-d sat+megaraid,N'.
+       As a side effect, '-d usbcypress+TYPE' is also supported.
+
+  [CF] Add parser to read drive database from a file. Add '-B' option
+       to smartctl and smartd to specify database file name. File syntax
+       is identical to the C/C++ syntax used to inialize the internal
+       database array.
+
+  [CF] New syntax for drive database: Specify presets by strings
+       with '-v' and '-F' options. Use empty strings instead of NULL.
+
+  [JPH] Added Linux support for viewing disks behind MegaRAID
+       controllers
+
+  [CF] smartd: Improve min/max temperature recording in conjunction
+       with '-s' option.
+
+  [CF] Add a wrapper class for FILE *.
+
+  [CF] smartd: Add experimental support for state persistence (ATA only).
+       Add option '-s' to specify path prefix for state files.
+       Rework scheduled self-test detection to support persistence.
+       If any test schedules are within downtime, the highest priority
+       test is run after next startup.
+
+  [CF] Remove casts from 'format_ata_string()' calls.
+
+  [CF] Minor changes to fix errors and warnings from Cygwin gcc 4.3.0.
+
+  [CF] smartd: Remove SCSITIMEOUT code. According to smartd.h 1.54 CVS log
+       from 2003-10-27, it did never work.
+
+  [CF] Remove dependencies ataprint.cpp and scsiprint.cpp from smartd.
+       Move common ATA functions from ataprint.cpp to atacmds.cpp.
+       Module scsiprint.cpp was apparently never used in smartd.
+
+  [CF] Move smartd local declarations from smartd.h and utility.h to
+       smartd.cpp. Remove smartd.h.
+
+  [CF] Fixed extra '\n' in "Offline data collection status" output.
+       Thanks to Alexander Shaduri for the patch.
+
+  [CF] smartd: Separate device configuration data from device state data.
+       Use references instead of pointers for configuration and state data.
+
+  [CF] Add const-correctness and static to ATA support functions.
+
+  [CF] Add a wrapper class for regex.
+
+  [CF] Simplify 'create_vendor_attribute_arg_list()'.
+
+  [CF] smartd: Rework of main data structures. Remove explicit memory
+       allocations, use STL containers and structs with value semantics
+       instead. Remove old malloc/free based memory management helper
+       functions unless old interface is still in use.
+
+  [CF] Linux: Cleanup device scan, remove name list, create objects directly.
+
+  [CF] Linux: Cleanup smart_device::open(), type strings are no longer used.
+
+  [CF] Remove CONTROLLER_* defines and variables unless old interface
+       is still in use.
+
+  [CF] Linux: Migrate 3ware interface to 'ata_pass_through()'.
+       Multi-sector support is not complete yet. 48-bit commands
+       possibly work.
+       WARNING: Not tested, please review code before first test!
+
+  [CF] Linux: Migrate os_linux.cpp to new interface.
+
+  [CF] Add direct access to 16-bit registers in 'ata_in/out_regs_48bit'.
+
+  [CF] Add 'ata_cmd_is_ok()' parameter check,
+       remove 'ata_pass_through_28/48bit()' functions.
+
+  [CF] Add CVS date/time from cvsversion.h to man pages also.
+
+  [CF] Add configure option '--with-os-deps='os_module.o ...' to specify
+       alternate OS interface modules. Useful for testing during migration.
+
+  [CF] Remove declarations of 'optarg', 'optind', ..., include <unistd.h>
+       instead. This fixes 'auto-importing' linker warnings on Cygwin.
+
+  [CF] Add '-l sataphy[,reset]' to print SATA Phy Event Counters.
+
+  [CF] Add '-l gplog,ADDR[,FIRST[-LAST|+SIZE]]' and '-l smartlog,...'
+       to dump any log page accessible via GP or SMART read log commands.
+
+  [CF] Enhance '-l directory' to print both GP and SMART Log directories.
+       Add '-l directory[,gs]' modifiers to select GP or SMART log.
+       Enhance 'ata_cmd_in' parameter struct for 48-bit commands.
+
+  [CF] Windows: Add full ATA pass through support including 48-bit commands.
+
+  [CF] Windows: Migrate os_win32.cpp to new interface.
+
+  [CF] SAT: Add full ATA pass through support including 48-bit commands.
+
+  [MS] knowndrives.cpp update
+       - Added FUJITSU MHZ2250BS G2 and family
+
+  [MS] knowndrives.cpp updates
+       - Added Maxtor DiamondMax 60 94098H6
+       - Added Maxtor DiamondMax 1280 84000A6 and family
+       - Added Maxtor DiamondMax VL 30 31536H2 (ATA100) and family
+       - Some Seagate Barracuda 7200.9 have garbage at end of name: permit it
+       - Added Seagate Barracuda ATA ST320430A and family
+       - Regression from previous checkin: add WD RE2 WD...0ABYS again
+       - Added WD RE3 WD5002ABYS and family
+       - Added Quantum Fireball CR13.0A
+       - Added Hitachi Travelstar 5K250 HTS542525K9SA00 and family
+       - Added WD AC420400D and add whole range of AC.... which
+           have 5400rpm or higher (i.e. PIO-only drives omitted)
+
+  [MS] knowndrives.cpp updates
+       - WD: Separated entries for EIDE and SATA
+       - WD: Separated entries for Caviar SE, SE16, RE, RE2
+       - WD Named: WD Caviar AC series
+       - WD Renamed: WD Caviar RE/RE2 -> WD RE/RE2
+       - WD Renamed: WD Caviar SE/SE16 WD....AA[A-Z][A-Z] -> WD Caviar Blue
+       - WD Renamed: WD Scorpio WD....BEV[A-Z] -> WD Scorpio Blue
+       - Added WD Scorpio Blue WD3200BEVT
+       - Added WD RE2 WD5001ABYS and family
+       - Added WD Caviar Green WD5000AACS and family
+       - Added WD VelociRaptor WD3000GLFS and family
+       - Added Seagate Barracuda ES.2 ST31000340NS and family
+       - Added Samsung SP80A4H
+       - Added Maxtor DiamondMax 21 STM3160215AS and STM3320620AS
+       - Added Seagate Barracuda 7200.7 ST380819AS
+       - Added Maxtor DiamondMax 10 6B100P0
+       - Added Seagate SV35.2 Series
+       - Added Fujitsu MHY2120BH and family
+       - Added Fujitsu MHW2080BH PL (PL variant)
+       - Added Toshiba MK3252GSX and family
+
+  [BA] Fix smartctl bug: when running in silent mode '-q errorsonly'
+       do not print the Selective Self-test log.  Any errors will
+       ALREADY appear in the SMART Self-test log.
+
+  [CF] Add missing 'const' and other minor fixes to prevent gcc warnings.
+
+  [OB] Added information message about supported Areca firmware versions.
+       It's displayed in case the ATA device identification fails.
+
+  [CF] Add configuration file for Doxygen.
+
+  [CF] Add new object oriented interface to access ATA and SCSI devices.
+       smartctl and smartd are modified to use the new classes in
+       'dev_interface.{h,cpp}'. The template class in 'dev_tunnelled.h'
+       is used in 'scsiata.cpp'. The code in 'dev_ata_cmd_set.{h,cpp}'
+       supports migration from old function 'ata_command_interface()'.
+       All existing 'os_*.cpp' modules should still work without any changes.
+       The required adapter classes from 'dev_legacy.cpp' are automatically
+       added by configure if necessary.
+
+  [BA] Updated smartd and smartctl and smartd.conf man-page documentation
+       to reflect support for Areca SATA RAID controller cards.
+
+  [OB] Added support for Areca controllers to smartd. Extensive tests
+       as well as documentation are still pending however.
+
+  [OB] Implemented device locking for Areca controllers in smartctl
+
+  [BA] Fixed selective self-test code.  Data structure revision number
+       may be != 1 if no selective self-test has ever been run.  Host
+       MUST set this value (at least at the first selective self-test
+       instance).  Thanks to Curtis Stevens of WDC for clarification.
+
+  [MC] usbcypress autodetection
+
+  [BA] Starting to commit Areca code.  For now just smartctl.
+       More changes and documentation coming soon.
+       Need Areca firmware version 1.45 dated 10 June 2008 or later.
+       May need changes in opening /dev/sg and file locking.
+       Many thanks to Hank Wu!
+
+  [CF] smartd: Fix too small name buffer for 3ware with >100 devices.
+
+  [JH] now C++ Support for QNX Target
+       already tested for QNX 6.3.2 on x86 and armle target
+   
+  [CF] Allow to set BUILD_INFO from make command line.
+
+  [CF] Windows: Add MSVC8 support, remove MSVC6 project files.
+
+  [MC] Add usbcypress device support for smartd.
+
+  [CF] Add output of latest CVS date/time stamp to version info.
+       New file cvsversion.h is generated by Makefile.
+       Move formatting of version info to utility.cpp.
+
+  [AR] Fix bug in 3ware node creation where nodes would be created
+       then deleted, then recreated.
+
+  [BA] Add missing CCISS cvs version tags to '-V' printouts.
+
+  [TS] Linux: Ensure the 3ware device nodes are created with a correct
+       SELinux security context.
+
+  [AR] Add support for up to 128 devices on 3ware controllers.
+
+  [CF] C++: Added new main() with exception handlers, replaced
+       exit(x) with throw(x), removed global variable 'exitstatus'.
+       Necessary for future changes, because exit() does not call
+       any destructors.
+
+  [SS] FreeBSD: plug file descriptor leak in smartd (only happens with
+       CISS devices).  Reported by Vadim Ostranitsyn.
+
+  [SS] FreeBSD: allow smartctl to interact with SCSI /dev/pass devices,
+       thus enabling it to work with RAID controllers that expose disks
+       via these devices.  From scottl@ via FreeBSD ports.
+
+  [MC] Add usbcypress device support for smartctl.
+
+  [KS] INSTALL on Solaris: updated description to use C++ compiler.
+
+  [KS] configure.in on Solaris: added options for Sun's compiler to
+       suppress trivial warnings.
+
+  [KS] configure.in on Solaris: added direction to search suitable
+       libraries for getaddrinfo().
+
+  [TS] smartd on Linux: remove forgotten return from deviceopen();
+       SCSI device descriptors had the FD_CLOEXEC flag unset.
+
+  [CF] Added 'const' to avoid warning on depreciated string constant
+       to 'char *' conversion.
+
+  [CF] autogen.sh: automake 1.10.1 is OK. Updated message texts.
+
+  [BA] removed smartmontools.spec file (now in CVS Attic).  This
+       was not being used by RH or FC anyhow, and was out of
+       date and not maintained.
+
+  [BA] smartd on Linux: sets FD_CLOEXEC on the opened device file
+       descriptor.  The descriptor is otherwise leaked to other
+       applications (mail sender) which may be considered a security
+       risk and may result in AVC messages on SELinux-enabled systems.
+       Thanks to: Tomá Smetana" <tsmetana@redhat.com>.
+
+  [BA] smartd: when sending email, to gather information about the
+       host for the body of the email, eliminate gethostbyname()
+       in favor of the IPv6-friendly function getaddrinfo() if the
+       latter is available.  Info may be found here
+       http://udrepper.livejournal.com/16116.html
+       and here
+       http://people.redhat.com/drepper/userapi-ipv6.html
+       Thanks to: Tomá Smetana" <tsmetana@redhat.com>.
+
+       Smartmontools developers: please check that smartd still LINKS
+       properly on your systems.
+
+  [BA] Fix ugly syntax bug in os_freebsd.cpp.  How did this go
+       undetected for so long??
+
+SMARTMONTOOLS STABLE RELEASE 5.38 2008/03/10
+
+  [KS] Solaris/x86: modified configure.in for Sun's compiler.
+
+  [BA] smartd.initd.in addition from Erwan Velu <erwan@seanodes.com>
+
+  [BA] smartd fixes:
+
+       - On Linux, DEVICESCAN now automatically recognizes SATA devices
+         behind libata, and SATA devices behind the Marvell driver, and
+         treats them correctly.
+
+       - On Linux, a '-d sat' or '-d marvell' is automatically added
+         if libata or the marvell driver are recognized behind a SCSI
+         device type
+
+  [SS] (Maybe) fix attribute autosave in FreeBSD.
+
+  [SS] Major NetBSD-specific bugfixes:
+       - handle actual SCSI and ATA errors and not only ioctl() errors;
+       - set up I/O request properly for AUTO_OFFLINE and AUTOSAVE commands (inspired by
+         similar change in os_freebsd.cpp);
+       - handle AUTO_OFFLINE and AUTOSAVE like STATUS_CHECK (like os_linux.cpp does).
+
+  [GG] add kfreebsd gnu support to configure.in
+
+  [BA] Fix auto-offline support in FreeBSD.  Thanks to
+       Cyrus Rahman <crahman@gmail.com> for the patch, and
+       Eduard Martinescu for blessing it.
+
+  [DG] smartd re-opens "SCSI" devices as ATA devices if a SAT layer is
+       detected (smartd bug IMO). In Linux this upsets scsi generic
+       device nodes (e.g. /dev/sg0). Detect the re-open in os_linux.cpp
+       and set the O_RDWR flag (ATA uses the O_RDONLY flag).
+
+  [CF] Drive database: Added Fujitsu MHW2 BH, Maxtor DiamondMax 17, 20, 21,
+       Hitachi Travelstar 4K40, 5K120, 7K200, Deskstar 7K160, T7K500,
+       T7K1000, Toshiba 1.8", Seagate Momentus 5400.3, 5400.3 ED, 7200.2,
+       Barracuda 7200.11 and ES.
+       Updated Toshiba 2.5", Seagate Barracuda 7200.9 and 7200.10.
+       Added missing "(Hitachi )?" to Travelstar entries.
+
+  [CF] Drive database: Added several Western Digital Caviar and Scorpio
+       drives, added Caviar RE EIDE family.
+
+  [CF] Drive database: Added Samsung P80 series with *-25 firmware.
+
+  [CF] Replaced 'head [-n] -1' by 'sed 1...' in autogen.sh to avoid
+       portability issues.
+
+  [BA] Fixed autogen.sh script so that it uses 'grep -n 1' if 'grep -1'
+       fails.  Needed for Mac OS X 10.4. Uck.
+  [CF] Windows: Added IOCTL_STORAGE_PREDICT_FAILURE. This allows access
+       to ATA SMART status and data if other calls do not work.
+       Thanks to Jaroslaw Kowalski for pointing this out.
+       Added support to use this function without admin rights.
+
+  [CF] Added ATA-8 revision 4c message text.
+
+  [CF] Added compiler.h to cciss_ioctl.h header check to prevent
+       configure warning.
+
+  [SS] DragonFly support added (using os_freebsd code; untested).
+
+  [CF] smartctl: Fixed ATA identify byte swapping issue on big-endian
+       platforms. This regression was introduced by the change for
+       '-F swapid'. Thanks to Matthew Butch for bug report and testing.
+
+  [DG] SAT/SCSI: Improve SAT error processing code. Aborted commands from
+       ATA devices (typically because SMART was disabled) were not being
+       properly detected.
+
+  [GG] smartd: wait for the pid file to show up, return an error if it doesn't
+
+  [JH] fix bad return code (get STATUS) for QNX Part
+
+  [JH] initial porting to QNX Neutrino 6.3.2
+       need at this time a prerelease devb-eide driver and libcam.so.2
+       only tested for X86 Target, but devb-eide and lobcam.so.2 available for X86/ARM
+       the officional driver coming soon with the next QNX release
+       create two new source files os_qnxnto.[c..h]
+
+  [CF] smartd: Added option '-n, --no-fork' so that smartd works
+       better with modern init methods. Thanks to Enrico Scholz
+       for the patch from 2005-12-24.
+
+  [CF] Windows: Improved ATA/SCSI device type detection and
+       DEVICESCAN. This also fixes a regression in 3ware DEVICESCAN.
+
+  [CF] smartd: Don't start self tests in first pass to avoid
+       performance problems during boot.
+       https://bugzilla.novell.com/show_bug.cgi?id=192591
+
+  [CF] Fixed regression in SMART STATUS command on Win9x/ME.
+
+  [BA] Fixed 3ware issue with new controllers.  Documentation said
+       that one could address up to 24 disks on a single controller,
+       but in fact one was limited to 16 disks.  This is now fixed:
+       up to 32 disks can be addressed.  Thanks to Adam Radford.
+
+       NOTE1: I have patched the Linux and FreeBSD code but not
+       modified the Win32 code (it already supports up to 32 disks).
+
+       NOTE2: NOT TESTED ON LINUX.  Do not use this on a production box!
+       I will remove this NOTE2 as soon as some positive test
+       reports are recieved.
+
+       NOTE3: NOT TESTED ON FREEBSD. Do not use this on a production box!
+       I will remove this NOTE3 as soon as some positive test
+       reports are recieved.
+
+  [CF] Windows installer: Added explorer drive menu, CMD window,
+       UBCD4Win plugin, smartd service update and other minor
+       improvements.
+
+  [CF] Windows: Modified drive letter handling for explorer drive
+       context menu: try SCSI if type is unknown, allow 'X:\.' syntax.
+
+  [CF] Windows: Added automatic ATA/SCSI device type detection and
+       SCSI device scanning. The device names '/dev/sdX' and
+       '/dev/pd<n>' now work for both ATA and SCSI disks.
+
+  [CF] smartctl: Added ability to parse '-r ataioctl,2' output from
+       stdin ('-') and simulate the ATA commands for testing purposes.
+
+  [BA] SMART Attributes: added 187, 189, more accurate name for 190.
+
+  [CF] Windows: Added drive letters 'X:' as alternate disk device names.
+
+  [CF] smartctl: Added '-F swapid' to fix ATA identify string byte
+       ordering. Added '-q noserial' to suppress serial number output.
+
+  [CF] Windows: Added '/dev/n?st<n>' as alternate device names for SCSI
+       tapes. These names are also used by Cygwin's /dev emulation layer.
+       Thanks to Corinna Vinschen (Cygwin project lead) for pointing this
+       out. 
+
+  [CF] Windows: Added IOCTL_SCSI_MINIPORT_*SMART* for commands not handled
+       properly by SMART_IOCTL in disk class driver. This allows to use
+       READ_LOG, WRITE_LOG and ABORT_SELFTEST even if the driver does not
+       support ATA_PASS_THROUGH.
+
+  [CF] Added ATA-8 revision 4, fixed WRITE LOG '-r ioctl' output.
+
+  [BA] Updated smartctl and smartd so that they can be used with the latest
+       3ware controllers which have 24 ports.  Also updated docs.
+       Thanks to Tim Bell at CERN.
+
+  [GG] bit 4 in smartctl's return code might be set even when the dist check
+       didn't return "DISK OK"
+
+  [CF] Drive database: added '-F samsung3' for Samsung P80 firmware
+       BH100-35.
+
+  [SS] Applied patch from Dean Bennett to fix scheduled tests on 
+       Highpoint RAID controllers.
+
+  [BA] Added patch from Tejun Heo http://thread.gmane.org/gmane.linux.ide/13222/focus=13235
+       to fix broken auto-offline and auto-save via libata.  Very clean fix: does it
+       "the right way".  Thanks Tejun!
+
+  [CF] Added message text for ATA-7 self-test execution status 8
+       ("... handling damage").
+
+  [GG] cciss: support more than 16 disks (patch taken from
+       http://cciss.sourceforge.net/smartmontools_cciss_more_than_16_drives.patch
+       and adjusted for smartd)
+
+  [DG] Solaris: [SCSI] add USCSI_RQENABLE flag to uscsi pass-through so
+       sense buffer is made available. Expand reporting at this level.
+
+  [GK] Darwin: Improve handling of powered-down drives.
+
+  [SS] CCISS physical drive enumeration method changed (incompatibly).
+
+  [CF] Fixed smartd crash on missing '-s' directive argument.
+
+  [SS] Support CCISS on FreeBSD (kernel source is required until FreeBSD PR 109813
+       is fixed).
+
+  [DG] SCSI/TAPE: some IBM tape drives don't react properly to a LOG
+       SENSE with an allocation length of 4; work around for that case.
+
+  [CF] Applied Guido's patch to fix CCISS LUN array bounds check
+       (openSUSE bug #239956) and remove trailing spaces in
+       os_linux.cpp.
+
+  [CF] Fixed 64-bit compilation issue in SCT status struct.
+
+  [DG] SAT/SCSI: make real SCSI disks visible to DEVICESCAN in
+       smartd again.
+
+  [CF] Fixed check of SCT temperature table size.
+
+  [CF] Added ATA-8 draft revisions, added SCT status format 3.
+
+  [CF] Drive database: added Samsung T166 series.
+
+  [CF] ATA: Added ',p' option for '-t scttempint,N' to make
+       setting persistent.
+
+  [CF] ATA: Added '-t scttempint,N' option to set SCT temperature
+       logging interval.
+
+  [CF] ATA: Added '-l scttemp[sts,hist]' options to print disk
+       temperature information and history table provided by
+       SMART Command Transport (SCT) Feature Set.
+
+  [CF] ATA: Added '-t selective,{redo,next,cont}' commands to
+       perform tests based on the last ranges still stored on
+       disk. Added 'N+SIZE' and 'N-max' format for LBA range
+       specification.
+
+  [CF] Added Min/Max Temperature format used in attribute 190 of
+       recent Maxtor disks (DiamondMax 20).
+
+  [CF] Linux: Added check for <linux/cciss_ioctl.h> to allow build
+       (without CCISS support) also when this file is missing.
+
+  [CF] Added -F samsung3 option to correct firmware bug reporting
+       completed self-tests as still in progress. Thanks to Manfred
+       Schwarb for the patch.
+
+  [CF] Added missing const specifiers (undetected by gcc 3.4 and 4.X)
+       to fix compilation with gcc 2.X.
+
+  [CF] Linux: compile fix for SuSE, config.h must be included first.
+
+smartmontools 5.37 Experimental Release
+
+  [CF] Windows: Added alternate method for (limited) monitoring of
+       3ware controllers by parsing the output of CLI or 3DM.
+       Either "tw_cli" can be run internally ("/dev/tw_cli/cx/py"),
+       or data can be read from standard input ("/dev/tw_cli/stdin")
+       or clipboard ("/dev/tw_cli/clip").
+
+  [DG] Remove linux specific libata detect code; rely on general SAT
+       code. smartd should now generate a sensible log message for
+       ATA devices behind a SAT layer on all architectures.
+
+  [BA] Increased max line length MAXLINELEN for /etc/smartd.conf from
+       128 to 256 characters to handle long strings in
+       /dev/disk/by-id.  Thanks to Martin Krafft.
+
+  [PW] Drive database: added missing drives from Seagate Momentus 5400.2
+       family
+
+  [BA] Finished Christian's fix (next item below) by removing
+       LINUX_86_64 hack from configure.in.
+
+  [CF] Fixed inclusion of PRI?64 macros from inttypes.h.
+
+  [CF] Windows: Added WRITE LOG to support selective self tests.
+
+  [CF] Fix selective self test log revision number if '-T permissive'
+       is specified (Tested with Samsung HD401LJ).
+
+  [CF] Windows: Fixed int64 printf format for MinGW runtime.
+
+  [PW] Drive database: added Seagate Barracuda 7200.10 family, Seagate
+       Momentus 42 family, Maxtor DiamondMax 60 ATA 66 family, Maxtor
+       DiamondMax 60 ATA 100 family, and Western Digital Caviar Serial
+       ATA family
+
+  [PW] Drive database: added missing drives from Seagate Barracuda
+       7200.9 family, Seagate Barracuda 7200.7 family, Seagate Momentus
+       7200.1 family, Toshiba 2.5" HDD family (80 GB and above), Western
+       Digital Caviar RE Serial ATA family, Hitachi Deskstar 7K80 family,
+       and Maxtor DiamondMax 4320 Ultra ATA family
+
+  [BA] Linux: compile fix for SuSE.  Check for existence
+       of linux/compiler.h and include in os_linux.h if
+       present.  Thanks to SB.
+
+  [BA] smartd: DEVICESCAN will now pick up SATA/SAT devices
+       attached to a SCSI device tree via SAT translation.
+       Note: this is a bit of a hack.  I will document it once
+       I know if this needs to be Linux only or can have more
+       general application.
+
+  [BA] Added a couple SATA commands to the tables -- thanks DG!
+       Phil -- how about going through and systematically adding
+       these new commands to atacmdnames.cpp?
+
+  [BA] Linux s86_64: get rid of some compiler warnings on
+       x86_64 Linux systems.
+
+  [CF] Windows: Added missing support for READ_LOG, ABORT_SELFTEST
+       and CHECK_POWER_STATE for 3ware 9000 controllers. Thanks to
+       Greg de Valois for implementing this new ioctl in the driver.
+
+  [PW] Drive database: added Seagate NL35 SATA family.  Thanks to Kai
+       Harrekilde-Petersen for providing a patch.
+
+  [DG] [SCSI, Windows] add SPT interface for NT and later. New device
+       names are "pd<n>", "sd<l>" and "tape<n>".
+
+  [PW] Drive database: added Western Digital Scorpio family, Fujitsu MHV
+       family, Maxtor MaXLine Pro 500 family, and Maxtor DiamondMax 11
+       family
+
+  [PW] Drive database: added missing drives from Toshiba 2.5" HDD
+       (30-60 GB) family, Maxtor DiamondMax 10 family, Seagate Barracuda
+       7200.8 family, Fujitsu MHT family, and Maxtor DiamondMax Plus 8
+       family
+
+  [SB] Added examplescripts/Example4 using powersave-notify.
+
+  [SB] More temperature monitoring examples in smartd.conf with DEVICESCAN.
+
+  [SB] Minor improvements of SuSE part of init script.
+
+  [CF] Drive database: added Samsung P80 series, P120 series, SP8004H
+       and T series.
+
+  [GG] Add CCISS (Compaq Smart Array Controller) support with contributions
+       from Praveen Chidambaram, Douglas Gilbert, Guido Guenther and Frédéric
+       BOITEUX
+
+  [PW] Drive database: added Hitachi Deskstar T7K250 and Hitachi
+       Deskstar 7K500 series.  Thanks to L. J. Wu for providing a
+       patch
+
+  [PW] Drive database: added Maxtor MaXLine III family, Seagate U7
+       family, Seagate ST34321A, FUJITSU MHM2060AT, FUJITSU MHT2040AS,
+       Western Digital Caviar SE16 family, IBM Travelstar 4GT family,
+       QUANTUM FIREBALLP KA9.1, QUANTUM FIREBALL SE4.3A, TOSHIBA
+       MK1032GAX, TOSHIBA MK4026GAX
+
+  [PW] Drive database: added missing drives from Western Digital Caviar
+       SE (Serial ATA) and WD Raptor families
+
+  [CF] Windows: Added support for 3ware 9000 controllers using extended
+       SMART functionality in new 3ware driver. This includes DEVICESCAN
+       support for at most 2 controllers. Thanks to Greg de Valois from
+       AMCC/3ware for new driver features, development support and
+       hardware for testing.
+
+  [SZ] smartd: Support HighPoint RocketRAID controller under GNU/linux
+
+  [DG] [SCSI] First cut for '-l background' to show background scan
+       results log
+
+  [SZ] smartctl: Support HighPoint RocketRAID controller under GNU/linux
+
+  [KS] C++ compile fixes for Solaris with a few cleanups.
+
+  [BA] C++ compile fixes for Darwin (thanks to CF)
+
+  [CF] Removed old *.c files (now in CVS Attic).
+
+  [CF] Added changes for C++ to platform independent and Windows
+       related files.
+
+  [BA] Tagged last .c Version with PRE_MOVE_TO_CPP. Copied *.c,v
+       to *.cpp,v in CVS repository to preserve history of source
+       files. Removed sm5_Darwin repository.
+
+  [CF] smartctl: Added -n option to skip checks when disk is in
+       low-power mode.
+
+  [CF] Windows: Added alternate system call for power state check
+       because the PASS THROUGH calls may spin up the disk.
+
+  [CF] smartd: Modified power state logging to report state changes
+       instead of standby condition.
+
+  [CF] smartd: Ignore -n directive on scheduled self tests.
+
+  [DG] [SCSI] Make start stop cycle counter log page decoding
+       more robust
+
+  [DG] Modify smartctl (but not smartd) to detect probable ATA
+       devices behind a SAT layer. In the absence of an explicit
+       device type, change to device type 'sat'.
+
+  [DG] Add indication that controller (device) type has been
+       explicitly set. Preparation for automatic detection of
+       'sat' device type unless user specifies a device type.
+
+  [SS] NetBSD: Deliver strings from ata_identify_device properly 
+       on little- and big-endian platforms.
+
+  [BA] Added published ANSI ATA-7 spec to list of recognized ATA
+       versions.
+
+  [BA] Code janitor: added missing header strings for '-V' option.
+
+  [DG] [SATA] Extend 'sat' device type to allow either 12 or 16 byte
+       variant of the SAT ATA PASS THROUGH SCSI command. Syntax is
+       '-d sat,<n>' where <n> can be 0, 12 or 16 . The ',<n>' part
+       is optional. Currently defaults to 16 byte variant but that
+       could be made platform or even device dependent.
+
+  [DG] [SATA] Add new 'sat' device type for SATA disks behind a
+       SCSI to ATA Translation (SAT) Layer (SATL). Uses the ATA
+       PASS THROUGH (16) SCSI command thence the generic SCSI
+       passthrough for each platform.
+
+  [CF] Windows: Added script and make targets to create installer
+       with NSIS (http://nsis.sourceforge.net/)
+
+  [CF] Updated hostname and links for new SourceForge CVS service.
+
+  [CF] smartd: Added '-W' directive to track temperature changes
+       and warn if temperature limits are reached.
+
+  [CF] Windows: Added IOCTL_ATA_PASS_THROUGH (Win2003, XP SP2)
+       for commands unsupported by SMART_IOCTL. Added device
+       specific options to select subset and ordering of the ATA
+       IOCTLs actually used. These options are specified as
+       modifiers of the device name (/dev/hd[a-j]:[saic]+)
+
+  [CF] Windows: Added support for drives 4-7 (/dev/hd[e-h]) via
+       SMARTVSE.VXD on Win9x/ME. Thanks to Dariusz Rzonca for
+       patch and testing.
+
+  [DG] [SCSI/SATA linux] from lk 2.6.17 SATA disk identification in
+       libata will change. Expand LibAta detection to see old
+       identifier and new variant (VPD page 0x83).
+
+  [BA] Identified Attribute 190 for Western Digital disks.  This
+       stores temperature in Celsius, just like Attribute 194.
+       But it has a failure threshold set to correspond to the
+       maximum design operating temperature of the disk, which
+       is 55 Celsius on the WD800JD drives that I studied.
+       So if this Attribute has 'failed
+       in the past' this means that the maximum disk operating
+       temperature has been exceeded.
+
+  [GK] Darwin: Add support for AHCI drivers found in Intel-based Macs.
+
+smartmontools 5.36 Stable Release
+
+  [BA] Linux: smartd/smartctl issue syntax hints to user if 3ware
+       disk controller present with EITHER 3ware OR AMCC vendor
+       name, and user syntax incorrect.
+
+  [BA] Update copyright dates to 2006.
+
+  [DG] [SCSI] Loosen sanity check on Seagate/Hitachi factory information
+       log page so it is not skipped on recent Seagate SCSI disks.
+
+  [CF] Added command 'smartd -q showtests' to list test schedules.
+
+  [CF] Added command 'smartctl -P showall MODEL [FIRMWARE]' to list
+       database entries for specific drives and firmware.
+
+  [PW] Automatically set -v 9,minutes and -v 194,unknown for Maxtor
+       DiamondMax D540X-4G drives.
+
+  [DG] [SCSI] suppress various outputs when data fails sanity checks.
+       Correct 'last n error events' log page indexing.
+
+  [DG] [SCSI] changed smartctl exit status to reflect any problems in
+       the most recent 20 self test logs [Leandro Santi]
+
+  [DG] [SCSI] Fix process return value when scsiGetSmartData() fails
+       in smartctl [Leandro Santi]
+
+  [BA] Updated docs and error message to reflect Linux libata
+       support for smartmontools starting with the 2.6.15 kernel
+       series. Also init script support for the 'tinysofa' release.
+
+  [DG] [SCSI] Mask dpofua bit when changing mode pages. Fix failure
+       of 'smartctl -l error'.
+
+  [EM] Fixed a problem with FreeBSD and 3Ware 'twe' devices
+
+  [CF] Fixed a regexp in knowndrives table, added regexp syntax check
+       via 'smartctl -P showall'.
+
+  [CF] Cygwin & Windows: Fixed memory leak in function calling
+       IOCTL_IDE_PASS_THROUGH. Thanks to Fred Schmidt for the problem
+       report.
+
+  [CF] Cygwin: added cygrunsrv support and commands "install", "remove"
+       and "status" to smartd.initd.
+
+  [SS] Fix runtime problems on big-engian NetBSD platforms (patch provided
+       by Martin Husemann)
+
+  [CF] Cygwin smartd: Open smartd.conf in textmode to allow use of
+       Windows editors.
+
+  [CF] Cygwin smartd: Added option '--service' to allow smartd running
+       as windows service via cygrunsrv. Useful in conjunction with new
+       syslogd support added in Cygwin 1.5.15.
+
+  [CF] Windows: Added patch to avoid output of non-ascii timezone names.
+
+  [EM] Incorporate various patches to provide TWE support and support for 
+       multiple 3Ware cards, Power Check Support, and FreeBSD 6.x support.
+       Thanks to Rudolf Cejka, Frank Behrens, and Jung-uk Kim.
+
+  [DG] Silence gcc 4.0.1 compile warning concerning the difference in
+       "signedness" in pointer assignments. Changes to SCSI code
+       and os_linux.c .
+
+  [PW] Additions to knowndrives table: added missing drive from Quantum
+       Fireball Plus LM series, added QUANTUM BIGFOOT TS10.0A, added
+       ExcelStor J680 and J880, added Western Digital Caviar RE Serial ATA
+       series, added missing drives from Western Digital Caviar SE series,
+       added Seagate Momentus 4200.2 series, added missing drives from
+       Maxtor DiamondMax 10 series, added Fujitsu MHG and MHH series, and
+       added Hitachi Travelstar 5K100 series.
+
+  [PW] Additions to knowndrives table: added Fujitsu MHU2100AT, added
+       Fujitsu M1623TAU, added missing drives from Seagate Barracuda
+       7200.8 series, added Seagate Momentus 5400.2 series, and added
+       QUANTUM FIREBALL CR8.4A.
+
+  [PW] Additions to knowndrives table: added missing drive from Maxtor
+       MaxLine II series, added Maxtor DiamondMax 2880 Ultra ATA series,
+       added Maxtor DiamondMax 17 VL series, added Hitachi Deskstar 7K80
+       series, and added Hitachi Deskstar 7K400 series.
+
+  [CF] Windows: Fixed unsupported 'smartctl -X' on Win2000/XP by using
+       IOCTL_IDE_PASS_THROUGH instead.
+
+smartmontools 5.34 Stable Release [NOTE: never officially released]
+
+  [CF] Cygwin & Windows smartd: Increased SCSI DEVICESCAN range
+       from ASPI adapter 0-3 to 0-9. Added diagnostic messages.
+
+  [CF] Windows smartd: Added ability to run .bat files via '-M exec'
+       directive.
+
+  [CF] Cygwin smartd: Added FreeConsole() after fork() to avoid hang
+       of terminated shell console window.
+
+  [DG] [SCSI] Add code so 'smartctl -A' outputs the number of elements
+       in the grown defect list. When this number is increasing a
+       disk has problems. N.B. Similar logic should be added to smartd.
+
+  [CF] Windows smartd: Fixed event handling to allow start of another
+       smartd process when service is already running. Useful for testing
+       service configuration changes in debug mode.
+
+  [PW] Added following drives to knowndrives table: Western Digital Raptor
+       family, Seagate Barracuda 7200.8 family, Maxtor DiamondMax 2160
+       Ultra ATA and DiamondMax 10 families, Hitachi Travelstar E7K60
+       family, Seagate Medalist 17240, 13030, 10231, 8420, and 4310,
+       TOSHIBA MK4018GAP and MK6022GAX, ExcelStor Technology J360, and
+       Western Digital Caviar AC14300.
+
+  [PW] Added missing Fujitsu MHTxxxxAT and Seagate Barracuda 7200.7 drives
+       to knowndrives table.
+
+  [PW] Added QUANTUM FIREBALLP LM10.2 to knowndrives table.  Thanks to
+       Mike Fleetwood for submitting the patch.
+
+  [KS] Solaris/SPARC: fixed not to disable automatic offline test and
+       automatic save attributes incorrectly.  Thanks to Roy Badami.
+
+  [BA] Linux: smartd init script now recognizes 'trustix' distro.
+
+  [DG] [SCSI] Medium and hardware errors were slipping through
+       unreported. Fix linux SCSI sense reporting via SG_IO ioctl.
+
+  [DG] [SCSI] Change lba of first failure in selftest output to
+       decimal (was hex) to conform with ATA output.
+
+  [GK] smartd: Detect most self-test failures even if the hour counter
+       has wrapped.
+
+  [BA] smartctl: list 'marvell' as option if user give invalid
+       -d argument
+
+  [CF] Windows: fixed SCSI timeout handling to allow long timeouts
+       for selftests.
+
+  [CF] Fixed buffer overflow issues in printone() and safe_vsnprintf()
+       which results in crash on -V option (at least on Windows).
+
+  [DG] [SCSI] Add explicit timeouts to INQUIRY and REQUEST SENSE (that
+       were missed in an earlier patch). Could have impacted freebsd.
+
+  [DG] When linux detects a sata_via_libata disk suggest that user try
+       '-d ata' (rather then '-d libata). Anticipate kernel change.
+
+  [YD] Added OS/2 and eComStation platform support.
+
+  [PW] Added Seagate U4 family, Fujitsu MHJ and MHK families, Seagate
+       Barracuda 5400.1, QUANTUM FIREBALLP KX27.3, QUANTUM FIREBALLP KA10.1,
+       and ExcelStor J340 to knowndrives table.
+
+  [DG] [SCSI] After report of Hitachi IC35L073UCDY10 disks locking up
+       on log page 0x7 (last n error events), check log page (and some
+       others) is supported (via log page 0x0) before probing.
+
+  [CF] Added safe_v?snprintf() for platforms using v?snprintf()
+       with non standard behaviour on overflow (Windows, old Linux)
+
+  [CF] smartd: Added message if check power mode spins up disk.
+
+  [CF] Windows: Added support for READ_LOG on WinNT4 using undocumented
+       pseudo SCSI command via IOCTL_SCSI_PASS_THROUGH.
+
+  [CF] smartd: Added ',q' option for '-n' directive to suppress 'skipping
+       checks' log message. This prevents a laptop disk from spinning up
+       due to this message. Thanks to Rob MacLachlan and Manfred Schwarb
+       for pointing out problem & solution.
+
+  [CF] Windows: Added function get_os_version_str() to show OS flavor in
+       copyright message.
+
+  [CF] Windows: Added function ata_identify_is_cached() to check for outdated
+       SMART enabled bit in identify data.
+
+  [CF] Windows: Added fix to prevent linkage of smartd specific win32 modules
+       to smartctl.
+
+  [PW] Added Fujitsu MPG3153AH, Hitachi Endurastar J4K20/N4K20 (formerly
+       DK23FA-20J), Seagate Momentus family, and Maxtor Fireball 3 family
+       to knowndrives table.
+
+  [PW] Added missing Maxtor DiamondMax 16, Seagate Barracuda ATA IV, and
+       Western Digital Caviar WDxxxAA/WDxxxBA drives to knowndrives table.
+
+  [CF] Windows: Added ATA check power mode for smartd -n directive.
+
+  [CF] Windows: Fixed use of new service status flag which causes hang
+       of smartd service on WinNT4.
+
+  [CF] Windows: Fixed error checking of IOCTL_IDE_PASS_THROUGH (used
+       for READ_LOG on 2000/XP). Added some diagnostic messages on
+       -r ataioctl[,2]. Thanks to Manfred Schwarb for bug report and testing.
+
+  [BA] Fixed code bug that made it impossible to enable SMART on
+       disks with failing health status.  This would happen if the
+       os_*.c author made STATUS and STATUS_CHECK work the same way.
+       I have corrected this at a higher level; we now handle the
+       case where STATUS and STATUS_CHECK are identical without
+       issues. 
+
+  [LW] Make os_linux.c/marvell_command_interface() always return 0 on STATUS.
+       Needed for a disk having bad SMART status.
+
+  [CF] smartctl: Added drive family printing.
+
+  [CF] autogen.sh: Allow automake 1.9, added message if automake
+       version is unknown.
+
+  [BA] smartctl: use locale-specific separators for printing disk
+       capacity.  Also use AC_CHECK_HEADERS not AC_CHECK_HEADER in
+       configure.in.
+
+  [BA] clean-up of #include structure so that -V options to smartd
+       and smartctl work correctly.  Please, don't #include header
+       files into other header files.
+
+smartmontools 5.33 Experimental Release
+
+  [BA] smartctl: ATA disks, if SMART ATTRIBUTE THRESHOLDS page has ID
+       errors with some Attributes having NULL IDs, print Attribute
+       info anyway (but issuing a warning to the user).
+
+  [DG] [SCSI] Decode Last n error events log page; decode track following
+       and positioning errors [Hitachi]
+
+  [EM] FreeBSD: another tweak, __packed__ introduced in Version 5.0040
+
+  [EM] Cleaner tweak of fixes for FreeBSD 4.x.
+
+  [EM] Fix compilation errors under FreeBSD 4.x, as it is still using
+       and old GCC
+
+  [EM] Remove 3ware/FreeBSD specific files and just include pieces we need
+
+  [DG] Add logic in smartd to detect 3ware, Marvell controllers and SATA
+       disks behind an ATA-SCSI simulator (in Linux). If specific device
+       types are not given and they are picked in a general SCSI device
+       scan then warn and skip.
+
+  [GG] insert correct path to smartd into smartd's init script
+
+  [BA] Changed all default paths in documentation to reflect /usr/local as
+       default path prefix.  This affects on-line man pages, primarily.
+  
+  [DS] Added support for OpenBSD
+
+  [BA] Added another environment variable SMART_FULLMESSAGE set by
+       the smartd mailing feature, and modified examplescripts/Example1
+       to illustrate it.
+
+  [BA] Fixed potentially misleading messages of the form:
+       XXX failed: success
+
+  [DG] emit warning if SATA disk detected using libata in Linux; then exit
+
+  [PW] Added Seagate U10 family, Hitachi Travelstar 7K60, Fujitsu MHR2020AT,
+       and QUANTUM FIREBALLP AS20.5 to knowndrives table.
+
+  [DG] Detect 3ware and Marvell controllers from SCSI INQUIRY vendor string
+       and suggest usage of appropriate '-d' argument in smartctl.
+
+  [LW] Tested the RELEASE_5_33_WITH_MARVELL_SUPPORT branch on
+       actual Marvell 88SX5041 hardware, with success.
+       Merged into HEAD.
+
+  [BA] Fixed nasty DEVICESCAN bug
+
+  [BA] Checked in RELEASE_5_33_WITH_MARVELL_SUPPORT branch with
+       some Marvell support.
+
+  [BA] Additional modifications of Ed's controller scheme.  Fixed
+       broken 3ware support under linux, problems with scanning
+       devices in smartd, and other small problems.
+
+  [CF] Added make targets to build formatted man pages (htmlman, txtman),
+       Windows distribution (dist-win32) and MSVC6 config.h (config-vc6).
+
+  [EM] Minor change to FreeBSD inclusion of 'twe' include files.  Add 
+       code to check if they exising in /usr/include/sys to use those
+       in preference to ones added here
+
+  [EM] Very preliminary support attempt for 3Ware controllers under 
+       FreeBSD. Also, switched 'escalade_type/escalade_port' to
+       'controler_type/controller_port' and moved away from 
+       'tryata/tryscsi' to using new 'controller*' variables to 
+       determine which controller type (ATA/SCSI/3Ware) to use.
+
+  [GK] Added initscript support for Darwin.
+
+  [CF] Windows smartd: Added ability to run smartd as a windows service,
+       including new commands "smartd install ..." and "smartd remove"
+       to install and remove the service registry entry.
+
+  [BA] smartd: warn user if -s regexp regular expression contains
+       characters other than 0123456789.*()|+?[-]{}:=SLCO since such
+       characters are 'suspicous' and may indicate a poorly formed
+       regexp.  Extended regular expression gurus: can this list be
+       reduced somewhat?
+
+  [CF] Fixed bug in Windows smartd: Missing close of config file when
+       configuration is reloaded by smartd daemon.
+
+  [CF] Windows smartd: Added mail warning feature using the "Blat"
+       (http://blat.sourceforge.net/) mailer as a default.
+
+  [PW] Added Maxtor DiamondMax Plus 5120 Ultra ATA 33 series and TOSHIBA
+       MK3017GAP to knowndrives table.
+
+  [CF] Added fixes to build smartmontools on old Linux systems
+       (libc < 6, Kernel 2.0.x).
+
+  [BA] Added ATA minor version identity strings for latest ATA specification
+       updates: ATA/ATAPI-7 T13 1532D revision 4a and ATA/ATAPI-6 published,
+       ANSI INCITS 361-2002
+
+  [PW] Added Hitachi Travelstar 5K80 family and Fujitsu MHTxxxxAH family to
+       knowndrives table.
+
+  [EM] Fix up compilation under FreeBSD < 5.x
+
+  [PW] Added QUANTUM FIREBALL EX3.2A and missing Western Digital Caviar SE
+       drives to knowndrives table.
+
+  [BA] Modified Hitachi Travelstar 80GN family regexp in drive database.
+       Thanks to [GK/CF] for problem & solution.
+
+  [GK] Added os_darwin.[ch]
+
+  [PW] Added the following drives to the knowndrives table: IBM Travelstar
+       48GH, 30GN, and 15GN family; IBM Deskstar 37GP and 34GXP family;
+       Western Digital WDC WD272AA; Maxtor DiamondMax D540X-4D family;
+       TOSHIBA MK2016GAP, MK2018GAP, MK2018GAS, MK2023GAS; and
+       QUANTUM FIREBALL ST3.2A
+
+  [BA] smartd/smarctl now print build HOST/OS information as part
+       of startup slogan.  This should make it slightly easier to
+       read bug reports from users.
+
+  [RZ] Fixed the DEVICESCAN to do what it was supposed to do - give
+       error message unless scanning is in progress.  
+
+  [BA] Update documentation to describe 3ware character devices. Better
+       error detection for missing/malfunctioning devices behind 3ware
+       controllers. Now pack 3ware ioctl structures explicitly.
+
+  [BA] For ATA devices that support LBA mode, print capacity as part
+       of smartctl --info
+
+  [RZ] Made DEVICESCAN quiet about non-existing devices unless debug
+       is on.
+
+  [DG] treat "unit attention" SCSI warning as try again in some contexts
+       (test unit ready and mode sense)
+
+  [BA] on drives that store max/min rather than min/max, get order
+       correct in printing temp.
+
+  [BA] fixed typo in 'smartctl -h' output.  Thanks to Gabor Z. Papp.
+
+  [BA] linux: clean-up to 3ware/AMCC support; dynamically create
+       or fix /dev/tw[ae][0-15] device node entries if they don't
+       exist or are incorrect. One can now use the character devices
+       /dev/twe[0-15] OR /dev/sd? for 3ware 6000/7000/8000 series
+       cards.  One must use /dev/twa[0-15] for 3ware 9000 series cards.
+       Note that selective self-tests now work via /dev/tw[ae] devices.
+       Next step: documentation.
+
+  [BA] linux: experimental "support" for 3ware/AMCC 9000 series
+       controllers that use the 3w-9xxx driver.  This will be in a
+       state of flux for a few days.  Note that this requires the
+       character interface /dev/twa[0-15].
+
+  [DG] linux: extend general SCSI OS interface to use the SG_IO ioctl. If
+       not available, use the older SCSI_IOCTL_SEND_COMMAND ioctl.
+
+  [KS] Solaris/x86: fixed system identification problem in configure
+       script.  Thanks to Stuart Swales.
+
+smartmontools 5.32
+
+  [BA] Update link to revised/updated IBM Deskstar Firmware
+
+  [CF] Cygwin & Windows: Added missing ASPI manager initialization
+       with GetASPI32SupportInfo(). Thanks to Nikolai SAOUKH for pointing
+       this out and providing a patch.
+
+  [BA] modified smartd init script to work on whitebox (thanks to
+       Michael Falzon)
+
+  [BA] removed (reverted) additional Attribute definitions from
+       http://smart.friko.pl/attributes.php.  All (or most?) of these
+       appear to be return code values for the WD Digital Life Guard Utility.
+
+  [PW] Added Seagate Medalist 17242, 13032, 10232, 8422, and 4312 to
+       knowndrives table.  Added missing Seagate U Series 5 drives.
+
+  [PW] Added the following QUANTUM models to knowndrives table:
+       FIREBALL EX6.4A, FIREBALLP AS10.2, FIREBALLP AS40.0, FIREBALL CR4.3A,
+       FIREBALLP LM15, FIREBALLP LM30, and FIREBALLlct20 30
+
+  [PW] Added missing Western Digital Protege drives to knowndrives table.
+
+  [PW] Added Maxtor DiamondMax 40 ATA 66 series and DiamondMax 40 VL Ultra
+       ATA 100 series to knowndrives table.
+
+  [PW] Added the following Hitachi/IBM drives to knowndrives table:
+       HITACHI_DK14FA-20B, Travelstar 40GNX series, Travelstar 4LP series,
+       and Travelstar DK23XXB series.  Added the missing Travelstar 80GN
+       drives.
+
+  [PW] Added Fujitsu MPB series and MPG series to knowndrives table.  Added
+       the missing Fujitsu MHSxxxxAT drives.
+
+  [KS] Solaris: added workaround for dynamic change of time-zone.
+
+  [KS] Solaris: fixed problem that autogen.sh cannot detect absence of
+       auto* tools.
+
+  [BA] smartd: added time-zone bug information to man page. 
+       Reverted CF code for _WIN32 case. 
+
+  [CF] Cygwin & Windows: Added better error messages on IDE/ATA device
+       open error.
+
+  [BA] added additional Attribute definitions from
+       http://smart.friko.pl/attributes.php
+
+  [BA] smartd: reworked TimeZone bug workaround so it is only invoked
+       for glibc.  Note: this might not be right -- a similar bug may
+       exist in other platform's libcs.
+
+  [DG] SCSI smartmontools documentation updated [2004/5/6]. See:
+       http://smartmontools.sourceforge.net/smartmontools_scsi.html
+
+  [CF] Windows: Fixed reset of TZ=GMT in glibc timezone bug workaround.
+
+smartmontools 5.31
+
+  [DG] move SCSI device temperature and start-stop log page output
+       (smartctl) into --attributes section (was in --info section).
+
+  [GG] change default installation location to /usr/local
+
+  [CF] Cygwin smartd: Fixed crash on access of SCSI devices after fork().
+
+  [PW] Added TOSHIBA MK4018GAS and the following Maxtor drive families
+       to knowndrives table: DiamondMax D540X-4G, Fireball 541DX,
+       DiamondMax 3400 Ultra ATA, DiamondMax Plus 6800 Ultra ATA 66.
+
+  [PW] Added missing Maxtor DiamondMax 16, DiamondMax D540X-4K, and
+       DiamondMax Plus 45 Ulta ATA 100 drives to knowndrives table.
+
+  [PW] Added ExcelStor J240, Hitachi Travelstar 80GN family, Fujitsu
+       MHTxxxxAT family, and IBM Deskstar 25GP and 22GXP families to
+       knowndrives table.
+
+  [CF] Cygwin smartd: Added workaround for missing SIGQUIT via keyboard:
+       To exit smartd in debug mode, type CONTROL-C twice.
+
+  [BA] smartctl: printing of the selective self-test log is now
+       controlled by a new option: -l selective
+
+  [BA] Added entries for Samsung firmware versions -25 to -39 based
+       on latest info about firmware bug fixes.
+
+  [PW] Added Seagate U Series X family, Seagate U8 family, and Seagate
+       Medalist 8641 family to knowndrives table.
+
+  [CF] smartd: Added exit values 5/6 for missing/unreadable config file.
+
+  [BA] smartd: now monitor the Current Pending Sector count (Attribute 197)
+       and the Offline Pending Sector Count (Attribute 198).  Log a
+       warning (and send an email, if so configured) if the raw count
+       is nonzero.  These are controlled by new Directives: -C and -U.
+       Currently they are enabled by default.
+
+  [CF] Added option -c FILE, --configfile=FILE to smartd to specify
+       an alternate configuration FILE or '-' for standard input.
+
+  [KS] configure.in now searches for -lnsl and -lsocket for Solaris.
+
+  [CF] Win32/native smartd: Added thread to combine several syslog output
+       lines into one single event log entry.
+
+  [CF] Win32 smartd: Added DEVICESCAN for SCSI/ASPI devices.
+
+  [GG] Use gethostbyname() the get the DNS domain since getdomainname() 
+       returns the NIS domain when sending mails from smartd.
+
+  [GG] smartd.init.in: pass smartd_opts to smartd on startup, read distribution
+       specific configuration files if found
+
+  [SS] smartctl: added NetBSD support for Selective Self-tests.
+
+  [BA] smartd.conf example configuration file now has all examples
+       commented out except for 'DEVICESCAN'.
+
+  [CF] Win32/native smartd: Added ability to display warning "emails"
+       as message box by "-m msgbox" directive. With "-m sysmsgbox",
+       a system modal (always on top) message box is shown.
+
+  [BA] smartctl: printing of self-test log for disks that support
+       Selective self-testing now shows the status of the (optional)
+       read-scan after the selective self test.  Also, changed format
+       in printing self-test log to print failing LBA in base 10 not
+       base 16 (more compatible with kernel error messages).  Also,
+       in printing SMART error log, print timestamps in format
+       days+hours+minutes+seconds.
+
+  [CF] Win32 smartd: Added ability to log to stdout/stderr
+       (-l local1/2). Toggling debug console still works
+       if stdout is redirected.
+
+  [BA] smartctl: selective self-test log, print current status
+       in a  more detailed way.  Allow writing of selective self-test
+       log provided that no other self-test is underway.
+
+  [BA] Linux: eliminated dependency on kernel tree hdreg.h.
+
+  [BA] smartctl: -l selftest option now prints Selective self-test
+       log in addition to the normal self-test log.
+       Added additional options (-t pending, -t afterselect) to
+       control remaining Selective Self-test capabilities.  Tested
+       with several Maxtor disks. Modified error message printing
+       so that munged option messages print at the end not the
+       start of output.
+
+  [CF] Added daemon support to Win32 native version of smartd.
+       The daemon can be controlled by commands similar to initd
+       scripts: "smartd status|stop|reload|restart|sigusr1|sigusr2".
+
+  [CF] Added minor support for option "-l local[0-7]" to Win32 native
+       (not Cygwin) version of smartd. If specified, the log output
+       is written to file "./smartd[1-7]?.log" instead of event log.
+
+  [BA] Added Selective Self-test to smartctl (-t selective,M-N).
+       Currently only supported under Linux; Solaris, NetBSD, FreeBSD
+       and Windows developers must add WRITE LOG functionality to
+       os_*.c
+
+  [BA] Added workaround for an annoying glibc bug: if you change
+       timezones, (eg, flying with a laptop from USA to Europe)
+       localtime() does not notice this in a running
+       executable, so time that appears in the system log (syslog!)
+       will be incorrect.  See
+       http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=48184
+       for additional examples of this bug.
+
+  [DG] Set explicit timeouts for SCSI commands (most default to 6 seconds).
+       Previously a 0 second timeout was meant to be interpreted as a 
+       default timeout but the FreeBSD port had a problem in this area.
+
+  [CF] Fixed un-thread-safe exit signal handler for Win32
+
+  [BA] Fixed un-thread-safe exit signal handler pointed out
+       by CF.
+
+  [BA] Changed configure script to eliminate warnings under
+       Solaris from sys/int_type.h conflicts with int64.h
+       Added header files for umask to smartd.c.
+
+  [BA] Man page format change from Werner LEMBERG.  " " changed to \&
+
+  [CF] Added os_win32/syslogevt.* event message file tool for Win32
+       smartd (native+cygwin). May also be useful for other cygwin
+       programs writing to syslog().
+
+  [CF] Added Win32 version of smartd
+
+  [CF] Merged RELEASE_5_26_WIN32_BRANCH
+
+  [BA] Made some changes to man page markup suggested by
+       Richard Verhoeven to work around bugs in man2html.
+       Tested not to break anything under Linux and Solaris.
+
+  [CF] Moved PrintOut() from utility.c to smart{ctl,d}.c to avoid
+       syslog() output of smartctl.
+
+  [BA] Grew worried that some time-zone names could be very long (eg,
+       Mitteleuropaische Zeit) and put date string lengths into a
+       single macro in utility.c
+
+  [EM] Updated os_freebsd.c to handle older versions of FreeBSD in a 
+       more appropriate/obvious fashion.
+
+  [EM] Modified autogen.sh as FreeBSD installs automake 1.7 as 
+       'automake17' and NOT 'automake-1.7'
+
+smartmontools 5.30
+
+  [PW] Added QUANTUM FIREBALLlct15 30, QUANTUM FIREBALLlct20 40, and
+       Maxtor 6Y060P0 (DiamondMax Plus 9 60GB) to knowndrives table.
+
+  [PW] Added Maxtor MaXLine II family to knowndrives table (thanks to
+       Brett Russ for submitting the patch).
+
+  [BA] Added remaining read/write commands to detailed list of
+       error log commands that have text descriptions of problem
+       printed.  For commands that support it, print number of failed
+       sectors at problem LBA.
+
+  [BA] Made SuSE section of smartd init script more SuSE 9 compatible.
+       Thanks to Hans-Peter Jansen.
+
+  [CF] Windows smartd: Added IDE/ATA device scan
+       Added windows device names to smartctl.8.in, smartd.8.in
+   
+  [BA] smartctl/smartd: user-provided '-F samsung' and '-F samsung2'
+       command line options/Directives did NOT over-ride preset values
+       unless user specified '-P ignore'.  Now they will always over-ride
+       preset values from the database.
+
+  [BA] Added error decoding for a few more READ and WRITE commands.
+
+  [PW] Added Maxtor MaXLine Plus II, Western Digital Caviar SE (Serial ATA)
+       series, Hitachi Deskstar 7K250 series, and Ultra ATA 66 models of
+       the Maxtor DiamondMax Plus 40 series to knowndrives table.
+
+  [BA] Added Maxtor Diamondmax 250 GB drives to database.  Note that
+       these model numbers are not listed in Maxtor documentation, but
+       they exist.
+
+  [BA] Removed the 'contact developers' phrase from the Samsung disk
+       warning messages.
+
+  [PW] Added TOSHIBA MK2017GAP, IBM Deskstar 14GXP and 16GP series,
+       Fujitsu MPC series, Seagate Barracuda ATA III family, and missing
+       Seagate Barracuda U Series drives to knowndrives table
+
+  [BA] smartd: wrong loglevel for message: Configuration file
+       /etc/smartd.conf parsed.  Changed to LOG_INFO from LOG_CRIT.
+       Thanks to  Emmanuel CHANTREAU for the report.
+
+  [CF] Checked in development version of windows code base.
+
+smartmontools 5.29 (note: there was NO 5.28 release)
+
+  [BA] smartd: configure script did not set correct directory to search for
+       smartd.conf based on --prefix argument to ./configure.  Thanks to
+       GG for identifying the problem and fix.
+
+  [BA] make clean now removes man pages (generated from *.in) files as well
+       as object files.
+
+  [EM] Correct copying of sense data in FreeBSD SCSI implementation. Thanks
+       to Sergey Svishchev for noticing the bug.
+
+  [BA] On solaris, wrong warning message if no ATA support.  Warning message
+       concerns 3ware controller, not ATA.
+
+  [SS] Added SCSI support for NetBSD.
+
+  [BA] on big-endian linux machines, fixed interpretation of HDIO_GET_IDENTITY
+       to correctly identify ATAPI bit (was byte swapped).  This should
+       eliminate some SYSLOG noise if user queries a packet device (eg, CD
+       ROM or DVD reader).
+
+  [PW] Removed warning for IBM Deskstar 40GV & 75GXP series drives with
+       A5AA/A6AA firmware.  Thanks to Gerald Schnabel.
+
+  [PW] Added Toshiba TOS MK3019GAXB SUN30G to knowndrives table
+
+  [PW] Added Western Digital Caviar AC12500, AC24300, AC25100, AC36400,
+       and AC38400 to knowndrives table
+
+  [BA] When printing ATA error log, print the LBA at which READ
+       or WRITE commands failed.
+
+  [BA] Changed syntax of error message in smartctl
+
+  [BA] Added versioning info (-V options to smartd/smartctl) for
+       Solaris ATA module.
+
+smartmontools 5.27
+
+  [KS] Added ATA/IDE support for Solaris/SPARC (ATA/IDE not yet for
+       Solaris/x86).
+
+  [BA] 3ware controllers: documented that one can monitor any of the
+       physical disks from any of the 3ware /dev/sd? logical devices.
+       Better warnings if querying a disk that does not exist.
+
+  [PW] Added Hitachi Travelstar DK23DA series, Maxtor DiamondMax Plus 40
+       series, Western Digital Caviar WDxxxAA, WDxxxBA, and WDxxxAB series
+       to knowndrives table
+
+  [BA] missing 'pragma pack' on ATA IDENTIFY DEVICE structure may have
+       caused odd or incorrect results on 64-bit machines.
+
+  [BA] smartctl/smartd allow inspection of self-test and error logs even
+       if disk firmware claims that these don't exist.  This is needed
+       for some Maxtor disks whose firmware does not indicate log support
+       even though the disk DOES support it.
+
+  [BA] Improved porting instructions and documentation in os_generic.c
+
+  [PW] Add Western Digital Caviar WD136AA and SAMSUNG SP40A2H (RR100-07
+       firmware) to knowndrives table.
+
+  [EM] FreeBSD:        remove extra definition of FreeNonZero
+
+  [BA] smartctl: the -q silent option was printing output for some
+       error conditions.  Fixed.  Will rename relevant variables to help
+       avoid these errors in the future.
+
+  [SS] NetBSD port added.
+
+  [BA] more sensible error messages for devfs and devfs-like systems.
+       Instead of saying that the DIRECTORY does not exist, say that
+       the DEVICE does not exist.
+
+  [BA] smartd: added -n Directive, to prevent disk spin-up depending
+       upon the power mode (SLEEP, STANDBY, or IDLE).
+
+  [PW] Added Maxtor DiamondMax 20 VL series, Fujitsu MPF series,
+       Maxtor DiamondMax 36 series, Maxtor DiamondMax 4320 series, and
+       Maxtor DiamondMax 536DX series to knowndrives table.
+
+  [BA] many warning messages now give the file name AND VERSION
+
+  [BA] smartd: when the user provides multiple address recipients
+       to the '-m' Directive in a comma-delineated list, the commas
+       are stripped out before passing the list of addresses to the
+       mailer program. (Thanks to Calin A. Culianu for pointing this out
+       and providing a patch.)
+
+  [BA] smartd: when the '-M exec path' Directive is used, any stdout OR
+       stderr output from the executable "path" is assumed to indicate a
+       problem, and is echoed to SYSLOG.
+
+  [BA] Added all missing IBM/Hitachi Deskstar 180GXP models to knowndrives
+       table.
+
+  [PW] Added some missing IBM/Hitachi Deskstar 120GXP models to knowndrives
+       table.
+
+  [PW] Added IBM Travelstar 14GS to knowndrives table.
+
+  [PW] Modified knowndrives table to match entire Hitachi Travelstar
+       DK23BA and DK23EA series of drives (thanks to Norikatsu Shigemura
+       for submitting the patch).
+
+  [PW] Added some missing Fujitsu MPE series drives to knowndrives table.
+
+  [PW] Added TOSHIBA MK4019GAX, TOSHIBA MK6409MAV, and QUANTUM
+       FIREBALLlct15 20 to knowndrives table.
+
+  [EM] Fixup example command output for FreeBSD
+
+  [PW] Added Maxtor DiamondMax 80 family to knowndrives table.
+
+  [EM] Catch up FreeBSD code to switch PROJECTHOME to PACKAGE_HOMEPAGE
+       macros.
+
+  [BA] smartd: now watches stdout/stderr when trying to run mail, mailx
+       or mail warning script, and reports any output to SYSLOG.  This
+       gives a clearer error message if something is wrong.
+
+  [BA] smartd: Solaris init script modified to accomodate grep that
+       lacks '-q' quiet option.  Also check for running process to kill
+       on stop.
+
+  [PW] Added some missing Seagate Barracuda 7200.7 and 7200.7 Plus drives
+       to knowndrives table.
+
+  [PW] Added Maxtor DiamondMax Plus 60 family and Seagate U Series 5 20413
+       to knowndrives table.
+
+  [BA] smartd: under Solaris, made default mailer be 'mailx' not
+       'mail', since Solaris 'mail' does not accept a '-s' argument.
+       A workaround for Solaris users of earlier versions is to
+       have '-M exec /bin/mailx' in their smartd.conf config file.
+
+  [DG] some SCSI controllers don't like odd length transfers so make
+       sure LOG SENSE transfers are rounded up to an even number when
+       and odd length is reported (i.e. there is a double fetch, the
+       first to find the length, the second gets the data)
+
+  [BA] smartd man pages: under Solaris, correct section numbers in the
+       'See also' section.
+
+  [KS/BA] smartd man page: describe how to set Solaris syslog.conf
+       file to catch all messages.  Give correct Solaris SYSLOG default
+       path /var/adm/messages in man pages.
+
+  [BA] smartd: incorporated Debian startup script submitted by user.
+
+  [BA] smartctl: modified printing of self-test log entry number.  Seagate
+       firmware can leave 'holes' in the self-test log while a test is
+       actually running.  We now print entry numbers consistently in this
+       case, not assuming that entries are contiguous.
+
+  [PW] Added QUANTUM FIREBALL CX10.2A and Western Digital Caviar AC23200L
+       to knowndrives table.
+
+  [PW] Added QUANTUM FIREBALLlct20 20 to knowndrives table.
+
+  [PW] Added Maxtor DiamondMax Plus D740X family to knowndrives table.
+
+  [PW] Added IBM Travelstar 32GH, 30GT, and 20GN family to knowndrives
+       table.
+
+  [BA] Slackware init script modified to search for /etc/slackware-version
+       rather than /etc/slackware-release.
+
+  [PW] Added Seagate Barracuda ATA II family and TOSHIBA MK4019GAXB to
+       knowndrives table.
+
+  [GG] explain howto use autoreconf in autogen.sh
+
+  [KS] Makefile.am/configure.in: changed manual page sections for
+       Solaris.
+
+  [BA] smartd: reduced number of scheduled self-test messages if
+       test already run in current hour.
+
+  [PW] Added Maxtor DiamondMax Plus 8 family to knowndrives table.
+
+  [BA] linux: check for linux/hdreg.h.  If it's there, use it. If
+       not, provide the necessary definitions ourselves.
+
+  [PW] Removed warning for IBM Deskstar 40GV & 75GXP series drives
+       with TXAOA5AA firmware
+
+  [PW] Added IBM Travelstar 25GS, 18GT, and 12GN family to knowndrives
+       table.
+
+  [PW] Added IBM/Hitachi Travelstar 60GH & 40GN family to knowndrives
+       table.
+
+  [BA] smartd: made '-s' Directive more efficient.  Now store
+       compiled regex, and re-use.  If device lacks certain self-test
+       capabilities, track it and don't try again.
+
+  [BA] smartd: made memory allocation for device lists completely
+       dynamic (eliminating compile-time maximum length constants).
+
+  [PW] Removed warning for SAMSUNG SP0802N with TK100-23 firmware
+
+  [PW] Added Seagate Barracuda ATA IV family to knowndrives table.
+
+  [BA] smartd: reduce per-device memory footprint by making
+       mail-warning info dynamically allocated.  Also remove
+       potential memory leak if use has -m Directive twice and
+       keeps reloading the config file (highly unlikely this would
+       ever be noticed!)  
+
+  [DG] smartd: added SCSI scheduled self-tests (Background
+       short or extended).
+
+  [BA] smartd: can now run scheduled offline immediate and
+       self-tests.  See man page and -s Directive for details.
+
+  [GG] don't include manpages in make-dist-tarball.
+
+  [BA] smartctl: on-line examples given with -h are now correct
+       for solaris and linux, but wrong for freebsd.  Ed?
+
+  [BA] smartd: man page now explains device scanning for solaris as
+       well as linux and freebsd.
+
+  [BA] smartd/smartctl: man pages now report correct CVS tag release
+       date, and executables '-V' options reports more build info.
+
+smartmontools 5.26
+
+  [BA] Improved user messages that appear from 'make install'
+
+  [PW] Removed warning for SAMSUNG SP1213N with firmware TL100-23
+
+  [BA] incorporated SuSE init script from user.
+
+  [DG] if SCSI device is read only, then open it read only.
+
+  [BA] when compiled on non-supported system (NOT linux, freebsd or solaris) then
+       the run-time error messages now clearly say 'your system is not supported'
+       and give clear directions.
+
+  [BA] ./configure script now works correctly on SuSE linux boxes
+
+  [BA] minor improvements to man pages
+
+  [BA] simplified detection of packet (ATAPI, CD) devices.
+
+  [BA] init script (redhat, mandrake, yellowdog) now uses correct
+       strings for translation and is slightly more standard.
+
+  [DG] smartctl: output scsi Seagate vendor pages for disks (not tapes)
+
+smartmontools 5.25
+
+Note: there was no '5.24' release. From this point on, even numbered
+releases will be 'stable' ones and odd numbered releases will be
+unstable/testing/development ones.
+
+  [DG] smartd/smartctl: changed scsiClearControlGLTSD() to
+       scsiSetControlGLTSD() with an 'enabled' argument so '-S on'
+       and '-S off' work for SCSI devices (if changing GLTSD supported).
+
+  [BA] smartd/smartctl: wired in scsiClearControlGLTSD(). Could still
+       use a corresponding Set function.  Left stubs for this purpose.
+
+  [DG] scsicmds: added scsiClearControlGLTSD() [still to be wired in]
+
+  [BA] smartctl: make SCSI -T options behave the same way as the
+       ATA ones.
+
+  [DG] smartctl: output scsi transport protocol if available
+
+  [DG] scsi: stop device scan in smartd and smartctl if badly formed
+       mode response [heuristic to filter out USB devices before we
+       (potentially) lock them up].
+
+  [BA] smartd: deviceclose()->CloseDevice(). Got rid of SCSIDEVELOPMENT
+       macro-enabled code.  Added -W to list of gcc specific options to
+       always enable. Made code clean for -W warnings.
+
+  [PW] Added Maxtor DiamondMax VL 30 family to knowndrives table.
+
+  [DG] scsi: add warning (when '-l error' active) if Control mode page
+       GLTSD bit is set (global disable of saving log counters)
+
+  [DG] scsi: remember mode sense cmd length. Output trip temperature
+       from IE lpage (IBM extension) when unavailable from temp lpage.
+
+  [BA] smartd: for both SCSI and ATA now warns user if either
+       the number of self-test errors OR timestamp of most
+       recent self-test error have increased.
+
+  [DG] smartctl: output Seagate scsi Cache and Factory log pages (if
+       available) when vendor attributes chosen
+
+  [DG] smartd: add scsiCountFailedSelfTests() function.
+
+  [DG] Do more sanity checking of scsi log page responses.
+
+  [BA] smartd: now warns user if number of self-test errors has
+       increased for SCSI devices.
+
+  [BA] smartd: warn user if number of ATA self-test errors increases
+       (as before) OR if hour time stamp of most recent self-test
+       error changes.
+
+  [DG] More checks for well formed mode page responses. This has the side
+       effect of stopping scans on bad SCSI implementations (e.g. some
+       USB disks) prior to sending commands (typically log sense) that
+       locks them up.
+
+  [PW] Added Western Digital Caviar family and Caviar SE family to
+       knowndrives table.
+
+  [BA] smartd: added -l daemon (which is the default value if -l
+       is not used).
+
+  [PW] Added Seagate Barracuda ATA V family to knowndrives table.
+
+  [BA] smartd: added additional command line argument -l FACILITY
+       or --logfacility FACILITY.  This can be used to redirect
+       messages from smartd to a different file than the one used
+       by other system daemons.
+
+  [PW] Added Seagate Barracuda 7200.7, Western Digital Protege WD400EB,
+       and Western Digital Caviar AC38400 to knowndrives table.
+
+  [BA] smartd: scanning should now also work correctly for
+       devfs WITHOUT traditional links /dev/hd[a-t] or /dev/sd[a-z].
+  
+  [PW] Added Maxtor 4W040H3, Seagate Barracuda 7200.7 Plus,
+       IBM Deskstar 120GXP (40GB), Seagate U Series 20410,
+       Fujitsu MHM2100AT, MHL2300AT, MHM2150AT, and IBM-DARA-212000
+       to knowndrives table.
+
+  [PW] Added remaining Maxtor DiamondMax Plus 9 models to knowndrives
+       table.
+
+  [EM] smartd: If no matches found, then return 0, rather than an error
+       indication, as it just means no devices of the given type exist.
+       Adjust FreeBSD scan code to mirror Linux version.
+
+  [BA] smartd: made device scan code simpler and more robust. If
+       too many devices detected, warn user but scan as many
+       as possible.  If error in scanning, warn user but don't
+       die right away.
+
+  [EM] smartd: To keep as consistent as possible, migrate FreeBSD
+       devicescan code to also use glob(3). Also verified clean 
+       compile on a 4.7 FreeBSD system.
+
+  [BA] smartd: Modified device scan code to use glob(3). Previously
+       it appeared to have trouble when scanning devices on an XFS
+       file system, and used non-public interface to directory
+       entries. Problems were also reported when /dev/ was on an
+       ext2/3 file system, but there was a JFS partition on the same
+       disk.
+
+  [BA] Clearer error messages when device scanning finds no suitable
+       devices.
+
+  [EM] FreeBSD:        Fixup code to allow for proper compilation under 
+       -STABLE branch.
+
+smartmontools 5.23
+
+  [BA] smartd: didn't close file descriptors of ATA packet devices
+       that are scanned. Fixed.
+
+  [BA] Added reload/report targets to the smartmontools init script.
+       reload: reloads config file
+       report: send SIGUSR1 to check devices now
+
+smartmontools 5.22
+
+  [EM] Fix compile issues for FreeBSD < 5-CURRENT.
+
+  [PW] Added Fujitsu MHM2200AT to knowndrives table.
+
+  [BA] To help catch bugs, clear ATA error structures before all
+       ioctl calls.  Disable code that attempted to time-out on SCSI
+       devices when they hung (doesn't work).
+  [BA] Documented STATUS/ERROR flags added by [PW] below.
+
+  [BA] Improved algorithm to recognize ATA packet devices. Should
+       no longer generate SYSLOG kernel noise when user tries either
+       smartd or smartctl on packet device (CD-ROM or DVD).  Clearer
+       warning messages from smartd when scanning ATA packet device.
+
+  [PW] Added TOSHIBA MK4025GAS to knowndrives table.
+
+  [PW] Added a textual interpretation of the status and error registers
+       in the SMART error log (ATA).  The interpretation is
+       command-dependent and currently only eight commands are supported
+       (those which produced errors in the error logs that I happen to
+       have seen).
+
+  [BA] added memory allocation tracking to solaris code.
+       Fixed solaris signal handling (reset handler to default
+       after first call to handler) by using sigset. Added
+       HAVE_SIGSET to configure.in
+
+  [CD] solaris port: added SCSI functionality to solaris
+       stubs.
+
+  [BA] smartd: attempt to address bug report about smartd
+       hanging on USB devices when scanning:
+       https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=107615
+       Set a timeout of SCSITIMEOUT (nominally 7 seconds) before
+       giving up.
+
+  [EM] smartd: DEVICESCAN will follow links in a devfs filesystem and
+       make sure the end point is a disc.  Update documentation, added
+       note about FreeBSD scanning
+
+  [BA] smartd: DEVICESCAN also looks for block devices in
+       /dev.  Updated documentation.  Now scans for up to
+       20 ATA devices /dev/hda-t rather than previous 12
+       /dev/hda-l.
+
+  [EM] smartd: mirror the FreeBSD DEVICESCAN logic for Linux,
+       so that smartd now scans only devices found in /dev/. Also,
+       make utility memory functions take a line number and file so
+       that we report errors with the correct location.
+  [GG] add a note about Debian bug #208964 to WARNINGS.
+
+  [BA] smartctl: -T verypermissive option broken.  Use
+       -T verpermissive until the next release, please.
+
+  [BA] Syntax mods so that code also compiles on Solaris using
+       Sun Workshop compiler.  Need -xmemalign 1i -xCC flags
+       for cc.
+
+smartmontools 5.21
+
+  [DK] Changed configure.in so -Wall is only included if gcc
+       is used (this is a gcc specific flag) and -fsignedchar
+       is not used at all (this is a gcc specific compiler 
+       flag).
+
+  [BA] Modifications so that code now compiles under solaris. Now
+       all that's needed (:-) is to fill in os_solaris.[hc].  Added
+       os_generic.[hc] as guide to future ports.  Fixed -D option
+       of smartd (no file name).  Modified -h opt of smartd/smartctl
+       to work properly with solaris getopt().
+
+  [EM] Update MAN pages with notes that 3ware drives are NOT supported
+       under FreeBSD. Cleanup FreeBSD warning message handling.
+
+  [EM] FreeBSD only: Fix first user found bug....I guess I was making
+       the wrong assumption on how to convert ATA devnames to
+       channel/unit numbers.
+  
+  [EM] Allow for option --enable-sample to append '.sample' to installed
+       smartd.conf and rc script files. Also, let rc script shell setting
+       be determined by configure
+
+  [EM] Minor autoconf update to include -lcam for FreeBSD
+
+  [EM] Add conditional logic to allow FreeBSD to compile pre-ATAng.
+       -- note, not tested
+       Add some documentation to INSTALL for FreeBSD.
+
+  [EM] Implement SCSI CAM support for FreeBSD.  NOTE: I am not an expert
+       in the use of CAM.  It seems to work for me, but I may be doing
+       something horribly wrong, so please exercise caution.
+
+  [EM] Switch over to using 'atexit' rather than 'on_exit' routine. This also
+       meant we needed to save the exit status elsewhere so our 'Goodbye'
+       routine could examine it.
+
+  [EM] Move the DEVICESCAN code to os specific files. Also moved some of the
+       smartd Memory functions to utility.c to make available to smartctl.
+
+  [EM] Code janitor work on os_freebsd.c.
+
+  [EM] Added os_freebsd.[hc] code.  Additional code janitor
+       work.
+
+  [BA] Code janitor working, moving OS dependent code into
+       os_linux.[hc].
+
+  [GG] conditionally compile os_{freebsd,linux}.o depending on
+       host architecture
+
+  [PW] Print estimated completion time for tests
+
+  [BA] Added -F samsung2 flag to correct firmware byte swap.
+       All samsung drives with *-23 firmware revision string.
+
+smartmontools 5.20
+
+  [GG] Fixed broken Makefile.am (zero length smartd.conf.5
+       was being created), fix broken uninstall/distcheck targets
+
+  [FM] Improved Slackware init script added to /etc/smartd.initd
+
+smartmontools 5.19 [NOTE CHANGE OF RELEASE NUMBERING]
+
+  [BA] smartctl: added '-T verypermissive' option which is
+       equivalent to giving '-T permissive' many times.
+
+  [BA] Try harder to identify from IDENTIFY DEVICE structure
+       if SMART supported/enabled.  smartd now does a more
+       thorough job of trying to assess this before sending
+       a SMART status command to find out for sure.
+
+  [BA] smartctl: it's now possible to override the program's
+       guess of the device type (ATA or SCSI) with -d option.
+
+  [BA] try hard to avoid sending IDENTIFY DEVICE to packet
+       devices (CDROMS).  They can't do SMART, and this generates
+       annoying syslog messages. At the same time, identify type
+       of Packet device.
+
+  [BA] smartctl: Can now use permissive option more
+       than once, to control how far to go before giving up.
+
+  [BA] smartd: if user asked to monitor either error or self-test
+       logs (-l error or -l selftest) WITHOUT monitoring any of the
+       Attribute values, code will SEGV.  For 5.1-18 and earlier,
+       a good workaround is to enable Auto offline (-o on).
+
+  [BA] smartctl: If enable auto offline command given, update auto
+       offline status before printing capabilities.
+
+  [GG] Make autotools build the default, remove autotools.diff
+
+  [GG] Add auto{conf,make} support, not enabled by default. 
+
+  [BA] Eliminated #include <linux/hdreg.h> from code. This
+       should simplify porting to solaris, FreeBSD, etc. The
+       only linux-specific code is now isolated to three routines,
+       one for SCSI, one for Escalade, one for ATA.
+
+smartmontools 5.1-18
+
+  [BA] smartd: fixed serious bug - Attributes not monitored unless
+       user told smartd to ignore at least one of them!
+
+smartmontools 5.1-17
+
+  [BA] Default runlevels for smartd changed from 3 and 5 to
+       2, 3, 4, and 5.
+
+  [BA] Removed as much dynamic memory allocation as possible from
+       configuration file parsing. Reloading config file, even in
+       presence of syntax errors etc. should not cause memory leaks.
+
+  [PW] It is no longer permissible for the integer part (if any) of
+       arguments to --report and --device to be followed by non-digits.
+       For example, the "foo" in --report=ioctl,2foo was previously
+       ignored, but now causes an error.
+
+  [BA] smartd: added -q/--quit command line option to specify
+       under what circumstances smartd should exit.  The old
+       -c/--checkonce option is now obsoleted by this more
+       general-purpose option.
+
+  [BA] smartd now responds to a HUP signal by re-reading its
+       configuration file /etc/smartd.conf.  If there are
+       errors in this file, then the configuration file is
+       ignored and smartd continues to monitor the devices that
+       it was monitoring prior to receiving the HUP signal.
+
+  [BA] Now correctly get SMART status from disks behind 3ware
+       controllers, thanks to Adam Radford. Need 3w-xxxx driver
+       version 1.02.00.037 or later. Previously the smartmontools
+       SMART status always returned "OK" for 3ware controllers.
+
+  [BA] Additional work on dynamic memory allocation/deallocation.
+       This should have no effect on smartctl, but clears that way
+       for smartd to dynamically add and remove entries.  It should
+       also now be easier to modify smartd to re-read its config
+       file on HUP (which is easy) without leaking memory (which is
+       harder). The philosophy is that memory for data structures in
+       smartd is now allocated only on demand, the first time it
+       is needed.
+
+  [BA] smartd: finished cleanup.  Now use create/rm functions for
+       cfgentries and dynamic memory allocation almost everywhere.
+       Philosophy: aggresively try and provoke SEGV to help find
+       bad code.
+
+  [BA] Added SAMSUNG SV0412H to knowndrives table.
+
+  [BA] smartd: if DEVICESCAN used then knowndrives table might not set
+       the -v attributes correctly -- may have been the same for all
+       the drives.  Cleaned up some data structures and memory
+       allocation to try and ensure segvs if such problems are 
+       introduced again.
+
+  [BA] Now allow -S on and -o on for the 3ware device type.  For these
+       commands to be passed through, the stock 3ware 3w-xxxx driver
+       must be patched (8 lines).  I'll post a patch on the smartmontools
+       home page after it's been tested by a few other people and 3ware
+       have had a chance to look it over.
+
+smartmontools-5.1-16
+
+  [BA] smartd - can now monitor ATA drives behind 3ware controllers.
+
+  [BA] smartd - changed some FATAL out of memory error messages from
+       syslog level LOG_INFO to LOG_CRIT.
+
+  [BA] smartctl - added code to look at ATA drives behind 3ware RAID
+       controllers using the 3w-xxxx driver.  Note that for technical
+       reasons related to the 3w-xxxx driver, the "Enable Autosave",
+       "Enable Automatic Offline" commands are not implemented.
+       I will add this to smartd shortly.
+
+  [BA] smartd - modified sleep loop, so that smartd no longer comes
+       on the run queue every second.  Instead, unless interrupted,
+       it sleeps until the next polling time, when it wakes up. Now
+       smartd also tries to wake up at exactly the right
+       intervals (nominally 30 min) even if the user has been sending
+       signals to it.
+
+  [GG] add Fujitsu MHN2300AT to vendoropts_9_seconds.
+
+  [EB] Fujitsu change in knowndrives ... match the whole MPD and
+       MPE series for vendoropts_9_seconds.
+
+  [BA] smartd bug, might cause segv if a device can not be opened. Was
+       due to missing comma in char* list.  Consequence is that email
+       failure messages might have had the wrong Subject: heading for
+       errorcount, FAILEDhealthcheck, FAILEDreadsmartdata, FAILEDreadsmarterrorlog,
+       FAILEDreadsmartsefltestlog, FAILEDopendevice were all displaced by
+       one.  And FAILEDopendevice might have caused a segv if -m was being
+       used as a smartd Directive.
+
+smartmontools-5.1-15
+
+  [BA] Cleaned up smartmontools.spec so that upgrading, removing
+       and other such operations correctly preserve running behavior
+       and booting behavior of smartd.
+
+  [BA] Improved formatting of ATA Error Log printout, and added
+       listing of names of commands that caused the error. Added
+       obsolete ATA-4 SMART feature commands to table, along with
+       obsolete SFF-8035i SMART feature command.
+
+  [PW] Added atacmdnames.[hc], which turn command register &
+       feature register pairs into ATA command names.
+
+  [BA] Added conveyance self-test.  Some code added for selective
+       self-tests, but #ifdefed out.
+
+  [BA] Modified smartd exit status and log levels.  If smartd is
+       "cleanly" terminated, for example with SIGTERM, then its
+       exit messages are now logged at LOG_INFO not LOG_CRIT
+
+  [BA] Added Attribute IDs  (Fujitsu) 0xCA - 0xCE.  This is decimal
+       202-206. Added -v switches for interpretation of Attributes
+       192, 198 and 201. 
+
+  [BA] Made smartmontools work with any endian order machine for:
+       - SMART selftest log
+       - SMART ATA error log
+       - SMART Attributes values
+       - SMART Attributes thesholds
+       - IDENTIFY DEVICE information
+       - LOG DIRECTORY
+       Smartmontools is now free of endian bias and works correctly
+       on both little- and big-endian hardware.  This has been tested by
+       three independent PPC users on a variety of ATA and SCSI hardware.
+
+  [DG] Check that certain SCSI command responses are well formed. If
+       IEC mode page response is not well formed exit smartctl. This
+       is to protect aacraid. smartd should ignore a aacraid device.
+
+smartmontools-5.1-14
+
+  [BA] smartctl: added column to -A output to show if Attributes are
+       updated only during off-line testing or also during normal
+       operation.
+
+smartmontools-5.1-13
+
+  [BA] smartd: attempt to enable/disable automatic offline testing even
+       if the disk appears not to support it.  Now the same logic
+       as smartctl.
+
+  [BA] Added definition of Attribute 201, soft read error rate.
+
+  [BA] Added IBM/Hitachi IC35L120AVV207-1 (GXP-180) and corresponding
+       8MB Cache GXP-120 to drive database.
+
+  [BA] smartd: if DEVICESCAN Directive used in smartd.conf, and
+       -I, -R or -r Directives used in conjunction with this, got
+       segv errors.  Fixed by correcting memory allocation calls.
+
+  [BA] smartd: enable automatic offline testing was broken due
+       to cut-and-paste error that disabled it instead of
+       enabling it.  Thanks to Maciej W. Rozycki for pointing
+       out the problem and solution.
+
+  [BA] Fixed "spelling" of some Attribute names to replace spaces
+       in names by underscores. (Fixed field width easier for awk
+       style parsing.)
+
+  [BA,GF] Added mods submitted by [GF] to support Attribute 193 being
+       load/unload cycles. Add -v 193,loadunload option, useful for
+       Hitachi drive DK23EA-30, and add this drive to knowndrive.c
+       Add meaning of attribute 250 : Read error retry rate
+
+smartmontools-5.1-12
+
+  [BA] Added another entry for Samsung drives to knowndrive table.
+
+  [DG] Refine SCSI log sense command to do a double fetch in most cases
+       (but not for the TapeAlert log page). Fix TapeAlert and Self Test
+       log page response truncation.
+
+  [PW] Added 'removable' argument to -d Directive for smartd.  This indicates
+       that smartd should continue (rather than exit) if the device does not 
+       appear to be present.
+
+  [BA] Modified smartmontools.spec [Man pages location] and
+       smartd.initd [Extra space kills chkconfig!] for Redhat 6.x
+       compatibility (thanks to Gerald Schnabel).
+
+smartmontools-5.1-11
+
+  [EB] Add another Fujitsu disk to knowndrives.c
+
+  [GG] match for scsi/ and ide/ in case of devfs to exclude false postives
+
+  [BA] If SCSI device listed in /etc/smartd.conf fails to open or do
+       SMART stuff correctly, or not enough space
+       to list all SCSI devices, fail with error unless
+       -DSCSIDEVELOPMENT set during compile-time.
+
+  [BA] Added automatic recognition of /dev/i* (example: /dev/ide/...)
+       as an ATA device.
+
+  [DG] Add "Device type: [disk | tape | medium changer | ...] line to
+       smartctl -i output for SCSI devices.
+
+  [PW] Fixed bug in smartd where test email would be sent regularly (for
+       example, daily if the user had specified -M daily) instead of just
+       once on startup.
+
+  [KM] More TapeAlert work. Added translations for media changer
+       alerts. TapeAlert support reported according to the log page
+       presence. ModeSense not attempted for non-ready tapes (all
+       drives do not support this after all). Get peripheral type from
+       Inquiry even if drive info is not printed. Add QUIETON()
+       QUIETOFF() to TapeAlert log check.
+
+  [BA] Stupid bug in atacmds.c minor_str[] affected ataVersionInfo().
+       Two missing commas meant that minor_str[] had two few elements,
+       leading to output like this:
+       Device Model:     Maxtor 6Y120L0
+       Serial Number:    Y40BF74E
+       Firmware Version: YAR41VW0
+       Device is:        Not in smartctl database [for details use: -P showall]
+       ATA Version is:   7
+       ATA Standard is:  9,minutes
+                         ^^^^^^^^^
+       Missing commas inserted.
+
+  [BA] Fixed smartd bug.  On device registration, if ATA device did
+       not support SMART error or self-test logs but user had asked to
+       monitor them, an attempt would be made to read them anyway,
+       possibly generating "Drive Seek" errors.  We now check that
+       the self-test and error logs are supported before trying to
+       access them the first time.
+
+  [GG/BA] Fixed bug where if SMART ATA error log not supported,
+       command was tried anyway. Changed some error printing to use
+       print handlers.
+
+  [GG] Makefile modifications to ease packaging
+
+  [DG] Did work for TapeAlerts (SCSI). Now can detect /dev/nst0 as a
+       SCSI device. Also open SCSI devices O_NONBLOCK so they don't
+       hang on open awaiting media. The ATA side should worry about
+       this also: during a DEVICESCAN a cd/dvd device without media
+       will hang. Added some TapeAlert code suggested by Kai Makisara.
+
+smartmontools-5.1-10
+
+  [PW] Extended the -F option/Directive to potentially fix other firmware
+       bugs in addition to the Samsung byte-order bug.  Long option name is
+       now --firmwarebug and the option/Directive accepts an argument
+       indicating the type of firmware bug to fix.
+
+  [BA] Fixed a bug that prevented the enable automatic off-line
+       test feature from enabling.  It also prevented the enable Attribute
+       autosave from working.  See CVS entry for additional details.
+
+  [PW] Modified the -r/--report option (smartctl and smartd) to allow the
+       user to specify the debug level as a positive integer.
+
+  [BA] Added --log directory option to smartctl.  If the disk
+       supports the general-purpose logging feature set (ATA-6/7)
+       then this option enables the Log Directory to be printed.
+       This Log Directory shows which device logs are available, and
+       their lengths in sectors.
+
+  [PW] Added -P/--presets option to smartctl and -P Directive to smartd.
+
+  [GG] Introduce different exit codes indicating the type of problem
+       encountered for smartd.
+
+  [DG] Add non-medium error count to '-l error' and extended self test
+       duration to '-l selftest'. Get scsi IEs and temperature changes
+       working in smartd. Step over various scsi disk problems rather
+       than abort smartd startup.
+
+  [DG] Support -l error for SCSI disks (and tapes). Output error counter
+       log pages.
+
+  [BA] Added -F/--fixbyteorder option to smartctl.  This allows us to read
+       SMART data from some disks that have byte-reversed two- and four-
+       byte quantities in their SMART data structures.
+
+  [BA] Fixed serious bug: the -v options in smartd.conf were all put
+       together and used together, not drive-by-drive.
+
+  [PW] Added knowndrives.h and knowndrives.c.  The knowndrives array
+       supersedes the drivewarnings array.
+
+  [GG] add {-p,--pidfile} option to smartd to write a PID file on
+       startup. Update the manpage accordingly.
+
+  [DG] Fix scsi smartd problem detecting SMART support. More cleaning
+       and fix (and rename) scsiTestUnitReady(). More scsi renaming.
+
+  [BA] Fixed smartd so that if a disk that is explictily listed is not
+       found, then smartd will exit with nonzero status BEFORE forking.
+       If a disk can't be registered, this will also be detected before
+       forking, so that init scripts can react correctly.
+
+  [BA] Replaced all linux-specific ioctl() calls in atacmds.c with
+       a generic handler smartcommandhandler().  Now the only routine
+       that needs to be implemented for a given OS is os_specific_handler().
+       Also implemented the --report ataioctl. This provides 
+       two levels of reporting.  Using the option once gives a summary
+       report of device IOCTL transactions.  Using the option twice give
+       additional info (a printout of ALL device raw 512 byte SMART
+       data structures).  This is useful for debugging.
+
+  [DG] more scsi cleanup. Output scsi device serial number (VPD page
+       0x80) if available as part of '-i'. Implement '-t offline' as
+       default self test (only self test older disks support).
+
+  [BA] Changed crit to info in loglevel of smartd complaint to syslog
+       if DEVICESCAN enabled and device not found.
+
+  [BA] Added -v 194,10xCelsius option/Directive. Raw Attribute number
+       194 is ten times the disk temperature in Celsius.
+
+  [DG] scsicmds.[hc] + scsiprint.c: clean up indentation, remove tabs.
+       Introduce new intermediate interface based on "struct scsi_cmnd_io"
+       to isolate SCSI generic commands + responses from Linux details;
+       should help port to FreeBSD of SCSI part of smartmontools.
+       Make SCSI command builders more parametric.
+
+smartmontools-5.1-9
+  
+  [BA] smartctl: if HDIO_DRIVE_TASK ioctl() is not implemented (no
+       kernel support, then try to assess drive health by examining
+       Attribute values/thresholds directly.
+
+  [BA] smartd/smartctl: added -v 200,writeerrorcount option/Directive
+       for Fujitsu disks.
+
+  [BA] smartd: Now send email if any of the SMART commands fails,
+       or if open()ing the device fails.  This is often noted
+       as a common disk failure mode.
+
+  [BA] smartd/smartctl: Added -v N,raw8 -v N,raw16 and -v N,raw48
+       Directives/Options for printing Raw Attributes in different
+       Formats.
+
+  [BA] smartd: Added -r ID and -R ID for reporting/tracking Raw
+       values of Attributes.
+
+  [BA] smartd/smartctl: Changed printing of spin-up-time attribute
+       raw value to reflect current/average as per IBM standard.
+
+  [BA] smartd/smartctl: Added -v 9,seconds option for disks which
+       use Attribute 9 for power-on lifetime in seconds.
+
+  [BA] smartctl: Added a warning message so that users of some IBM
+       disks are warned to update their firmware.  Note: we may want
+       to add a command-line flag to disable the warning messages.
+       I have done this in a general way, using regexp, so that we
+       can add warnings about any type of disk that we wish...
+
+smartmontools-5.1-7
+
+  [BA] smartd: Created a subdirectory examplescripts/ of source
+       directory that contains executable scripts for the -M exec PATH
+       Directive of smartd.
+
+smartmontools-5.1-5
+
+  [BA] smartd: DEVICESCAN in /etc/smartd.conf
+       can now be followed by all the same Directives as a regular
+       device name like /dev/hda takes.  This allows one to use
+       (for example):
+       DEVICESCAN -m root@example.com
+       in the /etc/smartd.conf file.
+
+  [BA] smartd: Added -c (--checkonce) command-line option. This checks
+       all devices once, then exits.  The exit status can be
+       used to learn if devices were detected, and if smartd is
+       functioning correctly. This is primarily for Distribution
+       scripters.
+
+  [BA] smartd: Implemented -M exec Directive for
+       smartd.conf.  This makes it possible to run an
+       arbitrary script or mailing program with the
+       -m option.
+
+  [PW] smartd: Modified -M Directive so that it can be given
+       multiple times.  Added -M exec Directive.
+
+smartmontools-5.1-4
+
+  [BA] Fixed bug in smartctl pointed out by Pierre Gentile.
+       -d scsi didn't work because tryata and tryscsi were
+       reversed -- now works on /devfs SCSI devices.
+
+  [BA] Fixed bug in smartctl pointed out by Gregory Goddard
+       <ggoddard@ufl.edu>.  Manual says that bit 6 of return
+       value turned on if errors found in smart error log.  But
+       this wasn't implemented.
+
+smartmontools-5.1-3
+
+  [BA] Modified printing format for 9,minutes to read
+       Xh+Ym not X h + Y m, so that fields are fixed width.
+
+  [BA] Added Attribute 240 "head flying hours"
+
+smartmontools-5.1.1
+
+  [BA] As requested, local time/date now printed by smartctl -i
+
+  [PW] Added "help" argument to -v for smartctl
+
+  [PW] Added -D, --showdirectives option to smartd
+
+  [DG] add '-l selftest' capability for SCSI devices (update smartctl.8)
+
+  [BA] smartd,smartctl: added additional Attribute modification option
+       -v 220,temp and -v 9,temp.
+
+  [PW] Renamed smartd option -X to -d
+
+START OF SMARTMONTOOLS 5.1 series
+
+smartmontools-5.0.50
+
+  [PW] Changed smartd.conf Directives -- see man page
+
+  [BA/DG] Fixed uncommented comment in smartd.conf
+
+  [DG] Correct 'Recommended start stop count' for SCSI devices
+
+  [PW] Replaced smartd.conf directive -C with smartd option -i
+
+  [PW] Changed options for smartctl -- see man page.
+
+  [BA] Use strerror() to generate system call error messages.
+
+  [BA] smartd: fflush() all open streams before fork().
+
+  [BA] smartctl, smartd simplified internal handling of checksums
+  for simpler porting and less code.
+
+smartmontools-5.0.49
+
+  [PW] smartd --debugmode changed to --debug
+
+  [BA] smartd/smartctl added attribute 230 Head Amplitude from
+  IBM DPTA-353750.
+
+  [PW] Added list of proposed new options for smartctl to README.
+
+  [PW] smartd: ParseOpts() now uses getopt_long() if HAVE_GETOPT_LONG is
+  defined and uses getopt() otherwise.  This is controlled by CPPFLAGS in
+  the Makefile.
+
+  [BA] smartd: Fixed a couple of error messages done with perror()
+  to redirect them as needed.
+
+smartmontools-5.0.48
+
+  [BA] smartctl: The -O option to enable an Immediate off-line test
+  did not print out the correct time that the test would take to
+  complete.  This is because the test timer is volatile and not
+  fixed.  This has been fixed, and the smartctl.8 man page has been
+  updated to explain how to track the Immediate offline test as it
+  progresses, and to further emphasize the differences between the
+  off-line immediate test and the self-tests.
+
+  [BA] smartd/smartctl: Added new attribute (200) Multi_Zone_Error_Rate
+
+  [BA] smartctl: modified so that arguments could have either a single -
+  as in -ea or multiple ones as in -e -a.  Improved warning message for
+  device not opened, and fixed error in redirection of error output of
+  HD identity command.
+
+  [PW] smartd: added support for long options.  All short options are still
+  supported; see manpage for available long options.
+
+  [BA] smartctl.  When raw Attribute value was 2^31 or larger, did
+  not print correctly.
+
+smartmontools-5.0.46
+
+  [BA] smartd: added smartd.conf Directives -T and -s.  The -T Directive
+  enables/disables Automatic Offline Testing.  The -s Directive
+  enables/disables Attribute Autosave. Documentation and
+  example configuration file updated to agree.
+
+  [BA] smartd: user can make smartd check the disks at any time
+  (ie, interrupt sleep) by sending signal SIGUSR1 to smartd.  This
+  can be done for example with:
+  kill -USR1 <pid>
+  where <pid> is the process ID number of smartd.
+
+  [EB] scsi: don't trust the data we receive from the drive too
+  much. It very well might have errors (like zero response length).
+  Seen on Megaraid logical drive, and verified in the driver source.
+
+  [BA] smartd: added Directive -m for sending test email and
+  for modifying email reminder behavior.  Updated manual, and sample
+  configuration file to illustrate & explain this.
+
+  [BA] smartd: increased size of a continued smartd.conf line to
+  1023 characters.
+
+  [BA] Simplified Directive parsers and improved warning/error
+  messages.
+
+smartmontools-5.0.45
+
+  [EB] Fixed bug in smartd where testunitready logic inverted
+  prevented functioning on scsi devices.
+  The bug in question only affects smartd users with scsi devices.
+  To see if your version of smartd has the testunitready() bug, do
+     smartd -V
+  If the version of the module smartd.c in a line like:
+     Module: smartd.c      revision: 1.66   date: 2002/11/17
+  has a revision greater than or equal to 1.30, and less than or equal to
+  1.64, then your version of the code has this problem.
+  This problem affected releases starting with RELEASE_5_0_16 up to and
+  including RELEASE_5_0_43.
+
+  [BA] Added testunitnotready to smartctl for symmetry with smartd.
+
+  [SB] added Czech descriptions to .spec file
+  [SB]  corrected comment in smartd.conf example
+
+  [BA] Changed way that entries in the ATA error log are printed,
+  to make it clearer which is the most recent error and
+  which is the oldest one.
+
+  NOTE: All changes made prior to this point were done by Bruce Allen
+  [BA] although several of them had been suggested by earlier postings
+  by Stanislav Brabec [SB].
+
+smartmontools-5.0.43
+
+  Changed Temperature_Centigrade to Temperature_Celsius.
+  The term "Centigrade" ceased to exist in 1948.  (c.f
+  http://www.bartleby.com/64/C004/016.html).
+
+smartmontools-5.0.42
+
+  Modified SCSI device check to also send warning emails if
+  requested in directives file.
+
+  Added a new smartd configuration file Directive: -M ADDRESS.
+  This sends a single warning email to ADDRESS for failures or
+  errors detected with the -c, -L, -l, or -f Directives.
+
+smartmontools-5.0.38
+
+  Modified perror() statements in atacmds.c so that printout for SMART
+  commands errors is properly suppressed or queued depending upon users
+  choices for error reporting modes.
+
+  Added Italian descriptions to smartmontools.spec file.
+
+  Started impementing send-mail-on-error for smartd; not yet enabled.
+
+  Added -P (Permissive) Directive to smartd.conf file to allow SMART
+  monitoring of pre-ATA-3 Rev 4 disks that have SMART but do not have
+  a SMART capability bit.
+  Removed charset encodings from smartmontools.spec file for non-English
+  fields.
+
+smartmontools-5.0.32
+
+  Added manual page smartd.conf.5 for configuration file.
+
+  smartctl: Missing ANSI prototype in failuretest(); fixed.
+
+  smartctl: Checksum warnings now printed on stdout, or are silent,
+  depending upon -q and -Q settings.
+
+smartmontools-5.0.31
+
+  Changed Makefile so that the -V option does not reflect file state
+  before commit!
+
+  smartctl: added new options -W, -U, and -P to control if and how the
+  smartctl exits if an error is detected in either a SMART data
+  structure checksum, or a SMART command returns an error.
+
+  modified manual page to break options into slightly more logical
+  categories.
+
+  reformatted 'usage' message order to agree with man page ordering
+
+  modified .spec file so that locale information now contains
+  character set definition.   Changed pt_BR to pt since we do not use any
+  aspect other than language.  See man setlocale.
+
+smartmontools-5.0.30
+  smartctl: added new options -n and -N to force device to be ATA or SCSI
+  smartctl: no longer dies silently if device path does not start/dev/X
+  smartctl: now handles arbitrary device paths
+
+smartmontools-5.0.29
+  Modified .spec file and Makefile to make them more compliant with
+  the "right" way of doing things.
+
+smartmontools-5.0.26
+  Fixed typesetting error in man page smartd.8
+
+  Removed redundant variable (harmless) from smartd.c
+
+smartmontools-5.0.25
+
+  Added a new directive for the configuration file.  If the word
+  DEVICESCAN appears before any non-commented material in the
+  configuration file, then the confi file will be ignored and the
+  devices wil be scanned.
+
+smartmontools-5.0.24
+
+    Note: it has now been confirmed that the code modifications between
+    5.0.23 and 5.0.24 have eliminated the GCC 3.2 problems.  Note that
+    there is a GCC bug howerver, see #8404 at
+    http://gcc.gnu.org/cgi-bin/gnatsweb.pl?database=gcc&cmd=query
+    http://gcc.gnu.org/bugzilla/show_bug.cgi?id=8404
+
+      Added new Directive for Configuration file:
+      -C <N> This sets the time in between disk checks to be <N>
+      seconds apart.  Note that  although  you  can  give
+       this Directive multiple times on different lines of
+       the configuration file, only the final  value  that
+       is  given  has  an  effect,  and applies to all the
+       disks.  The default value of <N> is 1800  sec,  and
+       the minimum allowed value is ten seconds.
+
+    Problem wasn't the print format. F.L.W. Meunier <0@pervalidus.net>
+    sent me a gcc 3.2 build and I ran it under a debugger.  The
+    problem seems to be with passing the very large (2x512+4) byte
+    data structures as arguments.  I never liked this anyway; it was
+    inherited from smartsuite.  So I've changed all the heavyweight
+    functions (ATA ones, anyone) to just passing pointers, not hideous
+    kB size structures on the stack.  Hopefully this will now build OK
+    under gcc 3.2 with any sensible compilation options.
+
+smartmontools-5.0.23
+
+    Because of reported problems with GCC 3.2 compile, I have gone
+    thorough the code and explicitly changed all print format
+    parameters to correspond EXACTLY to int unless they have to be
+    promoted to long longs.  To quote from the glibc bible: [From
+    GLIBC Manual: Since the prototype doesn't specify types for
+    optional arguments, in a call to a variadic function the default
+    argument promotions are performed on the optional argument
+    values. This means the objects of type char or short int (whether
+    signed or not) are promoted to either int or unsigned int, as
+    appropriate.]
+
+smartmontools-5.0.22
+
+    smartd, smartctl now warn if they find an attribute whose ID
+    number does not match between Data and Threshold structures.
+
+    Fixed nasty bug which led to wrong number of arguments for a
+    varargs statement, with attendent stack corruption.  Sheesh!
+    Have added script to CVS attic to help find such nasties in the
+    future.
+
+smartmontools-5.0.21
+
+    Eliminated some global variables out of header files and other
+    minor cleanup of smartd.
+
+smartmontools-5.0.20
+
+    Did some revision of the man page for smartd and made the usage
+    messages for Directives 100% consistent.
+
+smartmontools-5.0-19
+
+    smartd: prints warning message when it gets SIGHUP, saying that it
+    is NOT re-reading the config file.
+
+    smartctl: updated man page to say self-test commands -O,x,X,s,S,A
+    appear to be supported in the code.  [I can't test these,  can anyone
+    report?]
+
+smartmontools-5.0-18
+
+    smartctl: smartctl would previously print the LBA of a self-test
+    if it completed, and the LBA was not 0 or 0xff...f However
+    according to the specs this is not correct.  According to the
+    specs, if the self-test completed without error then LBA is
+    undefined.  This version fixes that.  LBA value only printed if
+    self-test encountered an error.
+
+smartmontools-5.0-17
+
+    smartd has changed significantly. This is the first CVS checkin of
+    code that extends the options available for smartd.  The following
+    options can be placed into the /etc/smartd.conf file, and control the
+    behavior of smartd.
+    Configuration file Directives (following device name):
+    -A     Device is an ATA device
+    -S     Device is a SCSI device
+    -c     Monitor SMART Health Status
+    -l     Monitor SMART Error Log for changes
+    -L     Monitor SMART Self-Test Log for new errors
+    -f     Monitor for failure of any 'Usage' Attributes
+    -p     Report changes in 'Prefailure' Attributes
+    -u     Report changes in 'Usage' Attributes
+    -t     Equivalent to -p and -u Directives
+    -a     Equivalent to -c -l -L -f -t Directives
+    -i ID  Ignore Attribute ID for -f Directive
+    -I ID  Ignore Attribute ID for -p, -u or -t Directive
+    #      Comment: text after a hash sign is ignored
+    \      Line continuation character
+
+    cleaned up functions used for printing CVS IDs.  Now use string
+    library, as it should be.
+
+    modified length of device name string in smartd internal structure
+    to accomodate max length device name strings
+
+    removed un-implemented (-e = Email notification) option from
+    command line arg list.  We'll put it back on when implemeneted.
+
+    smartd now logs serious (fatal) conditions in its operation at
+    loglevel LOG_CRIT rather than LOG_INFO before exiting with error.
+
+    smartd used to open a file descriptor for each SMART enabled
+    device, and then keep it open the entire time smartd was running.
+    This meant that some commands, like IOREADBLKPART did not work,
+    since the fd to the device was open.  smartd now opens the device
+    when it needs to read values, then closes it.  Also, if one time
+    around it can't open the device, it simply prints a warning
+    message but does not give up.  Have eliminated the .fd field from
+    data structures -- no longer gets used.
+
+    smartd now opens SCSI devices as well using O_RDONLY rather than
+    O_RDWR.  If someone can no longer monitor a SCSI device that used
+    to be readable, this may well be the reason why.
+
+    smartd never checked if the number of ata or scsi devices detected
+    was greater than the max number it could monitor.  Now it does.
+
+smartmontools-5.0-16
+
+    smartd on startup now looks in the configuration file /etc/smartd.conf for
+    a list of devices which to include in its monitoring list.  See man page
+    (man smartd) for syntax.
+
+    smartd: close file descriptors of SCSI device if not SMART capable
+    Closes ALL file descriptors after forking to daemon.
+
+    added new temperature attribute (231, temperature)
+
+    smartd: now open ATA disks using O_RDONLY
+
+smartmontools-5.0-11
+
+    smartd now prints the name of a failed or changed attribute
+    into logfile, not just ID number
+
+    Changed name of -p (print version) option to -V
+
+    Minor change in philosophy: if a SMART command fails or the device
+    appears incapable of a SMART command that the user has asked for,
+    complain by printing an error message, but go ahead and try
+    anyway.  Since unimplemented SMART commands should just return an
+    error but not cause disk problems, this should't cause any
+    difficulty.
+
+    Added two new flags: q and Q.  q is quiet mode - only print: For
+    the -l option, errors recorded in the SMART error log; For the -L
+    option, errors recorded in the device self-test log; For the -c
+    SMART "disk failing" status or device attributes (pre-failure or
+    usage) which failed either now or in the past; For the -v option
+    device attributes (pre-failure or usage) which failed either now
+    or in the past.  Q is Very Quiet mode: Print no ouput.  The only
+    way to learn about what was found is to use the exit status of
+    smartctl.
+
+    smartctl now returns sensible values (bitmask).  See smartctl.h
+    for the values, and the man page for documentation.
+
+    The SMART status check now uses the correct ATA call.  If failure
+    is detected we search through attributes to list the failed ones.
+    If the SMART status check shows GOOD, we then look to see if their
+    are any usage attributes or prefail attributes have failed at any
+    time.  If so we print them.
+
+    Modified function that prints vendor attributes to say if the
+    attribute has currently failed or has ever failed.
+
+    -p option now prints out license info and CVS strings for all
+    modules in the code, nicely formatted.
+
+    Previous versions of this code (and Smartsuite) only generate
+    SMART failure errors if the value of an attribute is below the
+    threshold and the prefailure bit is set.  However the ATA Spec
+    (ATA4 <=Rev 4) says that it is a SMART failure if the value of an
+    attribute is LESS THAN OR EQUAL to the threshold and the
+    prefailure bit is set.  This is now fixed in both smartctl and
+    smartd.  Note that this is a troubled subject -- the original
+    SFF 8035i specification defining SMART was inconsistent about
+    this.  One section says that Attribute==Threshold is pass,
+    and another section says it is fail.  However the ATA specs are
+    consistent and say Attribute==Threshold is a fail.
+
+    smartd did not print the correct value of any failing SMART attribute.  It
+    printed the index in the attribute table, not the attribute
+    ID. This is fixed.
+
+    when starting self-tests in captive mode ioctl returns EIO because
+    the drive has been busied out.  Detect this and don't return an eror
+    in this case.  Check this this is correct (or how to fix it?)
+    fixed possible error in how to determine ATA standard support
+    for devices with no ATA minor revision number.
+
+    device opened only in read-only not read-write mode.  Don't need R/W 
+    access to get smart data. Check this with Andre.
+
+    smartctl now handles all possible choices of "multiple options"
+    gracefully.  It goes through the following phases of operation,
+    in order: INFORMATION, ENABLE/DISABLE, DISPLAY DATA, RUN/ABORT TESTS.
+    Documentation has bee updated to explain the different phases of
+    operation.  Control flow through ataPrintMain()
+    simplified.
+
+    If reading device identity information fails, try seeing if the info
+    can be accessed using a "DEVICE PACKET" command.  This way we can
+    at least get device info.
+
+    Modified Makefile to automatically tag CVS archive on issuance of
+    a release
+
+    Modified drive detection so minor device ID code showing ATA-3 rev
+    0 (no SMART) is known to not be SMART capable.
+
+    Now verify the checksum of the device ID data structure, and of the
+    attributes threshold structure.  Before neither of these
+    structures had their checksums verified.
+
+    New behavior vis-a-vis checksums.  If they are wrong, we log
+    warning messages to stdout, stderr, and syslog, but carry on
+    anyway.  All functions now call a checksumwarning routine if the
+    checksum doesn't vanish as it should.
+
+    Changed Read Hard Disk Identity function to get fresh info from
+    the disk on each call rather than to use the values that were read
+    upon boot-up into the BIOS.  This is the biggest change in this
+    release.  The ioctl(device, HDIO_GET_IDENTITY, buf ) call should
+    be avoided in such code.  Note that if people get garbled strings
+    for the model, serial no and firmware versions of their drives,
+    then blame goes here (the BIOS does the byte swapping for you,
+    apparently!)
+    
+    Function ataSmartSupport now looks at correct bits in drive
+    identity structure to verify first that these bits are valid,
+    before using them.
+    
+    Function ataIsSmartEnabled() written which uses the Drive ID state
+    information to tell if SMART is enabled or not.  We'll carry this
+    along for the moment without using it.
+
+    Function ataDoesSmartWork() guaranteed to work if the device
+    supports SMART.
+
+    Replace some numbers by #define MACROS
+
+    Wrote Function TestTime to return test time associated with each
+    different type of test.
+
+    Thinking of the future, have added a new function called
+    ataSmartStatus2().  Eventually when I understand how to use the
+    TASKFILE API and am sure that this works correctly, it will
+    replace ataSmartStatus().  This queries the drive directly to
+    see if the SMART status is OK, rather than comparing thresholds to
+    attribute values ourselves. But I need to get some drives that fail
+    their SMART status to check it.
+
+
+smartmontools-5.0-10
+    Removed extraneous space before printing in some error messages
+    Fixed additional typos in documentation
+    Fixed some character buffers that were too short for their contents.
+
+smartmontools-5.0-9
+
+    Put project home path into all source files near the top
+    Corrected typos in the documentation
+    Modified Makefile so that Mandrake Cooker won't increment version number
+    (unless they happen to be working on my machine, which I doubt!)
+
+smartmontools-5.0-8:
+
+    For IBM disks whose raw temp data includes three temps. print all
+    three
+
+    print timestamps for error log to msec precision
+
+    added -m option for Hitachi disks that store power on life in
+    minutes
+
+    added -L option for printing self-test error logs
+
+    in -l option, now print power on lifetime, so that one can see
+    when the error took place
+
+    updated SMART structure definitions to ATA-5 spec
+
+    added -p option
+
+    added -f and -F options to enable/disable autosave threshold
+    parameters
+
+    changed argv parsing to use getops -- elminate buffer overflow
+    vulnerability
+
+    expanded and corrected documentation
+
+    fixed problem with smartd.  It did not actually call
+    ataSmartEnable()!  Since the argument was left out, the test
+    always suceeded because it evaluated to a pointer to the function.
+
+    smartd: closed open file descriptors if device does not support
+    smart. Note: this still needs to be fixed for SCSI devices
+
+
+smartmontools-5.0-0  STARTED with smartsuite-2.1-2
diff --git a/INSTALL b/INSTALL
index 1863c34f4f4831f2982030a1144c83b210517536..f63b04a32c14aa42376f6594152e2753d80c9bc6 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,7 +1,7 @@
 Smartmontools installation instructions
 =======================================
 
-$Id: INSTALL 3555 2012-06-01 21:07:33Z chrfranke $
+$Id: INSTALL 3713 2012-11-23 21:26:17Z chrfranke $
 
 Please also see the smartmontools home page:
 http://smartmontools.sourceforge.net/
@@ -97,7 +97,7 @@ Table of contents:
 
     E) Cygwin
 
-    The code was tested on Cygwin 1.7.7-1. It should also work on other
+    The code was tested on Cygwin 1.7.15-1.  It should also work on other
     recent releases.
 
     Both Cygwin and Windows versions of smartmontools share the same code
@@ -106,40 +106,14 @@ Table of contents:
 
     F) Windows
 
-    The code was tested on Windows 98SE, ME, NT4(SP5,SP6), 2000(SP4),
-    XP(up to SP3), 2003, Vista and Windows 7.
-
-    -- Windows 9x/ME
-
-    On 9x/ME, only standard (legacy) IDE/ATA devices 0-3 are supported.
-    The driver SMARTVSD.VXD must be present in WINDOWS\SYSTEM\IOSUBSYS
-    to get loaded at Windows startup. The default location in a new
-    installation of some versions of Windows is the WINDOWS\SYSTEM folder.
-    In this case, move SMARTVSD.VXD to WINDOWS\SYSTEM\IOSUBSYS and reboot
-    (http://support.microsoft.com/kb/265854/en-us).
-
-    SMARTVSD.VXD relies on the standard IDE port driver ESDI_506.PDR.
-    If the system uses a vendor specific driver, access of SMART data
-    is not possible.
-
-    Some ATA controllers (e.g. Promise) provided a custom SMARTVSD.VXD
-    for their Win9x/ME driver. To access SMART data from both the legacy
-    (/dev/h[a-d]) and this additional (/dev/hd[e-h]) controller, rename
-    this file to SMARTVSE.VXD. Open the file with a hex editor and replace
-    all occurrences of the string "SMARTVSD" with "SMARTVSE". Then reinstall
-    the original Windows SMARTVSD.VXD.
-
-    To access SCSI and USB devices, an installed ASPI interface (WNASPI32.DLL)
-    is required. The code was tested with Adaptec Windows ASPI drivers 4.71.2.
-    (http://www.adaptec.com/en-US/support/_eol/scsi_sw/ASPI-4.70/)
-    Links to other ASPI drivers can be found at http://www.nu2.nu/aspi/.
-
-    -- Windows NT4/2000/XP/2003/Vista/Win7
+    The code was tested on Windows XP SP3, 2003, Vista, Windows 7 and
+    Windows 8 Release Preview.  Support von Windows 9x/ME and NT4 was removed
+    after smartmontools 5.43.
 
     ATA or SATA devices are supported if the device driver implements
     the SMART IOCTLs or IOCTL_IDE_PASS_THROUGH or IOCTL_ATA_PASS_THROUGH.
-    The ATA SMART READ LOG command (smartctl -l, --log, -a, --all) is not
-    supported if only the SMART IOCTLs are implemented.
+    Only the latter provides full pass-through support which is needed
+    for all smartmontools features.
 
     SCSI and USB devices are accessed through SPTI. Special driver support
     is not required.
@@ -458,8 +432,6 @@ Cross-compile statically linked 64-bit version with MinGW-w64:
   Tested on Cygwin and Debian Linux with MinGW-w64 from
   http://mingw-w64.sourceforge.net/.
 
-WARNING: The smartmontools version for 64-bit Windows is still EXPERIMENTAL.
-
 Cross-compile on Cygwin with old gcc-mingw 3.x:
 
   ./configure --build=$(./config.guess) \
@@ -532,10 +504,9 @@ use the following on MSYS or Cygwin:
   ../configure [... any MinGW option set from above ...]
   make config-vc10
 
-  The MSVC project files (os_win32/smartmontools_vc10.sln,
-  os_win32/smart{ctl,d}_vc10.vcxproj) are included in SVN (but not in
-  source tarball). The target config-vc10 from a Makefile configured
-  for MinGW creates os_win32/{config,svnversion}_vc10.h from
+  The MSVC project files (os_win32/vc10/*) are included in SVN (but not
+  in source tarball). The target config-vc10 from a Makefile configured
+  for MinGW creates os_win32/vc10/{config,svnversion}.h from
   ./{config,svnversion}.h. The configure skript must be run outside
   of the source directory to avoid inclusion of the original config.h.
 
@@ -621,7 +592,7 @@ The following files are installed if ./configure has no options:
 /usr/local/share/man/man8/smartctl.8                    [Manual page]
 /usr/local/share/man/man8/smartd.8                      [Manual page]
 /usr/local/share/doc/smartmontools/AUTHORS              [Information about the authors and developers]
-/usr/local/share/doc/smartmontools/CHANGELOG            [A log of changes. Also see SVN]
+/usr/local/share/doc/smartmontools/ChangeLog            [A log of changes. Also see SVN]
 /usr/local/share/doc/smartmontools/COPYING              [GNU General Public License Version 2]
 /usr/local/share/doc/smartmontools/INSTALL              [Installation instructions: what you're reading!]
 /usr/local/share/doc/smartmontools/NEWS                 [Significant bugs discovered in old versions]
index d1055560fd12e2e576f19ba6e7899e4fad4034ed..25f625e58e9e7f33240f88d10cd16677b8305ac5 100644 (file)
@@ -1,11 +1,11 @@
 ## Process this file with automake to produce Makefile.in
 #
-# $Id: Makefile.am 3545 2012-05-25 21:19:03Z chrfranke $
+# $Id: Makefile.am 3759 2013-01-26 21:11:02Z chrfranke $
 #
 
 @SET_MAKE@
 
-ACLOCAL_AM_FLAGS = -I m4
+ACLOCAL_AMFLAGS = -I m4
 
 # Make sure .cpp takes precedence to avoid compiling old .c file
 SUFFIXES = .cpp .c .s .o
@@ -34,8 +34,9 @@ if NEED_REGEX
 AM_CPPFLAGS += -I$(srcdir)/regex
 endif
 
-sbin_PROGRAMS = smartd         \
-               smartctl
+sbin_PROGRAMS = \
+        smartctl \
+        smartd
 
 if ENABLE_DRIVEDB
 if OS_WIN32_MINGW
@@ -45,115 +46,136 @@ endif
 endif
 
 
-smartd_SOURCES =  smartd.cpp      \
-                  atacmdnames.cpp \
-                  atacmdnames.h   \
-                  atacmds.cpp     \
-                  atacmds.h       \
-                  dev_ata_cmd_set.cpp \
-                  dev_ata_cmd_set.h   \
-                  dev_interface.cpp   \
-                  dev_interface.h     \
-                  dev_tunnelled.h     \
-                  drivedb.h           \
-                  int64.h         \
-                  knowndrives.cpp \
-                  knowndrives.h   \
-                  scsicmds.cpp    \
-                  scsicmds.h      \
-                  scsiata.cpp     \
-                  utility.cpp     \
-                  utility.h
+smartctl_SOURCES = \
+        smartctl.cpp \
+        smartctl.h \
+        atacmdnames.cpp \
+        atacmdnames.h \
+        atacmds.cpp \
+        atacmds.h \
+        ataidentify.cpp \
+        ataidentify.h \
+        ataprint.cpp \
+        ataprint.h \
+        dev_ata_cmd_set.cpp \
+        dev_ata_cmd_set.h \
+        dev_interface.cpp \
+        dev_interface.h \
+        dev_tunnelled.h \
+        drivedb.h \
+        int64.h \
+        knowndrives.cpp \
+        knowndrives.h \
+        scsicmds.cpp \
+        scsicmds.h \
+        scsiata.cpp \
+        scsiprint.cpp \
+        scsiprint.h \
+        utility.cpp \
+        utility.h
+
+smartctl_LDADD = @os_deps@ @os_libs@
+smartctl_DEPENDENCIES = @os_deps@
+
+EXTRA_smartctl_SOURCES = \
+        os_darwin.cpp \
+        os_darwin.h \
+        os_linux.cpp \
+        os_linux.h \
+        os_freebsd.cpp \
+        os_freebsd.h \
+        os_netbsd.cpp \
+        os_netbsd.h \
+        os_openbsd.cpp \
+        os_openbsd.h \
+        os_qnxnto.cpp \
+        os_qnxnto.h \
+        os_solaris.cpp \
+        os_solaris.h \
+        os_solaris_ata.s \
+        os_win32.cpp \
+        os_generic.cpp \
+        os_generic.h \
+        cciss.cpp \
+        cciss.h \
+        cissio_freebsd.h \
+        dev_areca.cpp \
+        dev_areca.h \
+        dev_legacy.cpp \
+        megaraid.h
+
+if OS_WIN32_MINGW
+
+smartctl_LDADD        += smartctl_res.o
+smartctl_DEPENDENCIES += smartctl_res.o
+
+endif
+
+
+smartd_SOURCES = \
+        smartd.cpp \
+        atacmdnames.cpp \
+        atacmdnames.h \
+        atacmds.cpp \
+        atacmds.h \
+        dev_ata_cmd_set.cpp \
+        dev_ata_cmd_set.h \
+        dev_interface.cpp \
+        dev_interface.h \
+        dev_tunnelled.h \
+        drivedb.h \
+        int64.h \
+        knowndrives.cpp \
+        knowndrives.h \
+        scsicmds.cpp \
+        scsicmds.h \
+        scsiata.cpp \
+        utility.cpp \
+        utility.h
 
 smartd_LDADD = @os_deps@ @os_libs@ @CAPNG_LDADD@
 smartd_DEPENDENCIES = @os_deps@
 
-EXTRA_smartd_SOURCES = os_darwin.cpp    \
-                       os_darwin.h      \
-                       os_linux.cpp     \
-                       os_linux.h       \
-                       os_freebsd.cpp   \
-                       os_freebsd.h     \
-                       os_netbsd.cpp    \
-                       os_netbsd.h      \
-                       os_openbsd.cpp   \
-                       os_openbsd.h     \
-                       os_qnxnto.cpp    \
-                       os_qnxnto.h      \
-                       os_solaris.cpp   \
-                       os_solaris.h     \
-                       os_solaris_ata.s \
-                       os_win32.cpp     \
-                       os_generic.cpp   \
-                       os_generic.h     \
-                       cciss.cpp        \
-                       cciss.h          \
-                       cissio_freebsd.h \
-                       dev_legacy.cpp   \
-                       megaraid.h
-
+EXTRA_smartd_SOURCES = \
+        os_darwin.cpp \
+        os_darwin.h \
+        os_linux.cpp \
+        os_linux.h \
+        os_freebsd.cpp \
+        os_freebsd.h \
+        os_netbsd.cpp \
+        os_netbsd.h \
+        os_openbsd.cpp \
+        os_openbsd.h \
+        os_qnxnto.cpp \
+        os_qnxnto.h \
+        os_solaris.cpp \
+        os_solaris.h \
+        os_solaris_ata.s \
+        os_win32.cpp \
+        os_generic.cpp \
+        os_generic.h \
+        cciss.cpp \
+        cciss.h \
+        cissio_freebsd.h \
+        dev_areca.cpp \
+        dev_areca.h \
+        dev_legacy.cpp \
+        megaraid.h
 
 if OS_WIN32_MINGW
 
 smartd_SOURCES += \
         os_win32/daemon_win32.cpp \
         os_win32/daemon_win32.h \
-        os_win32/hostname_win32.cpp \
-        os_win32/hostname_win32.h \
         os_win32/syslog_win32.cpp \
         os_win32/syslog.h
 
-endif
-
-smartctl_SOURCES= smartctl.cpp    \
-                  smartctl.h      \
-                  atacmdnames.cpp \
-                  atacmdnames.h   \
-                  atacmds.cpp     \
-                  atacmds.h       \
-                  ataprint.cpp    \
-                  ataprint.h      \
-                  dev_ata_cmd_set.cpp \
-                  dev_ata_cmd_set.h   \
-                  dev_interface.cpp   \
-                  dev_interface.h     \
-                  dev_tunnelled.h     \
-                  drivedb.h           \
-                  int64.h         \
-                  knowndrives.cpp \
-                  knowndrives.h   \
-                  scsicmds.cpp    \
-                  scsicmds.h      \
-                  scsiata.cpp     \
-                  scsiprint.cpp   \
-                  scsiprint.h     \
-                  utility.cpp     \
-                  utility.h
-
+smartd_LDADD        += smartd_res.o
+smartd_DEPENDENCIES += smartd_res.o
 
-smartctl_LDADD = @os_deps@ @os_libs@
-smartctl_DEPENDENCIES = @os_deps@
+endif
 
-EXTRA_smartctl_SOURCES = os_linux.cpp \
-                       os_linux.h     \
-                       os_freebsd.cpp \
-                       os_freebsd.h   \
-                       os_netbsd.cpp  \
-                       os_netbsd.h    \
-                       os_openbsd.cpp \
-                       os_openbsd.h   \
-                       os_qnxnto.cpp  \
-                       os_qnxnto.h    \
-                       os_solaris.cpp \
-                       os_solaris.h   \
-                       os_win32.cpp   \
-                       os_generic.cpp \
-                       os_generic.h   \
-                       cciss.cpp      \
-                       cciss.h        \
-                       cissio_freebsd.h \
-                       dev_legacy.cpp \
-                       megaraid.h
 
 if NEED_GETOPT_LONG
 
@@ -270,15 +292,17 @@ man_MANS =        smartd.conf.5 \
 endif
 
 docsdir=$(docdir)
-docs_DATA = AUTHORS     \
-            CHANGELOG   \
-            COPYING     \
-            INSTALL     \
-            NEWS        \
-            README      \
-            TODO        \
-            WARNINGS    \
-            smartd.conf
+docs_DATA = \
+        AUTHORS \
+        ChangeLog \
+        ChangeLog-5.0-6.0 \
+        COPYING \
+        INSTALL \
+        NEWS \
+        README \
+        TODO \
+        WARNINGS \
+        smartd.conf
 
 examplesdir=$(exampledir)
 examples_DATA = \
@@ -321,6 +345,10 @@ uninstall-sysconfDATA:
        echo " rm -f $$f"; \
        rm -f "$$f"
 
+# automake does not allow 'sysconf_SCRIPTS'
+sysscriptdir = $(sysconfdir)
+sysscript_SCRIPTS = smartd_warning.sh
+
 EXTRA_DIST = \
         autogen.sh \
         smartd.initd.in \
@@ -330,6 +358,7 @@ EXTRA_DIST = \
         smartd.conf.5.in \
         smartd.conf \
         smartd.service.in \
+        smartd_warning.sh.in \
         update-smart-drivedb.in \
         m4/pkg.m4 \
         os_darwin/SMART.in \
@@ -339,10 +368,13 @@ EXTRA_DIST = \
         os_win32/runcmd.c \
         os_win32/runcmda.exe.manifest \
         os_win32/runcmdu.exe.manifest \
-        os_win32/syslogevt.c \
+        os_win32/smartctl_res.rc.in \
+        os_win32/smartd_res.rc.in \
+        os_win32/smartd_warning.cmd \
         os_win32/syslogevt.mc \
         os_win32/update-smart-drivedb.nsi \
         os_win32/wbemcli_small.h \
+        os_win32/wtssendmsg.c \
         $(docs_DATA) \
         $(examples_DATA) \
         $(examples_SCRIPTS)
@@ -363,6 +395,7 @@ CLEANFILES = \
         smartd.initd \
         smartd.freebsd.initd \
         smartd.service \
+        smartd_warning.sh \
         svnversion.h \
         update-smart-drivedb \
         SMART
@@ -386,7 +419,7 @@ utility.o: svnversion.h
 
 if IS_SVN_BUILD
 # Get version info from SVN
-svnversion.h: CHANGELOG Makefile $(svn_deps)
+svnversion.h: ChangeLog Makefile $(svn_deps)
        echo '/* svnversion.h.  Generated by Makefile from svn info.  */' > $@
        (cd $(srcdir) \
         && svnversion 2>/dev/null | sed -n 's,^\([0-9].*\),REV  "\1",p' \
@@ -396,9 +429,9 @@ svnversion.h: CHANGELOG Makefile $(svn_deps)
 else
 
 # SVN not available, guess version info from Id strings
-svnversion.h: CHANGELOG Makefile
+svnversion.h: ChangeLog Makefile
        echo '/* svnversion.h.  Generated by Makefile from Id strings.  */' > $@
-       (cd $(srcdir) && cat CHANGELOG Makefile.am configure.in smart*.in *.cpp *.h *.s) \
+       (cd $(srcdir) && cat ChangeLog Makefile.am configure.ac smart*.in *.cpp *.h *.s) \
        | sed -n 's,^.*\$$[I][d]: [^ ]* \([0-9][0-9]* [0-9][-0-9]* [0-9][:0-9]*\)[^:0-9][^$$]*\$$.*$$,\1,p' \
        | sort -n -r \
        | sed -n 'h;s,^\([^ ]*\) .*$$,REV  "\1",p;g;s,^[^ ]* \([^ ]*\) .*$$,DATE "\1",p;g;s,^[^ ]* [^ ]* \([^ ]*\)$$,TIME "\1",p;q' \
@@ -424,6 +457,9 @@ update-smart-drivedb: update-smart-drivedb.in config.status
        $(SHELL) ./config.status --file=$@
        chmod +x $@
 
+smartd_warning.sh: smartd_warning.sh.in config.status
+       $(SHELL) ./config.status --file=$@
+       chmod +x $@
 
 if INSTALL_INITSCRIPT
 if OS_DARWIN
@@ -494,8 +530,8 @@ systemdsystemunit_DATA = smartd.service
 endif
 
 smartd.service: smartd.service.in Makefile
-       sed "s|/usr/local/sbin/smartd|$(sbindir)/smartd|g; \
-            s|/usr/local/etc/sysconfig/smartmontools|$(sysconfdir)/sysconfig/smartmontools|g" \
+       sed -e 's|/usr/local/sbin/smartd|$(sbindir)/smartd|g' \
+           -e 's|/usr/local/etc/sysconfig/smartmontools|$(sysconfdir)/sysconfig/smartmontools|g' \
        $(srcdir)/smartd.service.in > $@
 
 if ENABLE_CAPABILITIES
@@ -523,17 +559,18 @@ MAN_ATTRIBUTELOG = sed '/^\.\\" %IF ENABLE_ATTRIBUTELOG/,/^\.\\" %ENDIF ENABLE_A
 endif
 
 MAN_FILTER = \
-    sed "s|CURRENT_SVN_VERSION|$(releaseversion)|g; \
-         s|CURRENT_SVN_DATE|`sed -n 's,^.*DATE[^"]*"\([^"]*\)".*$$,\1,p' svnversion.h`|g; \
-         s|CURRENT_SVN_REV|`sed -n 's,^.*REV[^"]*"\([^"]*\)".*$$,r\1,p' svnversion.h`|g; \
-         s|/usr/local/share/man/|$(mandir)/|g; \
-         s|/usr/local/sbin/|$(sbindir)/|g; \
-         s|/usr/local/etc/rc\\.d/init.d/|$(initddir)/|g; \
-         s|/usr/local/share/doc/smartmontools/examplescripts/|!exampledir!|g; \
-         s|/usr/local/share/doc/smartmontools/|$(docsdir)/|g; \
-         s|!exampledir!|$(exampledir)/|g; \
-         s|/usr/local/etc/smartd\\.conf|$(sysconfdir)/smartd.conf|g; \
-         s|/usr/local/etc/smart_drivedb\\.h|$(sysconfdir)/smart_drivedb\\.h|g" | \
+    sed -e 's|CURRENT_SVN_VERSION|$(releaseversion)|g' \
+        -e "s|CURRENT_SVN_DATE|`sed -n 's,^.*DATE[^"]*"\([^"]*\)".*$$,\1,p' svnversion.h`|g" \
+        -e "s|CURRENT_SVN_REV|`sed -n 's,^.*REV[^"]*"\([^"]*\)".*$$,r\1,p' svnversion.h`|g" \
+        -e 's|/usr/local/share/man/|$(mandir)/|g' \
+        -e 's|/usr/local/sbin/|$(sbindir)/|g' \
+        -e 's|/usr/local/etc/rc\.d/init.d/|$(initddir)/|g' \
+        -e 's|/usr/local/share/doc/smartmontools/examplescripts/|!exampledir!|g' \
+        -e 's|/usr/local/share/doc/smartmontools/|$(docsdir)/|g' \
+        -e 's|!exampledir!|$(exampledir)/|g' \
+        -e 's|/usr/local/etc/smartd\.conf|$(sysconfdir)/smartd.conf|g' \
+        -e 's|/usr/local/etc/smartd_warning\.|$(sysconfdir)/smartd_warning.|g' \
+        -e 's|/usr/local/etc/smart_drivedb\.h|$(sysconfdir)/smart_drivedb.h|g' | \
     $(MAN_ATTRIBUTELOG) | \
     $(MAN_CAPABILITIES) | \
     $(MAN_DRIVEDB) | \
@@ -567,11 +604,11 @@ MAN2HTML = man2html
 MAN2TXT = groff -man -Tascii -P'-bcou'
 
 # Remove HTTP header and fix links in man2html output
-FIXHTML = sed '1s,^Content-type.*,,' \
-        | sed 's,<A HREF="http://[-a-z/]*/man2html?\([1-8]\)+\(smart[cd][.a-z]*\)">,<A HREF="\2.\1.html">,g' \
-        | sed 's,<A HREF="http://[-a-z/]*/man2html">,<A HREF=".">,g' \
-        | sed 's,<A HREF="http://[-a-z/]*/man2html?[^"]*">\([^<]*\)</A>,\1,g' \
-        | sed 's,<A HREF="mailto:[^s][^m][^a][^"]*">\([^<]*\)</A>,\1,g'
+FIXHTML = sed -e '1s,^Content-type.*,,' \
+              -e 's,<A HREF="[^"]*/man2html?\([1-8]\)+\(smart[cd][.a-z]*\)">,<A HREF="\2.\1.html">,g' \
+              -e 's,<A HREF="[^"]*/man2html">,<A HREF=".">,g' \
+              -e 's,<A HREF="[^"]*/man2html?[^"]*">\([^<]*\)</A>,\1,g' \
+              -e 's,<A HREF="mailto:[^s][^m][^a][^"]*">\([^<]*\)</A>,\1,g'
 
 # Convert man pages into .html and .txt
 
@@ -612,6 +649,30 @@ check:
 
 
 if OS_WIN32_MINGW
+# Windows resources
+
+smartctl_res.o: smartctl_res.rc
+       $(WINDRES) $< $@
+
+smartd_res.o: smartd_res.rc syslogevt.rc
+       $(WINDRES) -I. $< $@
+
+# Convert version for VERSIONINFO resource: 6.1 r3754 -> 6.1.0.3754
+WIN_RC_FILTER = \
+    ( ver=`echo '$(PACKAGE_VERSION).0' | sed -n 's,^\([0-9]*\.[0-9]*\.[0-9]*\).*$$,\1,p'`; \
+      rev=`sed -n 's,^.*REV[^"]*"\([0-9]*\).*$$,\1,p' svnversion.h`; \
+      txtver="$${ver:-0.0.0}.$${rev:-0}"; binver=`echo "$$txtver" | sed 's|\.|,|g'`; \
+      sed -e "s|@BINARY_VERSION@|$$binver|g" -e "s|@TEXT_VERSION@|$$txtver|g"; )
+
+smartctl_res.rc: os_win32/smartctl_res.rc.in Makefile svnversion.h
+       cat $< | $(WIN_RC_FILTER) > $@
+
+smartd_res.rc: os_win32/smartd_res.rc.in Makefile svnversion.h
+       cat $< | $(WIN_RC_FILTER) > $@
+
+syslogevt.rc: os_win32/syslogevt.mc
+       $(WINDMC) -b $<
+
 # Definitions for Windows distribution
 
 if OS_WIN64
@@ -631,13 +692,10 @@ EXEFILES_WIN32 = \
         $(exedir_win32)/smartctl.exe \
         $(exedir_win32)/smartctl-nc.exe \
         $(exedir_win32)/smartd.exe \
+        $(exedir_win32)/smartd_warning.cmd \
         $(exedir_win32)/runcmda.exe \
-        $(exedir_win32)/runcmdu.exe
-
-if OS_WIN32_WINDMC
-EXEFILES_WIN32 += \
-        $(exedir_win32)/syslogevt.exe
-endif
+        $(exedir_win32)/runcmdu.exe \
+        $(exedir_win32)/wtssendmsg.exe
 
 if ENABLE_DRIVEDB
 if OS_WIN32_NSIS
@@ -649,7 +707,8 @@ endif
 FILES_WIN32 = \
         $(EXEFILES_WIN32) \
         $(docdir_win32)/AUTHORS.txt \
-        $(docdir_win32)/CHANGELOG.txt \
+        $(docdir_win32)/ChangeLog.txt \
+        $(docdir_win32)/ChangeLog-5.0-6.0.txt \
         $(docdir_win32)/COPYING.txt \
         $(docdir_win32)/INSTALL.txt \
         $(docdir_win32)/NEWS.txt \
@@ -676,8 +735,11 @@ CLEANFILES += \
         $(FILES_WIN32) \
         runcmdu.exe \
         smartctl-nc.exe smartctl-nc.exe.tmp \
-        syslogevt.exe syslogevt.h syslogevt.o \
-        syslogevt.res.o syslogevt.rc syslogevt_*.bin \
+        smartctl_res.rc smartctl_res.o \
+        smartd_res.rc smartd_res.o \
+        syslogevt.h syslogevt.o \
+        syslogevt.rc syslogevt_*.bin \
+        wtssendmsg.exe \
         update-smart-drivedb.exe \
         distdir.mkdir
 
@@ -758,6 +820,10 @@ $(exedir_win32)/%.exe.manifest: $(srcdir)/os_win32/%.exe.manifest
        $(UNIX2DOS) < $< > $@
        touch -r $< $@
 
+$(exedir_win32)/%.cmd: $(srcdir)/os_win32/%.cmd
+       $(UNIX2DOS) < $< > $@
+       touch -r $< $@
+
 $(docdir_win32)/%.html: %.html
        $(UNIX2DOS) < $< > $@
        touch -r $< $@
@@ -794,36 +860,32 @@ smartctl-nc.exe: smartctl.exe
          else echo "EXE patch failed"; exit 1; fi
        mv -f $@.tmp $@
 
-# Build runcmd?.exe
+# Build runcmd?.exe and wtssendmsg.exe
 runcmdu.exe: os_win32/runcmd.c
        $(CC) -Os -o $@ $<
 
-if OS_WIN32_WINDMC
-# Build syslogevt.exe event message file tool
-
-syslogevt.exe: syslogevt.o syslogevt.res.o
-       $(LINK) $^
+wtssendmsg.exe: os_win32/wtssendmsg.c
+       $(CC) -Os -o $@ $< -lwtsapi32
 
-syslogevt.o: os_win32/syslogevt.c syslogevt.rc
-       $(CC) -c -I. -Os -o $@ $<
+# Build os_win32/vc10/{config.h,smart*.rc,svnversion.h} for MSVC10 from MinGW files
 
-syslogevt.res.o: syslogevt.rc
-       $(WINDRES) $< $@
-
-syslogevt.rc: os_win32/syslogevt.mc
-       $(WINDMC) -b $<
-endif
-
-# Build {config,svnversion}_vc10.h for MSVC10 from MinGW {config,svnversion}.h
+config-vc10: $(srcdir)/os_win32/vc10/config.h \
+             $(srcdir)/os_win32/vc10/smartctl_res.rc \
+             $(srcdir)/os_win32/vc10/smartd_res.rc \
+             $(srcdir)/os_win32/vc10/svnversion.h
 
-config-vc10: $(srcdir)/os_win32/config_vc10.h  $(srcdir)/os_win32/svnversion_vc10.h
-
-$(srcdir)/os_win32/config_vc10.h: config.h Makefile
-       sed -e '1i/* config_vc10.h.  Generated from config.h by Makefile.  */' \
+$(srcdir)/os_win32/vc10/config.h: config.h Makefile
+       sed -e '1i/* os_win32/vc10/config.h.  Generated from config.h by Makefile.  */' \
            -e 's,^#define HAVE_\(ATTR_PACKED\|GETTIMEOFDAY\|INTTYPES_H\|[DK_]*NTDDDISK_H\|STRINGS_H\|STRTOULL\|UNISTD_H\|WORKING_SNPRINTF\) 1$$,/* #undef HAVE_\1 */,' \
            -e 's,^\(#define SMARTMONTOOLS_BUILD_HOST "[^-]*\)[^"]*,\1-pc-w32vc10,' $< > $@
 
-$(srcdir)/os_win32/svnversion_vc10.h: svnversion.h
+$(srcdir)/os_win32/vc10/svnversion.h: svnversion.h
+       cp $< $@
+
+$(srcdir)/os_win32/vc10/smartctl_res.rc: smartctl_res.rc
+       cp $< $@
+
+$(srcdir)/os_win32/vc10/smartd_res.rc: smartd_res.rc
        cp $< $@
 
 endif
diff --git a/NEWS b/NEWS
index a5b41cda93390f6e31606655cd9fd03e49f43175..1b7edfe83de040c7118e4745704f3d0d8654e73f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,73 @@
 smartmontools NEWS
 ------------------
-$Id: NEWS 3557 2012-06-04 19:50:21Z chrfranke $
+$Id: NEWS 3808 2013-04-18 17:30:12Z chrfranke $
 
 The most up-to-date version of this file is:
 http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
 
 Date <Not released yet, please try current SVN>
+Summary: smartmontools release 6.2
+-----------------------------------------------------------
+- Cygwin: 64-bit compile fixes.
+
+Date 2013-03-16
+Summary: smartmontools release 6.1
+-----------------------------------------------------------
+- smartctl '-l directory': improved output format.
+- smartctl: Fix parsing of '-l select,cont+SIZE' option.
+- smartctl prints ATA Additional Product Id (OEM Id).
+- smartctl '-s/-g wcache' for SCSI devices to control write cache.
+- smartctl '-s/-g rcache' for SCSI devices to control read cache.
+- smartctl prints more info for SCSI devices: media rotation rate,
+  form factor, physical block size, lowest LBA alignement,
+  logical block provisioning, disk protection type
+  and selftest progress status.
+- smartctl '--identify' updated for latest ATA ACS-3 spec.
+- smartd runs /etc/smartd_warning.sh to generate warning emails
+  (Windows: smartd_warning.cmd).
+- smartd '-w PATH' option to specify this executable.
+- smartd '-d ignore' directive.
+- smartd DEVICESCAN ignores devices already specified.
+- smartd: added support for state persistence ('-s') and attribute logging
+  ('-A') for SCSI devices.
+- smartd '-W' directive uses ATA attribute 190 if 194 is missing.
+- Support of larger SCSI defect lists via READ DEFECT(12).
+- Device type '-d usbjmicron,p' for Prolific USB bridges.
+- Many HDD, SSD and USB additions to drive database.
+- Linux: Support for SAS disks behind Areca controllers.
+- Linux: Improved support for SATA disks on LSI/Megaraid controllers
+- Linux: disks on MegaRaid controllers are automatically scanned
+- FreeBSD: Support for SAS disks behind Areca controllers.
+- FreeBSD: Enhanced ATA command support for 3ware.
+- FreeBSD: Support for 3ware 9750 (/dev/twsX).
+- FreeBSD: Fixed support for 48-bit ATA commands on legacy controllers
+  with ATACAM driver.
+- FreeBSD: Improved support for SAS/SCSI disks on LSI/Megaraid controllers.
+- Windows: smartd.conf '-M exec' supports path names with spaces.
+- Windows: Tool wtssendmsg.exe to handle smartd.conf '-m console'.
+- Windows: DEVICESCAN now supports up to 128 drives.
+- Windows: smartctl.exe and smartd.exe include VERSIONINFO resource.
+- Windows: smartd.exe includes MESSAGETABLE resource.
+- Windows: syslogevt.exe is no longer provided.
+
+Date 2012-10-10
+Summary: smartmontools release 6.0
+-----------------------------------------------------------
+- option/directive '-F nologdir' and '-F xerrorlba'.
+- smartctl '--identify' option.
+- smartctl prints nominal media rotation rate (ATA).
+- smartctl prints SATA version and speed.
+- smartctl '-l sataphy' works for CD/DVD drives also.
+- smartctl '-x' includes ATA Device Statistics.
+- smartd warning emails include device identify info.
+- smartd '-d' output is flushed to support redirection.
+- HDD, SSD and USB additions to drive database.
+- Windows smartd: smartd.conf directives '-m console',
+  '-m active', '-m connected'.
+- Windows: Support for SAS disks behind Areca controllers.
+- Windows: Win9x/ME and NT4 are no longer supported.
+
+Date 2012-06-30
 Summary: smartmontools release 5.43
 -----------------------------------------------------------
 - smartctl options '-g, --get' and '-s, --set' to get/set
@@ -21,7 +83,8 @@ Summary: smartmontools release 5.43
 - Controller-independent SAT detection: '-d sat,auto[+TYPE]'.
 - smartd.conf DEFAULT directive.
 - Many HDD, SSD and USB additions to drive database.
-- Linux and FreeBSD: Support for SATA disks behind Areca SAS controllers.
+- Linux and FreeBSD: Support for SATA disks behind Areca SAS
+  RAID controllers and HP Smart Array controllers.
 - Windows: Support for SATA disks behind Areca controllers.
 - Windows smartd: directives '-l offlinests,ns' and
   '-l selfteststs,ns'.
diff --git a/README b/README
index aa7278ec1215cefc809806ae50b3a0b79a36d98f..5a6d12e75466f3990726261389cf6023f9bff44b 100644 (file)
--- a/README
+++ b/README
@@ -3,7 +3,7 @@ smartmontools - S.M.A.R.T. utility toolset for Darwin/Mac
 OSX, FreeBSD, Linux, NetBSD, OpenBSD, Solaris, and Windows.
 ==========================================================
 
-$Id: README 2844 2009-07-18 12:59:21Z chrfranke $
+$Id: README 3727 2012-12-13 17:23:06Z samm2 $
 
 == HOME ==
 The home for smartmontools is located at:
@@ -27,8 +27,8 @@ 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, write to the Free Software Foundation, Inc., 675
-Mass Ave, Cambridge, MA 02139, USA.
+example COPYING); if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 
 == CREDITS ==
index ecd483bbef39bf7c2e7a657ff1d01d31bce56802..9ba90f65a35961e0248da4deeff876f3a51b9a7c 100644 (file)
@@ -1,13 +1,10 @@
 /*
  * atacmdnames.cpp
  *
- * This module is based on the T13/1532D Volume 1 Revision 3 (ATA/ATAPI-7)
- * specification, which is available from http://www.t13.org/#FTP_site
- *
  * Home page of code is: http://smartmontools.sourceforge.net
- * Address of support mailing list: smartmontools-support@lists.sourceforge.net
  *
  * Copyright (C) 2003-8 Philip Williams
+ * Copyright (C) 2012 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
@@ -15,8 +12,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 #include <stdlib.h>
 #include <stdio.h>
 
-#define COMMAND_TABLE_SIZE 256
-
-const char *atacmdnames_c_cvsid="$Id: atacmdnames.cpp,v 1.17 2008/03/29 23:41:28 shattered Exp $" ATACMDNAMES_H_CVSID;
+const char * atacmdnames_cpp_cvsid = "$Id: atacmdnames.cpp 3670 2012-10-31 22:00:50Z chrfranke $"
+  ATACMDNAMES_H_CVSID;
 
 const char cmd_reserved[]        = "[RESERVED]";
 const char cmd_vendor_specific[] = "[VENDOR SPECIFIC]";
 const char cmd_reserved_sa[]     = "[RESERVED FOR SERIAL ATA]";
 const char cmd_reserved_cf[]     = "[RESERVED FOR COMPACTFLASH ASSOCIATION]";
-const char cmd_reserved_mcpt[]   = "[RESERVED FOR MEDIA CARD PASS THROUGH]";
+const char cmd_reserved_mcpt[]   = "[RESERVED FOR MEDIA CARD PASS THROUGH]"; // ACS-3: Reserved
 const char cmd_recalibrate_ret4[]= "RECALIBRATE [RET-4]";
 const char cmd_seek_ret4[]       = "SEEK [RET-4]";
 
-const char *command_table[COMMAND_TABLE_SIZE] = {
+// Tables B.3 and B.4 of T13/2161-D (ACS-3) Revision 4, September 4, 2012
+
+const char * const command_table[] = {
 /*-------------------------------------------------- 00h-0Fh -----*/
   "NOP",
   cmd_reserved,
   cmd_reserved,
-  "CFA REQUEST EXTENDED ERROR CODE",
-  cmd_reserved,
+  "CFA REQUEST EXTENDED ERROR",
   cmd_reserved,
   cmd_reserved,
+  "DATA SET MANAGEMENT", // ACS-2
   cmd_reserved,
   "DEVICE RESET",
   cmd_reserved,
   cmd_reserved,
-  cmd_reserved,
+  "REQUEST SENSE DATA EXT", // ACS-2
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
@@ -74,46 +71,46 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
 /*-------------------------------------------------- 20h-2Fh -----*/
   "READ SECTOR(S)",
   "READ SECTOR(S) [OBS-5]",
-  "READ LONG (w/ retry) [OBS-4]",
+  "READ LONG [OBS-4]",
   "READ LONG (w/o retry) [OBS-4]",
   "READ SECTOR(S) EXT",
   "READ DMA EXT",
-  "READ DMA QUEUED EXT",
-  "READ NATIVE MAX ADDRESS EXT",
+  "READ DMA QUEUED EXT [OBS-ACS-2]",
+  "READ NATIVE MAX ADDRESS EXT [OBS-ACS-3]",
   cmd_reserved,
   "READ MULTIPLE EXT",
   "READ STREAM DMA",
-  "READ STREAM PIO",
+  "READ STREAM",
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
   "READ LOG EXT",
 /*-------------------------------------------------- 30h-3Fh -----*/
   "WRITE SECTOR(S)",
-  "WRITE SECTOR(S) [OBS-5]",
-  "WRITE LONG(w/ retry) [OBS-4]",
-  "WRITE LONG(w/o retry) [OBS-4]",
+  "WRITE SECTOR(S) (w/o retry) [OBS-5]",
+  "WRITE LONG [OBS-4]",
+  "WRITE LONG (w/o retry) [OBS-4]",
   "WRITE SECTORS(S) EXT",
   "WRITE DMA EXT",
-  "WRITE DMA QUEUED EXT",
-  "SET MAX ADDRESS EXT",
+  "WRITE DMA QUEUED EXT [OBS-ACS-2]",
+  "SET NATIVE MAX ADDRESS EXT [OBS-ACS-3]",
   "CFA WRITE SECTORS WITHOUT ERASE",
   "WRITE MULTIPLE EXT",
   "WRITE STREAM DMA",
-  "WRITE STREAM PIO",
+  "WRITE STREAM",
   "WRITE VERIFY [OBS-4]",
   "WRITE DMA FUA EXT",
-  "WRITE DMA QUEUED FUA EXT",
+  "WRITE DMA QUEUED FUA EXT [OBS-ACS-2]",
   "WRITE LOG EXT",
 /*-------------------------------------------------- 40h-4Fh -----*/
   "READ VERIFY SECTOR(S)",
-  "READ VERIFY SECTOR(S) [OBS-5]",
+  "READ VERIFY SECTOR(S) (w/o retry) [OBS-5]",
   "READ VERIFY SECTOR(S) EXT",
   cmd_reserved,
   cmd_reserved,
+  "WRITE UNCORRECTABLE EXT", // ATA-8
   cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
+  "READ LOG DMA EXT", // ATA-8
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
@@ -130,22 +127,22 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
+  "WRITE LOG DMA EXT", // ATA-8
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
+  "TRUSTED NON-DATA", // ATA-8
+  "TRUSTED RECEIVE", // ATA-8
+  "TRUSTED RECEIVE DMA", // ATA-8
+  "TRUSTED SEND", // ATA-8
+  "TRUSTED SEND DMA", // ATA-8
 /*-------------------------------------------------- 60h-6Fh -----*/
-  "READ FPDMA QUEUED",
-  "WRITE FPDMA QUEUED",  
-  cmd_reserved_sa,
-  cmd_reserved_sa,
-  cmd_reserved_sa,
+  "READ FPDMA QUEUED", // ATA-8
+  "WRITE FPDMA QUEUED", // ATA-8
   cmd_reserved_sa,
+  "NCQ QUEUE MANAGEMENT", // ACS-3
+  "SEND FPDMA QUEUED", // ACS-3
+  "RECEIVE FPDMA QUEUED", // ACS-3
   cmd_reserved_sa,
   cmd_reserved_sa,
   cmd_reserved,
@@ -164,8 +161,8 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   cmd_seek_ret4,
   cmd_seek_ret4,
   cmd_seek_ret4,
-  cmd_seek_ret4,
-  cmd_seek_ret4,
+  "SET DATE & TIME EXT", // ACS-3
+  "ACCESSIBLE MAX ADDRESS CONFIGURATION", // ACS-3
   cmd_seek_ret4,
   cmd_seek_ret4,
   cmd_seek_ret4,
@@ -194,7 +191,7 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   "EXECUTE DEVICE DIAGNOSTIC",
   "INITIALIZE DEVICE PARAMETERS [OBS-6]",
   "DOWNLOAD MICROCODE",
-  cmd_reserved,
+  "DOWNLOAD MICROCODE DMA", // ACS-2
   "STANDBY IMMEDIATE [RET-4]",
   "IDLE IMMEDIATE [RET-4]",
   "STANDBY [RET-4]",
@@ -210,7 +207,7 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
 /*-------------------------------------------------- A0h-AFh -----*/
   "PACKET",
   "IDENTIFY PACKET DEVICE",
-  "SERVICE",
+  "SERVICE [OBS-ACS-2]",
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
@@ -226,21 +223,21 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   cmd_reserved,
 /*-------------------------------------------------- B0h-BFh -----*/
   "SMART",
-  "DEVICE CONFIGURATION",
-  cmd_reserved,
+  "DEVICE CONFIGURATION [OBS-ACS-3]",
   cmd_reserved,
   cmd_reserved,
+  "SANITIZE DEVICE", // ACS-2
   cmd_reserved,
-  cmd_reserved,
-  cmd_reserved,
-  cmd_reserved_cf,
-  cmd_reserved_cf,
-  cmd_reserved_cf,
+  "NV CACHE [OBS-ACS-3]", // ATA-8
   cmd_reserved_cf,
   cmd_reserved_cf,
   cmd_reserved_cf,
   cmd_reserved_cf,
   cmd_reserved_cf,
+  cmd_reserved,
+  cmd_reserved,
+  cmd_reserved,
+  cmd_reserved,
 /*-------------------------------------------------- C0h-CFh -----*/
   "CFA ERASE SECTORS [VS IF NO CFA]",
   cmd_vendor_specific,
@@ -249,18 +246,18 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   "READ MULTIPLE",
   "WRITE MULTIPLE",
   "SET MULTIPLE MODE",
-  "READ DMA QUEUED",
+  "READ DMA QUEUED [OBS-ACS-2]",
   "READ DMA",
-  "READ DMA [OBS-5]",
+  "READ DMA (w/o retry) [OBS-5]",
   "WRITE DMA",
-  "WRITE DMA [OBS-5]",
-  "WRITE DMA QUEUED",
+  "WRITE DMA (w/o retry) [OBS-5]",
+  "WRITE DMA QUEUED [OBS-ACS-2]",
   "CFA WRITE MULTIPLE WITHOUT ERASE",
   "WRITE MULTIPLE FUA EXT",
   cmd_reserved,
 /*-------------------------------------------------- D0h-DFh -----*/
   cmd_reserved,
-  "CHECK MEDIA CARD TYPE",
+  "CHECK MEDIA CARD TYPE [OBS-ACS-2]",
   cmd_reserved_mcpt,
   cmd_reserved_mcpt,
   cmd_reserved_mcpt,
@@ -269,12 +266,12 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   cmd_reserved,
   cmd_reserved,
   cmd_reserved,
-  "GET MEDIA STATUS",
+  "GET MEDIA STATUS [OBS-8]",
   "ACKNOWLEDGE MEDIA CHANGE [RET-4]",
   "BOOT POST-BOOT [RET-4]",
   "BOOT PRE-BOOT [RET-4]",
-  "MEDIA LOCK",
-  "MEDIA UNLOCK",
+  "MEDIA LOCK [OBS-8]",
+  "MEDIA UNLOCK [OBS-8]",
 /*-------------------------------------------------- E0h-EFh -----*/
   "STANDBY IMMEDIATE",
   "IDLE IMMEDIATE",
@@ -285,14 +282,11 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   "SLEEP",
   "FLUSH CACHE",
   "WRITE BUFFER",
-  "WRITE SAME [RET-4]",  /* Warning!  This command is retired but the value of
-                            f_reg is used in look_up_ata_command().  If this
-                            command code is reclaimed in a future standard then
-                            be sure to update look_up_ata_command(). */
+  "READ BUFFER DMA", // ACS-2 (was: WRITE SAME [RET-4])
   "FLUSH CACHE EXT",
-  cmd_reserved,
+  "WRITE BUFFER DMA", // ACS-2
   "IDENTIFY DEVICE",
-  "MEDIA EJECT",
+  "MEDIA EJECT [OBS-8]",
   "IDENTIFY DEVICE DMA [OBS-4]",
   "SET FEATURES",
 /*-------------------------------------------------- F0h-FFh -----*/
@@ -304,8 +298,8 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   "SECURITY FREEZE LOCK",
   "SECURITY DISABLE PASSWORD",
   cmd_vendor_specific,
-  "READ NATIVE MAX ADDRESS",
-  "SET MAX",
+  "READ NATIVE MAX ADDRESS [OBS-ACS-3]",
+  "SET MAX ADDRESS [OBS-ACS-3]",
   cmd_vendor_specific,
   cmd_vendor_specific,
   cmd_vendor_specific,
@@ -314,6 +308,9 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
   cmd_vendor_specific
 };
 
+typedef char ASSERT_command_table_size[
+  sizeof(command_table)/sizeof(command_table[0]) == 256 ? 1 : -1];
+
 /* Returns the name of the command (and possibly sub-command) with the given
    command code and feature register values.   For most command codes this
    simply returns the corresponding entry in the command_table array, but for
@@ -321,33 +318,28 @@ const char *command_table[COMMAND_TABLE_SIZE] = {
    distinguishes commands. */
 const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
 
-  // check that command table not messed up.  The compiler will issue
-  // warnings if there are too many array elements, but won't issue
-  // warnings if there are not enough of them.
-  if (sizeof(command_table) != sizeof(char *)*COMMAND_TABLE_SIZE){
-    fprintf(stderr, 
-            "Problem in atacmdnames.c.  Command Table command_table[] does\n"
-            "not have %d entries!  It has %d entries. Please fix it.\n",
-            COMMAND_TABLE_SIZE, (int)(sizeof(command_table)/sizeof(char *)));
-    abort();
-  }
-
   switch (c_code) {
   case 0x00:  /* NOP */
     switch (f_reg) {
     case 0x00:
       return "NOP [Abort queued commands]";
     case 0x01:
-      return "NOP [Don't abort queued commands]";
+      return "NOP [Don't abort queued commands] [OBS-ACS-2]";
     default:
-      return "NOP [Reserved subcommand]";
+      return "NOP [Reserved subcommand] [OBS-ACS-2]";
     }
   case 0x92:  /* DOWNLOAD MICROCODE */
     switch (f_reg) {
     case 0x01:
-      return "DOWNLOAD MICROCODE [Temporary]";
+      return "DOWNLOAD MICROCODE [Temporary] [OBS-8]";
+    case 0x03:
+      return "DOWNLOAD MICROCODE [Save with offsets]"; // ATA-8
     case 0x07:
       return "DOWNLOAD MICROCODE [Save]";
+    case 0x0e:
+      return "DOWNLOAD MICROCODE [Save for future use]"; // ACS-3
+    case 0x0f:
+      return "DOWNLOAD MICROCODE [Activate]"; // ACS-3
     default:
       return "DOWNLOAD MICROCODE [Reserved subcommand]";
     }
@@ -379,36 +371,27 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
       return "SMART EN/DISABLE AUTO OFFLINE [NS (SFF-8035i)]";
     default:
         if (f_reg >= 0xE0)
-          return "[Vendor specific SMART command]";
+          return "SMART [Vendor specific subcommand]";
         else
-          return "[Reserved SMART command]";
+          return "SMART [Reserved subcommand]";
     }
   case 0xB1:  /* DEVICE CONFIGURATION */
     switch (f_reg) {
     case 0xC0:
-      return "DEVICE CONFIGURATION RESTORE";
+      return "DEVICE CONFIGURATION RESTORE [OBS-ACS-3]";
     case 0xC1:
-      return "DEVICE CONFIGURATION FREEZE LOCK";
+      return "DEVICE CONFIGURATION FREEZE LOCK [OBS-ACS-3]";
     case 0xC2:
-      return "DEVICE CONFIGURATION IDENTIFY";
+      return "DEVICE CONFIGURATION IDENTIFY [OBS-ACS-3]";
     case 0xC3:
-      return "DEVICE CONFIGURATION SET";
+      return "DEVICE CONFIGURATION SET [OBS-ACS-3]";
     default:
-      return "DEVICE CONFIGURATION [Reserved command]";
+      return "DEVICE CONFIGURATION [Reserved subcommand] [OBS-ACS-3]";
     }
-  case 0xE9:  /* WRITE SAME */
-    switch (f_reg) {
-    case 0x22:
-      return "WRITE SAME [Start specified] [RET-4]";
-    case 0xDD:
-      return "WRITE SAME [Start unspecified] [RET-4]";
-    default:
-      return "WRITE SAME [Invalid subcommand] [RET-4]";
-    } 
   case 0xEF:  /* SET FEATURES */
     switch (f_reg) {
     case 0x01:
-      return "SET FEATURES [Enable 8-bit PIO]";
+      return "SET FEATURES [Enable 8-bit PIO] [OBS-3]"; // Now CFA
     case 0x02:
       return "SET FEATURES [Enable write cache]";
     case 0x03:
@@ -422,39 +405,45 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
     case 0x07:
       return "SET FEATURES [Set device spin-up]";
     case 0x09:
-      return "SET FEATURES [Reserved (address offset)]";
+      return "SET FEATURES [Reserved (address offset)] [OPS-ACS-3]";
     case 0x0A:
       return "SET FEATURES [Enable CFA power mode 1]";
     case 0x10:
-      return "SET FEATURES [Reserved for Serial ATA]";
+      return "SET FEATURES [Enable SATA feature]"; // ACS-3
     case 0x20:
       return "SET FEATURES [Set Time-ltd R/W WCT]";
     case 0x21:
       return "SET FEATURES [Set Time-ltd R/W EH]";
     case 0x31:
-      return "SET FEATURES [Disable Media Status Notf]";
+      return "SET FEATURES [Disable Media Status Notf] [OBS-8]";
     case 0x33:
       return "SET FEATURES [Disable retry] [OBS-4]";
+    case 0x41:
+      return "SET FEATURES [Enable Free-fall Control]"; // ATA-8
     case 0x42:
-      return "SET FEATURES [Enable AAM]";
+      return "SET FEATURES [Enable AAM] [OBS-ACS-2]";
     case 0x43:
       return "SET FEATURES [Set Max Host I/F S Times]";
     case 0x44:
       return "SET FEATURES [Length of VS data] [OBS-4]";
+    case 0x4a:
+      return "SET FEATURES [Ext. Power Conditions]"; // ACS-2
     case 0x54:
       return "SET FEATURES [Set cache segs] [OBS-4]";
     case 0x55:
       return "SET FEATURES [Disable read look-ahead]";
     case 0x5D:
-      return "SET FEATURES [Enable release interrupt]";
+      return "SET FEATURES [Enable release interrupt] [OBS-ACS-2]";
     case 0x5E:
-      return "SET FEATURES [Enable SERVICE interrupt]";
+      return "SET FEATURES [Enable SERVICE interrupt] [OBS-ACS-2]";
     case 0x66:
       return "SET FEATURES [Disable revert defaults]";
+    case 0x69:
+      return "SET FEATURES [LPS Error Reporting Control]"; // ACS-2
     case 0x77:
       return "SET FEATURES [Disable ECC] [OBS-4]";
     case 0x81:
-      return "SET FEATURES [Disable 8-bit PIO]";
+      return "SET FEATURES [Disable 8-bit PIO] [OBS-3]"; // Now CFA
     case 0x82:
       return "SET FEATURES [Disable write cache]";
     case 0x84:
@@ -470,9 +459,9 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
     case 0x8A:
       return "SET FEATURES [Disable CFA power mode 1]";
     case 0x90:
-      return "SET FEATURES [Reserved for Serial ATA]";
+      return "SET FEATURES [Disable SATA feature]"; // ACS-3
     case 0x95:
-      return "SET FEATURES [Enable Media Status Notf]";
+      return "SET FEATURES [Enable Media Status Notf] [OBS-8]";
     case 0x99:
       return "SET FEATURES [Enable retries] [OBS-4]";
     case 0x9A:
@@ -483,16 +472,20 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
       return "SET FEATURES [Set max prefetch] [OBS-4]";
     case 0xBB:
       return "SET FEATURES [4 bytes VS data] [OBS-4]";
+    case 0xC1:
+      return "SET FEATURES [Disable Free-fall Control]"; // ATA-8
     case 0xC2:
-      return "SET FEATURES [Disable AAM]";
+      return "SET FEATURES [Disable AAM] [OBS-ACS-2]";
+    case 0xC3:
+      return "SET FEATURES [Sense Data Reporting]"; // ACS-2
     case 0xCC:
       return "SET FEATURES [Enable revert to defaults]";
     case 0xDD:
-      return "SET FEATURES [Disable release interrupt]";
+      return "SET FEATURES [Disable release interrupt] [OBS-ACS-2]";
     case 0xDE:
-      return "SET FEATURES [Disable SERVICE interrupt]";
+      return "SET FEATURES [Disable SERVICE interrupt] [OBS-ACS-2]";
     case 0xE0:
-      return "SET FEATURES [Obsolete subcommand]";
+      return "SET FEATURES [Vendor specific] [OBS-7]";
     default:
       if (f_reg >= 0xF0)
         return "SET FEATURES [Reserved for CFA]";
@@ -504,15 +497,15 @@ const char *look_up_ata_command(unsigned char c_code, unsigned char f_reg) {
     case 0x00:
       return "SET MAX ADDRESS [OBS-6]";
     case 0x01:
-      return "SET MAX SET PASSWORD";
+      return "SET MAX SET PASSWORD [OBS-ACS-3]";
     case 0x02:
-      return "SET MAX LOCK";
+      return "SET MAX LOCK [OBS-ACS-3]";
     case 0x03:
-      return "SET MAX UNLOCK";
+      return "SET MAX UNLOCK [OBS-ACS-3]";
     case 0x04:
-      return "SET MAX FREEZE LOCK";
+      return "SET MAX FREEZE LOCK [OBS-ACS-3]";
     default:
-      return "[Reserved SET MAX command]";
+      return "SET MAX [Reserved subcommand] [OBS-ACS-3]";
     }
   default:
     return command_table[c_code];
index b2e65c9cd3698233c0ab04dacd7497c35d1a99ec..ac0e446a0bb0ab9591962719e163eaf96267e1c1 100644 (file)
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
 #ifndef ATACMDNAMES_H_
 #define ATACMDNAMES_H_
 
-#define ATACMDNAMES_H_CVSID "$Id: atacmdnames.h,v 1.6 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define ATACMDNAMES_H_CVSID "$Id: atacmdnames.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 /* Returns the name of the command (and possibly sub-command) with the given
    command code and feature register values. */
index f9ab53bac33967f45767ba3e954236b6e3f01812..d84d1f033fc2752e2e44f48c5db93cc7e7058003 100644 (file)
@@ -4,7 +4,7 @@
  * Home page of code is: http://smartmontools.sourceforge.net
  *
  * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
  * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
  *
@@ -14,8 +14,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -36,7 +35,7 @@
 #include "utility.h"
 #include "dev_ata_cmd_set.h" // for parsed_ata_device
 
-const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3528 2012-03-25 17:13:47Z chrfranke $"
+const char * atacmds_cpp_cvsid = "$Id: atacmds.cpp 3777 2013-02-19 18:32:15Z samm2 $"
                                  ATACMDS_H_CVSID;
 
 // Print ATA debug messages?
@@ -57,103 +56,6 @@ bool dont_print_serial_number = false;
 #define SRET_STATUS_HI_EXCEEDED 0x2C
 #define SRET_STATUS_MID_EXCEEDED 0xF4
 
-// These Drive Identity tables are taken from hdparm 5.2, and are also
-// given in the ATA/ATAPI specs for the IDENTIFY DEVICE command.  Note
-// that SMART was first added into the ATA/ATAPI-3 Standard with
-// Revision 3 of the document, July 25, 1995.  Look at the "Document
-// Status" revision commands at the beginning of
-// http://www.t13.org/Documents/UploadedDocuments/project/d2008r7b-ATA-3.pdf
-// to see this.
-#define NOVAL_0                 0x0000
-#define NOVAL_1                 0xffff
-/* word 81: minor version number */
-#define MINOR_MAX 0x22
-static const char * const minor_str[] = {       /* word 81 value: */
-  "Device does not report version",             /* 0x0000       */
-  "ATA-1 X3T9.2 781D prior to revision 4",      /* 0x0001       */
-  "ATA-1 published, ANSI X3.221-1994",          /* 0x0002       */
-  "ATA-1 X3T9.2 781D revision 4",               /* 0x0003       */
-  "ATA-2 published, ANSI X3.279-1996",          /* 0x0004       */
-  "ATA-2 X3T10 948D prior to revision 2k",      /* 0x0005       */
-  "ATA-3 X3T10 2008D revision 1",               /* 0x0006       */ /* SMART NOT INCLUDED */
-  "ATA-2 X3T10 948D revision 2k",               /* 0x0007       */
-  "ATA-3 X3T10 2008D revision 0",               /* 0x0008       */ 
-  "ATA-2 X3T10 948D revision 3",                /* 0x0009       */
-  "ATA-3 published, ANSI X3.298-199x",          /* 0x000a       */
-  "ATA-3 X3T10 2008D revision 6",               /* 0x000b       */ /* 1st VERSION WITH SMART */
-  "ATA-3 X3T13 2008D revision 7 and 7a",        /* 0x000c       */
-  "ATA/ATAPI-4 X3T13 1153D revision 6",         /* 0x000d       */
-  "ATA/ATAPI-4 T13 1153D revision 13",          /* 0x000e       */
-  "ATA/ATAPI-4 X3T13 1153D revision 7",         /* 0x000f       */
-  "ATA/ATAPI-4 T13 1153D revision 18",          /* 0x0010       */
-  "ATA/ATAPI-4 T13 1153D revision 15",          /* 0x0011       */
-  "ATA/ATAPI-4 published, ANSI NCITS 317-1998", /* 0x0012       */
-  "ATA/ATAPI-5 T13 1321D revision 3",           /* 0x0013       */
-  "ATA/ATAPI-4 T13 1153D revision 14",          /* 0x0014       */
-  "ATA/ATAPI-5 T13 1321D revision 1",           /* 0x0015       */
-  "ATA/ATAPI-5 published, ANSI NCITS 340-2000", /* 0x0016       */
-  "ATA/ATAPI-4 T13 1153D revision 17",          /* 0x0017       */
-  "ATA/ATAPI-6 T13 1410D revision 0",           /* 0x0018       */
-  "ATA/ATAPI-6 T13 1410D revision 3a",          /* 0x0019       */
-  "ATA/ATAPI-7 T13 1532D revision 1",           /* 0x001a       */
-  "ATA/ATAPI-6 T13 1410D revision 2",           /* 0x001b       */
-  "ATA/ATAPI-6 T13 1410D revision 1",           /* 0x001c       */
-  "ATA/ATAPI-7 published, ANSI INCITS 397-2005",/* 0x001d       */
-  "ATA/ATAPI-7 T13 1532D revision 0",           /* 0x001e       */
-  "reserved",                                   /* 0x001f       */
-  "reserved",                                   /* 0x0020       */
-  "ATA/ATAPI-7 T13 1532D revision 4a",          /* 0x0021       */
-  "ATA/ATAPI-6 published, ANSI INCITS 361-2002" /* 0x0022       */
-};
-
-// NOTE ATA/ATAPI-4 REV 4 was the LAST revision where the device
-// attribute structures were NOT completely vendor specific.  So any
-// disk that is ATA/ATAPI-4 or above can not be trusted to show the
-// vendor values in sensible format.
-
-// Negative values below are because it doesn't support SMART
-static const int actual_ver[] = { 
-  /* word 81 value: */
-  0,            /* 0x0000       WARNING:        */
-  1,            /* 0x0001       WARNING:        */
-  1,            /* 0x0002       WARNING:        */
-  1,            /* 0x0003       WARNING:        */
-  2,            /* 0x0004       WARNING:   This array           */
-  2,            /* 0x0005       WARNING:   corresponds          */
-  -3, /*<== */  /* 0x0006       WARNING:   *exactly*            */
-  2,            /* 0x0007       WARNING:   to the ATA/          */
-  -3, /*<== */  /* 0x0008       WARNING:   ATAPI version        */
-  2,            /* 0x0009       WARNING:   listed in            */
-  3,            /* 0x000a       WARNING:   the                  */
-  3,            /* 0x000b       WARNING:   minor_str            */
-  3,            /* 0x000c       WARNING:   array                */
-  4,            /* 0x000d       WARNING:   above.               */
-  4,            /* 0x000e       WARNING:                        */
-  4,            /* 0x000f       WARNING:   If you change        */
-  4,            /* 0x0010       WARNING:   that one,            */
-  4,            /* 0x0011       WARNING:   change this one      */
-  4,            /* 0x0012       WARNING:   too!!!               */
-  5,            /* 0x0013       WARNING:        */
-  4,            /* 0x0014       WARNING:        */
-  5,            /* 0x0015       WARNING:        */
-  5,            /* 0x0016       WARNING:        */
-  4,            /* 0x0017       WARNING:        */
-  6,            /* 0x0018       WARNING:        */
-  6,            /* 0x0019       WARNING:        */
-  7,            /* 0x001a       WARNING:        */
-  6,            /* 0x001b       WARNING:        */
-  6,            /* 0x001c       WARNING:        */
-  7,            /* 0x001d       WARNING:        */
-  7,            /* 0x001e       WARNING:        */
-  0,            /* 0x001f       WARNING:        */
-  0,            /* 0x0020       WARNING:        */
-  7,            /* 0x0021       WARNING:        */
-  6             /* 0x0022       WARNING:        */
-};
-
-// Compile time check of above array sizes
-typedef char assert_sizeof_minor_str [sizeof(minor_str) /sizeof(minor_str[0])  == MINOR_MAX+1 ? 1 : -1];
-typedef char assert_sizeof_actual_ver[sizeof(actual_ver)/sizeof(actual_ver[0]) == MINOR_MAX+1 ? 1 : -1];
 
 // Get ID and increase flag of current pending or offline
 // uncorrectable attribute.
@@ -246,7 +148,7 @@ const char * map_old_vendor_opts[][2] = {
   {"198,increasing"               , "198,raw48+,Total_Offl_Uncorrectabl"}, // '+' sets flag
   {"200,writeerrorcount"          , "200,raw48,Write_Error_Count"},
   {"201,detectedtacount"          , "201,raw48,Detected_TA_Count"},
-  {"220,temp"                     , "220,raw48,Temperature_Celsius"},
+  {"220,temp"                     , "220,tempminmax,Temperature_Celsius"},
 };
 
 const unsigned num_old_vendor_opts = sizeof(map_old_vendor_opts)/sizeof(map_old_vendor_opts[0]);
@@ -327,7 +229,7 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
       defs[i].priority = priority;
       defs[i].raw_format = format;
       defs[i].flags = flags;
-      strcpy(defs[i].byteorder, byteorder);
+      snprintf(defs[i].byteorder, sizeof(defs[i].byteorder), "%s", byteorder);
     }
   }
   else if (defs[id].priority <= priority) {
@@ -337,7 +239,7 @@ bool parse_attribute_def(const char * opt, ata_vendor_attr_defs & defs,
     defs[id].raw_format = format;
     defs[id].priority = priority;
     defs[id].flags = flags;
-    strcpy(defs[id].byteorder, byteorder);
+    snprintf(defs[id].byteorder, sizeof(defs[id].byteorder), "%s", byteorder);
   }
 
   return true;
@@ -359,6 +261,35 @@ std::string create_vendor_attribute_arg_list()
   return s;
 }
 
+
+// Parse firmwarebug def (-F option).
+// Return false on error.
+bool parse_firmwarebug_def(const char * opt, firmwarebug_defs & firmwarebugs)
+{
+    if (!strcmp(opt, "none"))
+      firmwarebugs.set(BUG_NONE);
+    else if (!strcmp(opt, "nologdir"))
+      firmwarebugs.set(BUG_NOLOGDIR);
+    else if (!strcmp(opt, "samsung"))
+      firmwarebugs.set(BUG_SAMSUNG);
+    else if (!strcmp(opt, "samsung2"))
+      firmwarebugs.set(BUG_SAMSUNG2);
+    else if (!strcmp(opt, "samsung3"))
+      firmwarebugs.set(BUG_SAMSUNG3);
+    else if (!strcmp(opt, "xerrorlba"))
+      firmwarebugs.set(BUG_XERRORLBA);
+    else
+      return false;
+    return true;
+}
+
+// Return a string of valid argument words for parse_firmwarebug_def()
+const char * get_valid_firmwarebug_args()
+{
+  return "none, nologdir, samsung, samsung2, samsung3, xerrorlba";
+}
+
+
 // swap two bytes.  Point to low address
 void swap2(char *location){
   char tmp=*location;
@@ -433,17 +364,18 @@ static const char * const commandstrings[]={
 };
 
 
-static const char * preg(const ata_register & r, char * buf)
+static const char * preg(const ata_register & r, char (& buf)[8])
 {
   if (!r.is_set())
     //return "n/a ";
     return "....";
-  sprintf(buf, "0x%02x", r.val()); return buf;
+  snprintf(buf, sizeof(buf), "0x%02x", r.val());
+  return buf;
 }
 
 static void print_regs(const char * prefix, const ata_in_regs & r, const char * suffix = "\n")
 {
-  char bufs[7][4+1+13];
+  char bufs[7][8];
   pout("%s FR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, CMD=%s%s", prefix,
     preg(r.features, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
     preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
@@ -452,7 +384,7 @@ static void print_regs(const char * prefix, const ata_in_regs & r, const char *
 
 static void print_regs(const char * prefix, const ata_out_regs & r, const char * suffix = "\n")
 {
-  char bufs[7][4+1+13];
+  char bufs[7][8];
   pout("%sERR=%s, SC=%s, LL=%s, LM=%s, LH=%s, DEV=%s, STS=%s%s", prefix,
     preg(r.error, bufs[0]), preg(r.sector_count, bufs[1]), preg(r.lba_low, bufs[2]),
     preg(r.lba_mid, bufs[3]), preg(r.lba_high, bufs[4]), preg(r.device, bufs[5]),
@@ -672,7 +604,7 @@ int smartcommandhandler(ata_device * device, smart_command_set command, int sele
         }
         else {
           // We haven't gotten output that makes sense; print out some debugging info
-          pout("Error SMART Status command failed\n");
+          pout("SMART Status command failed\n");
           pout("Please get assistance from %s\n", PACKAGE_HOMEPAGE);
           pout("Register values returned from SMART Status command are:\n");
           print_regs(" ", out.out_regs);
@@ -883,7 +815,8 @@ bool ata_set_features(ata_device * device, unsigned char features,
 // capable).  The value of the integer helps identify the type of
 // Packet device, which is useful so that the user can connect the
 // formal device number with whatever object is inside their computer.
-int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id)
+int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id,
+                      unsigned char * raw_buf /* = 0 */)
 {
   unsigned short *rawshort=(unsigned short *)buf;
   unsigned char  *rawbyte =(unsigned char  *)buf;
@@ -909,6 +842,10 @@ int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_s
       swap2((char *)(buf->model+i));
   }
 
+  // If requested, save raw data before endianness adjustments
+  if (raw_buf)
+    memcpy(raw_buf, buf, sizeof(*buf));
+
 #ifndef __NetBSD__
   // if machine is big-endian, swap byte order as needed
   // NetBSD kernel delivers IDENTIFY data in host byte order
@@ -963,68 +900,6 @@ int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_s
   return 0;
 }
 
-// Returns ATA version as an integer, and a pointer to a string
-// describing which revision.  Note that Revision 0 of ATA-3 does NOT
-// support SMART.  For this one case we return -3 rather than +3 as
-// the version number.  See notes above.
-int ataVersionInfo(const char ** description, const ata_identify_device * drive, unsigned short * minor)
-{
-  // get major and minor ATA revision numbers
-  unsigned short major = drive->major_rev_num;
-  *minor=drive->minor_rev_num;
-  
-  // First check if device has ANY ATA version information in it
-  if (major==NOVAL_0 || major==NOVAL_1) {
-    *description=NULL;
-    return 0; // No info found
-  }
-  
-  // The minor revision number has more information - try there first
-  if (*minor && (*minor<=MINOR_MAX)){
-    int std = actual_ver[*minor];
-    if (std) {
-      *description=minor_str[*minor];
-      return std;
-    }
-  }
-
-  // Try new ATA-8 ACS minor revision numbers.
-  // Table 55 of T13/2015-D Revision 4a (ACS-2), December 9, 2010.
-  // (not in actual_ver/minor_str to avoid large sparse tables)
-  const char *desc;
-  switch (*minor) {
-    case 0x0027: desc = "ATA-8-ACS revision 3c"; break;
-    case 0x0028: desc = "ATA-8-ACS revision 6"; break;
-    case 0x0029: desc = "ATA-8-ACS revision 4"; break;
-    case 0x0031: desc = "ACS-2 revision 2"; break;
-    case 0x0033: desc = "ATA-8-ACS revision 3e"; break;
-    case 0x0039: desc = "ATA-8-ACS revision 4c"; break;
-    case 0x0042: desc = "ATA-8-ACS revision 3f"; break;
-    case 0x0052: desc = "ATA-8-ACS revision 3b"; break;
-    case 0x0107: desc = "ATA-8-ACS revision 2d"; break;
-    case 0x0110: desc = "ACS-2 revision 3"; break;
-    default:     desc = 0; break;
-  }
-  if (desc) {
-    *description = desc;
-    return 8;
-  }
-
-  // HDPARM has a very complicated algorithm from here on. Since SMART only
-  // exists on ATA-3 and later standards, let's punt on this.  If you don't
-  // like it, please fix it.  The code's in CVS.
-  int i;
-  for (i=15; i>0; i--)
-    if (major & (0x1<<i))
-      break;
-  
-  *description=NULL; 
-  if (i==0)
-    return 1;
-  else
-    return i;
-}
-
 // Get World Wide Name (WWN) fields.
 // Return NAA field or -1 if WWN is unsupported.
 // Table 34 of T13/1699-D Revision 6a (ATA8-ACS), September 6, 2008.
@@ -1047,6 +922,23 @@ int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & uniqu
   return (word108 >> 12);
 }
 
+// Get nominal media rotation rate.
+// Returns: 0 = not reported, 1 = SSD, >1 = HDD rpm, < 0 = -(Unknown value)
+int ata_get_rotation_rate(const ata_identify_device * id)
+{
+  // Table 37 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
+  // Table A.31 of T13/2161-D (ACS-3) Revision 3b, August 25, 2012
+  unsigned short word217 = id->words088_255[217-88];
+  if (word217 == 0x0000 || word217 == 0xffff)
+    return 0;
+  else if (word217 == 0x0001)
+    return 1;
+  else if (word217 > 0x0400)
+    return word217;
+  else
+    return -(int)word217;
+}
+
 // returns 1 if SMART supported, 0 if SMART unsupported, -1 if can't tell
 int ataSmartSupport(const ata_identify_device * drive)
 {
@@ -1082,7 +974,6 @@ int ataIsSmartEnabled(const ata_identify_device * drive)
 int ataReadSmartValues(ata_device * device, struct ata_smart_values *data){
   
   if (smartcommandhandler(device, READ_VALUES, 0, (char *)data)){
-    pout("Error SMART Values Read failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -1127,12 +1018,11 @@ static void fixsamsungselftestlog(ata_smart_selftestlog * data)
 
 // Reads the Self Test Log (log #6)
 int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
-                        unsigned char fix_firmwarebug)
+                        firmwarebug_defs firmwarebugs)
 {
 
   // get data from device
   if (smartcommandhandler(device, READ_LOG, 0x06, (char *)data)){
-    pout("Error SMART Error Self-Test Log Read failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -1141,7 +1031,7 @@ int ataReadSelfTestLog (ata_device * device, ata_smart_selftestlog * data,
     checksumwarning("SMART Self-Test Log Structure");
   
   // fix firmware bugs in self-test log
-  if (fix_firmwarebug == FIX_SAMSUNG)
+  if (firmwarebugs.is_set(BUG_SAMSUNG))
     fixsamsungselftestlog(data);
 
   // swap endian order if needed
@@ -1272,7 +1162,6 @@ int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_t
   
   // get data from device
   if (smartcommandhandler(device, READ_LOG, 0x09, (char *)data)){
-    pout("Error SMART Read Selective Self-Test Log failed: %s\n", device->get_errmsg());
     return -1;
   }
    
@@ -1294,9 +1183,6 @@ int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_t
     swap2((char *)&(data->pendingtime));
   }
   
-  if (data->logversion != 1)
-    pout("Note: selective self-test log revision number (%d) not 1 implies that no selective self-test has ever been run\n", data->logversion);
-  
   return 0;
 }
 
@@ -1315,6 +1201,7 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
   struct ata_selective_self_test_log sstlog, *data=&sstlog;
   unsigned char *ptr=(unsigned char *)data;
   if (ataReadSelectiveSelfTestLog(device, data)) {
+    pout("SMART Read Selective Self-test Log failed: %s\n", device->get_errmsg());
     pout("Since Read failed, will not attempt to WRITE Selective Self-test Log\n");
     return -1;
   }
@@ -1325,7 +1212,7 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
   // Host is NOT allowed to write selective self-test log if a selective
   // self-test is in progress.
   if (0<data->currentspan && data->currentspan<6 && ((sv->self_test_exec_status)>>4)==15) {
-    pout("Error SMART Selective or other Self-Test in progress.\n");
+    pout("SMART Selective or other Self-test in progress\n");
     return -4;
   }
 
@@ -1470,7 +1357,7 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
 
   // write new selective self-test log
   if (smartcommandhandler(device, WRITE_LOG, 0x09, (char *)data)){
-    pout("Error Write Selective Self-Test Log failed: %s\n", device->get_errmsg());
+    pout("Write Selective Self-test Log failed: %s\n", device->get_errmsg());
     return -3;
   }
 
@@ -1512,12 +1399,11 @@ static void fixsamsungerrorlog2(ata_smart_errorlog * data)
 // Error Log is #2, and the Extended Comprehensive SMART Error log is
 // #3
 int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
-                     unsigned char fix_firmwarebug)
+                     firmwarebug_defs firmwarebugs)
 {
   
   // get data from device
   if (smartcommandhandler(device, READ_LOG, 0x01, (char *)data)){
-    pout("Error SMART Error Log Read failed: %s\n", device->get_errmsg());
     return -1;
   }
   
@@ -1527,9 +1413,9 @@ int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
   
   // Some disks have the byte order reversed in some SMART Summary
   // Error log entries
-  if (fix_firmwarebug == FIX_SAMSUNG)
+  if (firmwarebugs.is_set(BUG_SAMSUNG))
     fixsamsungerrorlog(data);
-  else if (fix_firmwarebug == FIX_SAMSUNG2)
+  else if (firmwarebugs.is_set(BUG_SAMSUNG2))
     fixsamsungerrorlog2(data);
 
   // swap endian order if needed
@@ -1553,9 +1439,34 @@ int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
   return 0;
 }
 
+
+// Fix LBA byte ordering of Extended Comprehensive Error Log
+// if little endian instead of ATA register ordering is provided
+template <class T>
+static inline void fix_exterrlog_lba_cmd(T & cmd)
+{
+  T org = cmd;
+  cmd.lba_mid_register_hi = org.lba_high_register;
+  cmd.lba_low_register_hi = org.lba_mid_register_hi;
+  cmd.lba_high_register   = org.lba_mid_register;
+  cmd.lba_mid_register    = org.lba_low_register_hi;
+}
+
+static void fix_exterrlog_lba(ata_smart_exterrlog * log, unsigned nsectors)
+{
+   for (unsigned i = 0; i < nsectors; i++) {
+     for (int ei = 0; ei < 4; ei++) {
+       ata_smart_exterrlog_error_log & entry = log[i].error_logs[ei];
+       fix_exterrlog_lba_cmd(entry.error);
+       for (int ci = 0; ci < 5; ci++)
+         fix_exterrlog_lba_cmd(entry.commands[ci]);
+     }
+   }
+}
+
 // Read Extended Comprehensive Error Log
 bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log,
-                        unsigned nsectors)
+                        unsigned nsectors, firmwarebug_defs firmwarebugs)
 {
   if (!ataReadLogExt(device, 0x03, 0x00, 0, log, nsectors))
     return false;
@@ -1573,6 +1484,9 @@ bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log,
     }
   }
 
+  if (firmwarebugs.is_set(BUG_XERRORLBA))
+    fix_exterrlog_lba(log, nsectors);
+
   return true;
 }
 
@@ -1581,7 +1495,6 @@ int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt
   
   // get data from device
   if (smartcommandhandler(device, READ_THRESHOLDS, 0, (char *)data)){
-    pout("Error SMART Thresholds Read failed: %s\n", device->get_errmsg());
     return -1;
   }
   
@@ -1598,7 +1511,6 @@ int ataReadSmartThresholds (ata_device * device, struct ata_smart_thresholds_pvt
 
 int ataEnableSmart (ata_device * device ){
   if (smartcommandhandler(device, ENABLE, 0, NULL)){
-    pout("Error SMART Enable failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1607,7 +1519,6 @@ int ataEnableSmart (ata_device * device ){
 int ataDisableSmart (ata_device * device ){
   
   if (smartcommandhandler(device, DISABLE, 0, NULL)){
-    pout("Error SMART Disable failed: %s\n", device->get_errmsg());
     return -1;
   }  
   return 0;
@@ -1615,7 +1526,6 @@ int ataDisableSmart (ata_device * device ){
 
 int ataEnableAutoSave(ata_device * device){
   if (smartcommandhandler(device, AUTOSAVE, 241, NULL)){
-    pout("Error SMART Enable Auto-save failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1624,7 +1534,6 @@ int ataEnableAutoSave(ata_device * device){
 int ataDisableAutoSave(ata_device * device){
   
   if (smartcommandhandler(device, AUTOSAVE, 0, NULL)){
-    pout("Error SMART Disable Auto-save failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1638,7 +1547,6 @@ int ataEnableAutoOffline (ata_device * device){
   
   /* timer hard coded to 4 hours */  
   if (smartcommandhandler(device, AUTO_OFFLINE, 248, NULL)){
-    pout("Error SMART Enable Automatic Offline failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1649,7 +1557,6 @@ int ataEnableAutoOffline (ata_device * device){
 int ataDisableAutoOffline (ata_device * device){
   
   if (smartcommandhandler(device, AUTO_OFFLINE, 0, NULL)){
-    pout("Error SMART Disable Automatic Offline failed: %s\n", device->get_errmsg());
     return -1;
   }
   return 0;
@@ -1730,11 +1637,11 @@ int ataSmartTest(ata_device * device, int testtype, bool force,
 
   //  Print ouf message that we are sending the command to test
   if (testtype==ABORT_SELF_TEST)
-    sprintf(cmdmsg,"Abort SMART off-line mode self-test routine");
+    snprintf(cmdmsg, sizeof(cmdmsg), "Abort SMART off-line mode self-test routine");
   else if (!type)
-    sprintf(cmdmsg, "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
+    snprintf(cmdmsg, sizeof(cmdmsg), "SMART EXECUTE OFF-LINE IMMEDIATE subcommand 0x%02x", testtype);
   else
-    sprintf(cmdmsg,"Execute SMART %s routine immediately in %s mode",type,captive);
+    snprintf(cmdmsg, sizeof(cmdmsg), "Execute SMART %s routine immediately in %s mode", type, captive);
   pout("Sending command: \"%s\".\n",cmdmsg);
 
   if (select) {
@@ -2195,8 +2102,13 @@ std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
 
 // Attribute names shouldn't be longer than 23 chars, otherwise they break the
 // output of smartctl.
-static const char * get_default_attr_name(unsigned char id)
+static const char * get_default_attr_name(unsigned char id, int rpm)
 {
+  bool hdd = (rpm > 1), ssd = (rpm == 1);
+
+  static const char Unknown_HDD_Attribute[] = "Unknown_HDD_Attribute";
+  static const char Unknown_SSD_Attribute[] = "Unknown_SSD_Attribute";
+
   switch (id) {
   case 1:
     return "Raw_Read_Error_Rate";
@@ -2209,36 +2121,48 @@ static const char * get_default_attr_name(unsigned char id)
   case 5:
     return "Reallocated_Sector_Ct";
   case 6:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Read_Channel_Margin";
   case 7:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Seek_Error_Rate";
   case 8:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Seek_Time_Performance";
   case 9:
     return "Power_On_Hours";
   case 10:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Spin_Retry_Count";
   case 11:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Calibration_Retry_Count";
   case 12:
     return "Power_Cycle_Count";
   case 13:
     return "Read_Soft_Error_Rate";
   case 175:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Program_Fail_Count_Chip";
   case 176:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Erase_Fail_Count_Chip";
   case 177:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Wear_Leveling_Count";
   case 178:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Used_Rsvd_Blk_Cnt_Chip";
   case 179:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Used_Rsvd_Blk_Cnt_Tot";
   case 180:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Unused_Rsvd_Blk_Cnt_Tot";
   case 181:
     return "Program_Fail_Cnt_Total";
   case 182:
+    if (hdd) return Unknown_HDD_Attribute;
     return "Erase_Fail_Count_Total";
   case 183:
     return "Runtime_Bad_Block";
@@ -2249,6 +2173,7 @@ static const char * get_default_attr_name(unsigned char id)
   case 188:
     return "Command_Timeout";
   case 189:
+    if (ssd) return Unknown_SSD_Attribute;
     return "High_Fly_Writes";
   case 190:
     // Western Digital uses this for temperature.
@@ -2260,10 +2185,12 @@ static const char * get_default_attr_name(unsigned char id)
     // 55C sometime in the past.
     return "Airflow_Temperature_Cel";
   case 191:
+    if (ssd) return Unknown_SSD_Attribute;
     return "G-Sense_Error_Rate";
   case 192:
     return "Power-Off_Retract_Count";
   case 193:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Load_Cycle_Count";
   case 194:
     return "Temperature_Celsius";
@@ -2279,11 +2206,14 @@ static const char * get_default_attr_name(unsigned char id)
   case 199:
     return "UDMA_CRC_Error_Count";
   case 200:
+    if (ssd) return Unknown_SSD_Attribute;
     // Western Digital
     return "Multi_Zone_Error_Rate";
   case 201:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Soft_Read_Error_Rate";
   case 202:
+    if (ssd) return Unknown_SSD_Attribute;
     // Fujitsu: "TA_Increase_Count"
     return "Data_Address_Mark_Errs";
   case 203:
@@ -2298,36 +2228,49 @@ static const char * get_default_attr_name(unsigned char id)
     return "Thermal_Asperity_Rate";
   case 206:
     // Fujitsu
+    if (ssd) return Unknown_SSD_Attribute;
     return "Flying_Height";
   case 207:
     // Maxtor
+    if (ssd) return Unknown_SSD_Attribute;
     return "Spin_High_Current";
   case 208:
     // Maxtor
+    if (ssd) return Unknown_SSD_Attribute;
     return "Spin_Buzz";
   case 209:
     // Maxtor
+    if (ssd) return Unknown_SSD_Attribute;
     return "Offline_Seek_Performnce";
   case 220:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Disk_Shift";
   case 221:
+    if (ssd) return Unknown_SSD_Attribute;
     return "G-Sense_Error_Rate";
   case 222:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Loaded_Hours";
   case 223:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Load_Retry_Count";
   case 224:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Load_Friction";
   case 225:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Load_Cycle_Count";
   case 226:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Load-in_Time";
   case 227:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Torq-amp_Count";
   case 228:
     return "Power-off_Retract_Count";
   case 230:
     // seen in IBM DTPA-353750
+    if (ssd) return Unknown_SSD_Attribute;
     return "Head_Amplitude";
   case 231:
     return "Temperature_Celsius";
@@ -2336,8 +2279,10 @@ static const char * get_default_attr_name(unsigned char id)
     return "Available_Reservd_Space";
   case 233:
     // seen in Intel X25-E SSD
+    if (hdd) return Unknown_HDD_Attribute;
     return "Media_Wearout_Indicator";
   case 240:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Head_Flying_Hours";
   case 241:
     return "Total_LBAs_Written";
@@ -2346,6 +2291,7 @@ static const char * get_default_attr_name(unsigned char id)
   case 250:
     return "Read_Error_Retry_Rate";
   case 254:
+    if (ssd) return Unknown_SSD_Attribute;
     return "Free_Fall_Sensor";
   default:
     return "Unknown_Attribute";
@@ -2353,12 +2299,13 @@ static const char * get_default_attr_name(unsigned char id)
 }
 
 // Get attribute name
-std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs)
+std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs & defs,
+                                    int rpm /* = 0 */)
 {
   if (!defs[id].name.empty())
     return defs[id].name;
   else
-    return get_default_attr_name(id);
+    return get_default_attr_name(id, rpm);
 }
 
 // Find attribute index for attribute id, -1 if not found.
@@ -2377,11 +2324,11 @@ int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval)
 // non-default interpretations. If the Attribute does not exist, return 0
 unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs)
 {
-  for (int i = 0; i < 3; i++) {
-    static const unsigned char ids[3] = {194, 9, 220};
+  for (int i = 0; i < 4; i++) {
+    static const unsigned char ids[4] = {194, 190, 9, 220};
     unsigned char id = ids[i];
     const ata_attr_raw_format format = defs[id].raw_format;
-    if (!(   (id == 194 && format == RAWFMT_DEFAULT)
+    if (!(   ((id == 194 || id == 190) && format == RAWFMT_DEFAULT)
           || format == RAWFMT_TEMPMINMAX || format == RAWFMT_TEMP10X))
       continue;
     int idx = ata_find_attr_index(id, *data);
@@ -2409,7 +2356,7 @@ int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
   // read SCT status via SMART log 0xe0
   memset(sts, 0, sizeof(*sts));
   if (smartcommandhandler(device, READ_LOG, 0xe0, (char *)sts)){
-    pout("Error Read SCT Status failed: %s\n", device->get_errmsg());
+    pout("Read SCT Status failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -2427,7 +2374,7 @@ int ataReadSCTStatus(ata_device * device, ata_sct_status_response * sts)
 
   // Check format version
   if (!(sts->format_version == 2 || sts->format_version == 3)) {
-    pout("Error unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version);
+    pout("Unknown SCT Status format version %u, should be 2 or 3.\n", sts->format_version);
     return -1;
   }
   return 0;
@@ -2464,14 +2411,14 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
 
   // write command via SMART log page 0xe0
   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
-    pout("Error Write SCT Data Table command failed: %s\n", device->get_errmsg());
+    pout("Write SCT Data Table failed: %s\n", device->get_errmsg());
     return -1;
   }
 
   // read SCT data via SMART log page 0xe1
   memset(tmh, 0, sizeof(*tmh));
   if (smartcommandhandler(device, READ_LOG, 0xe1, (char *)tmh)){
-    pout("Error Read SCT Data Table failed: %s\n", device->get_errmsg());
+    pout("Read SCT Data Table failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -2480,7 +2427,7 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
     return -1;
 
   if (!(sts->ext_status_code == 0 && sts->action_code == 5 && sts->function_code == 1)) {
-    pout("Error unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
+    pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
       sts->ext_status_code, sts->action_code, sts->function_code);
     return -1;
   }
@@ -2490,12 +2437,8 @@ int ataReadSCTTempHist(ata_device * device, ata_sct_temperature_history_table *
     swapx(&tmh->format_version);
     swapx(&tmh->sampling_period);
     swapx(&tmh->interval);
-  }
-
-  // Check format version
-  if (tmh->format_version != 2) {
-    pout("Error unknown SCT Temperature History Format Version (%u), should be 2.\n", tmh->format_version);
-    return -1;
+    swapx(&tmh->cb_index);
+    swapx(&tmh->cb_size);
   }
   return 0;
 }
@@ -2535,7 +2478,7 @@ int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persisten
 
   // write command via SMART log page 0xe0
   if (smartcommandhandler(device, WRITE_LOG, 0xe0, (char *)&cmd)){
-    pout("Error Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
+    pout("Write SCT Feature Control Command failed: %s\n", device->get_errmsg());
     return -1;
   }
 
@@ -2544,7 +2487,7 @@ int ataSetSCTTempInterval(ata_device * device, unsigned interval, bool persisten
     return -1;
 
   if (!(sts.ext_status_code == 0 && sts.action_code == 4 && sts.function_code == 1)) {
-    pout("Error unexcepted SCT status 0x%04x (action_code=%u, function_code=%u)\n",
+    pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
       sts.ext_status_code, sts.action_code, sts.function_code);
     return -1;
   }
@@ -2599,7 +2542,7 @@ static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty
 
   ata_cmd_out out;
   if (!device->ata_pass_through(in, out)) {
-    pout("Error Write SCT (%cet) Error Recovery Control Command failed: %s\n",
+    pout("Write SCT (%cet) Error Recovery Control Command failed: %s\n",
       (!set ? 'G' : 'S'), device->get_errmsg());
     return -1;
   }
@@ -2609,7 +2552,7 @@ static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty
     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",
+    pout("Unexpected SCT status 0x%04x (action_code=%u, function_code=%u)\n",
       sts.ext_status_code, sts.action_code, sts.function_code);
     return -1;
   }
@@ -2619,9 +2562,16 @@ static int ataGetSetSCTErrorRecoveryControltime(ata_device * device, unsigned ty
     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");
+      pout("SMART WRITE LOG does not return COUNT and LBA_LOW register\n");
+      return -1;
+    }
+    if (   out.out_regs.sector_count == in.in_regs.sector_count
+        && out.out_regs.lba_low      == in.in_regs.lba_low     ) {
+      // 0xe001 (5734.5s) - this is most likely a broken ATA pass-through implementation
+      pout("SMART WRITE LOG returns COUNT and LBA_LOW register unchanged\n");
       return -1;
     }
+
     // Return value to caller
     time_limit = out.out_regs.sector_count | (out.out_regs.lba_low << 8);
   }
@@ -2713,8 +2663,9 @@ int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
   char msglba[32];
   if (retval < 0 && failing_lba < 0xffffffffffffULL)
     snprintf(msglba, sizeof(msglba), "%"PRIu64, failing_lba);
-  else
-    strcpy(msglba, "-");
+  else {
+    msglba[0] = '-'; msglba[1] = 0;
+  }
 
   pout("#%2u  %-19s %-29s %1d0%%  %8u         %s\n", testnum,
        msgtest.c_str(), msgstat.c_str(), test_status & 0x0f, timestamp, msglba);
@@ -2727,11 +2678,11 @@ int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
 // bottom 8 bits: number of entries found where self-test showed an error
 // remaining bits: if nonzero, power on hours of last self-test where error was found
 int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
-                             unsigned char fix_firmwarebug)
+                             firmwarebug_defs firmwarebugs)
 {
   if (allentries)
     pout("SMART Self-test log structure revision number %d\n",(int)data->revnumber);
-  if ((data->revnumber!=0x0001) && allentries && fix_firmwarebug != FIX_SAMSUNG)
+  if (data->revnumber != 0x0001 && allentries && !firmwarebugs.is_set(BUG_SAMSUNG))
     pout("Warning: ATA Specification requires self-test log structure revision number = 1\n");
   if (data->mostrecenttest==0){
     if (allentries)
index 9a715656968b44e8b6544d6ce850c7701f50c40e..a0d965dee40ee9d91ed9fc46c5c9b054dfbe8d12 100644 (file)
--- a/atacmds.h
+++ b/atacmds.h
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -26,7 +25,7 @@
 #ifndef ATACMDS_H_
 #define ATACMDS_H_
 
-#define ATACMDS_H_CVSID "$Id: atacmds.h 3528 2012-03-25 17:13:47Z chrfranke $"
+#define ATACMDS_H_CVSID "$Id: atacmds.h 3632 2012-10-09 10:10:53Z chrfranke $"
 
 #include "dev_interface.h" // ata_device
 
@@ -67,14 +66,6 @@ typedef enum {
   WRITE_LOG
 } smart_command_set;
 
-// Possible values for fix_firmwarebug.
-enum {
-  FIX_NOTSPECIFIED = 0,
-  FIX_NONE,
-  FIX_SAMSUNG,
-  FIX_SAMSUNG2,
-  FIX_SAMSUNG3
-};
 
 // ATA Specification Command Register Values (Commands)
 #define ATA_CHECK_POWER_MODE            0xe5
@@ -727,6 +718,37 @@ private:
 };
 
 
+// Possible values for firmwarebugs
+enum firmwarebug_t {
+  BUG_NONE = 0,
+  BUG_NOLOGDIR,
+  BUG_SAMSUNG,
+  BUG_SAMSUNG2,
+  BUG_SAMSUNG3,
+  BUG_XERRORLBA
+};
+
+// Set of firmware bugs
+class firmwarebug_defs
+{
+public:
+  firmwarebug_defs()
+    : m_bugs(0) { }
+
+  bool is_set(firmwarebug_t bug) const
+    { return !!(m_bugs & (1 << bug)); }
+
+  void set(firmwarebug_t bug)
+    { m_bugs |= (1 << bug); }
+
+  void set(firmwarebug_defs bugs)
+    { m_bugs |= bugs.m_bugs; }
+
+private:
+  unsigned m_bugs;
+};
+
+
 // Print ATA debug messages?
 extern unsigned char ata_debugmode;
 
@@ -734,7 +756,8 @@ extern unsigned char ata_debugmode;
 extern bool dont_print_serial_number;
 
 // Get information from drive
-int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id);
+int ata_read_identity(ata_device * device, ata_identify_device * buf, bool fix_swapped_id,
+                      unsigned char * raw_buf = 0);
 int ataCheckPowerMode(ata_device * device);
 
 // Issue a no-data ATA command with optional sector count register value
@@ -747,11 +770,10 @@ bool ata_set_features(ata_device * device, unsigned char features, int sector_co
 int ataReadSmartValues(ata_device * device,struct ata_smart_values *);
 int ataReadSmartThresholds(ata_device * device, struct ata_smart_thresholds_pvt *);
 int ataReadErrorLog (ata_device * device, ata_smart_errorlog *data,
-                     unsigned char fix_firmwarebug);
+                     firmwarebug_defs firmwarebugs);
 int ataReadSelfTestLog(ata_device * device, ata_smart_selftestlog * data,
-                       unsigned char fix_firmwarebug);
+                       firmwarebug_defs firmwarebugs);
 int ataReadSelectiveSelfTestLog(ata_device * device, struct ata_selective_self_test_log *data);
-int ataSetSmartThresholds(ata_device * device, struct ata_smart_thresholds_pvt *);
 int ataReadLogDirectory(ata_device * device, ata_smart_log_directory *, bool gpl);
 
 // Read GP Log page(s)
@@ -763,7 +785,7 @@ bool ataReadSmartLog(ata_device * device, unsigned char logaddr,
                      void * data, unsigned nsectors);
 // Read SMART Extended Comprehensive Error Log
 bool ataReadExtErrorLog(ata_device * device, ata_smart_exterrlog * log,
-                        unsigned nsectors);
+                        unsigned nsectors, firmwarebug_defs firwarebugs);
 // Read SMART Extended Self-test Log
 bool ataReadExtSelfTestLog(ata_device * device, ata_smart_extselftestlog * log,
                            unsigned nsectors);
@@ -799,14 +821,14 @@ int ataWriteSelectiveSelfTestLog(ata_device * device, ata_selective_selftest_arg
                                  const ata_smart_values * sv, uint64_t num_sectors,
                                  const ata_selective_selftest_args * prev_spans = 0);
 
-// Returns the latest compatibility of ATA/ATAPI Version the device
-// supports. Returns -1 if Version command is not supported
-int ataVersionInfo(const char ** description, const ata_identify_device * drive, unsigned short * minor);
-
 // Get World Wide Name (WWN) fields.
 // Return NAA field or -1 if WWN is unsupported.
 int ata_get_wwn(const ata_identify_device * id, unsigned & oui, uint64_t & unique_id);
 
+// Get nominal media rotation rate.
+// Returns: 0 = not reported, 1 = SSD, >1 = HDD rpm, < 0 = -(Unknown value)
+int ata_get_rotation_rate(const ata_identify_device * id);
+
 // If SMART supported, this is guaranteed to return 1 if SMART is enabled, else 0.
 int ataDoesSmartWork(ata_device * device);
 
@@ -883,7 +905,8 @@ std::string ata_format_attr_raw_value(const ata_smart_attribute & attr,
 
 // Get attribute name
 std::string ata_get_smart_attr_name(unsigned char id,
-                                    const ata_vendor_attr_defs & defs);
+                                    const ata_vendor_attr_defs & defs,
+                                    int rpm = 0);
 
 // External handler function, for when a checksum is not correct.  Can
 // simply return if no action is desired, or can print error messages
@@ -899,15 +922,6 @@ int ata_find_attr_index(unsigned char id, const ata_smart_values & smartval);
 unsigned char ata_return_temperature_value(const ata_smart_values * data, const ata_vendor_attr_defs & defs);
 
 
-// This are the meanings of the Self-test failure checkpoint byte.
-// This is in the self-test log at offset 4 bytes into the self-test
-// descriptor and in the SMART READ DATA structure at byte offset
-// 371. These codes are not well documented.  The meanings returned by
-// this routine are used (at least) by Maxtor and IBM. Returns NULL if
-// not recognized.
-const char *SelfTestFailureCodeName(unsigned char which);
-
-
 #define MAX_ATTRIBUTE_NUM 256
 
 // Parse vendor attribute display def (-v option).
@@ -924,6 +938,13 @@ unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs & defs,
 // parse_attribute_def().
 std::string create_vendor_attribute_arg_list();
 
+// Parse firmwarebug def (-F option).
+// Return false on error.
+bool parse_firmwarebug_def(const char * opt, firmwarebug_defs & firmwarebugs);
+
+// Return a string of valid argument words for parse_firmwarebug_def()
+const char * get_valid_firmwarebug_args();
+
 
 // These are two of the functions that are defined in os_*.c and need
 // to be ported to get smartmontools onto another OS.
@@ -935,12 +956,6 @@ std::string create_vendor_attribute_arg_list();
 //int areca_command_interface(int fd, int disknum, smart_command_set command, int select, char *data);
 
 
-// Optional functions of os_*.c
-#ifdef HAVE_ATA_IDENTIFY_IS_CACHED
-// Return true if OS caches the ATA identify sector
-//int ata_identify_is_cached(int fd);
-#endif
-
 // This function is exported to give low-level capability
 int smartcommandhandler(ata_device * device, smart_command_set command, int select, char *data);
 
@@ -957,7 +972,7 @@ int ataPrintSmartSelfTestEntry(unsigned testnum, unsigned char test_type,
 
 // Print Smart self-test log, used by smartctl and smartd.
 int ataPrintSmartSelfTestlog(const ata_smart_selftestlog * data, bool allentries,
-                             unsigned char fix_firmwarebug);
+                             firmwarebug_defs firmwarebugs);
 
 // Get capacity and sector sizes from IDENTIFY data
 struct ata_size_info
diff --git a/ataidentify.cpp b/ataidentify.cpp
new file mode 100644 (file)
index 0000000..900cd20
--- /dev/null
@@ -0,0 +1,708 @@
+/*
+ * ataidentify.cpp
+ *
+ * Home page of code is: http://smartmontools.sourceforge.net
+ *
+ * Copyright (C) 2012-13 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/>.
+ *
+ */
+
+#include "config.h"
+#include "ataidentify.h"
+
+const char * ataidentify_cpp_cvsid = "$Id: ataidentify.cpp 3785 2013-03-07 21:58:05Z chrfranke $"
+  ATAIDENTIFY_H_CVSID;
+
+#include "int64.h"
+#include "utility.h"
+
+
+// Table 12 of X3T10/0948D (ATA-2) Revision 4c, March 18, 1996
+// Table 9 of X3T13/2008D (ATA-3) Revision 7b, January 27, 1997
+// Tables 11 and 13 of T13/1153D (ATA/ATAPI-4) revision 18, August 19, 1998
+// Tables 20 and 22 of T13/1321D (ATA/ATAPI-5) Revision 3, February 29, 2000
+// Tables 27 and 29 of T13/1410D (ATA/ATAPI-6) Revision 3b, February 26, 2002
+// Tables 16 and 18 of T13/1532D (ATA/ATAPI-7) Volume 1 Revision 4b, April 21, 2004
+// Tables 29 and 39 of T13/1699-D (ATA8-ACS) Revision 6a, September 6, 2008
+// Tables 50 and 61 of T13/2015-D (ACS-2) Revision 7, June 22, 2011
+// Tables 51 and 56 of T13/2161-D (ACS-3) Revision 4g, February 27, 2013
+
+const char * const identify_descriptions[] = {
+  "  0 General configuration",
+    ". 15 Device identifier: 0 = ATA, 1 = ATAPI",
+    ". 14:8 ATA: Vendor specific [RET-3]",
+    ". 14 ATAPI: Must be set to 0",
+    ". 13 ATAPI: Reserved",
+    ". 12:8 ATAPI: Command set: 0x05 = CD/DVD",
+    ". 7 Removable media device",
+    ". 6 ATA: Not removable controller and/or device [OBS-6]",
+    ". 5:3 ATA: Vendor specific [RET-3]",
+    ". 6:5 ATAPI: DRQ after PACKET cmd: 0x0 = 3ms, 0x2 = 50us",
+    ". 4:3 ATAPI: Reserved",
+    ". 2 Response incomplete",
+    ". 1 ATA: Vendor specific [RET-3]",
+    ". 0 ATA: Reserved",
+    ". 1:0 ATAPI: Packet size: 0x0 = 12 byte, 0x1 = 16 byte",
+
+  "  1 Cylinders [OBS-6]",
+  "  2 Specific configuration (0x37c8/738c/8c73/c837)",
+  "  3 Heads [OBS-6]",
+  "  4 Vendor specific [RET-3]",
+  "  5 Vendor specific [RET-3]",
+  "  6 Sectors per track [OBS-6]",
+  "  7-8 Reserved for CFA (Sectors per card)",
+  "  9 Vendor specific [RET-4]",
+  " 10-19 Serial number (String)",
+  " 20 Vendor specific [RET-3]",
+  " 21 Vendor specific [RET-3]",
+  " 22 Vendor specific bytes on READ/WRITE LONG [OBS-4]",
+  " 23-26 Firmware revision (String)",
+  " 27-46 Model number (String)",
+
+  " 47 READ/WRITE MULTIPLE support",
+    ". 15:8 Must be set to 0x80",
+    ". 7:0 Maximum sectors per DRQ on READ/WRITE MULTIPLE",
+
+  " 48 Trusted Computing feature set options",
+    ". 15:14 Must be set to 0x1",
+    ". 13:1 Reserved for the Trusted Computing Group",
+    ". 0 Trusted Computing feature set supported",
+
+  " 49 Capabilities",
+    ". 15:14 ATA: Reserved for IDENTIFY PACKET DEVICE",
+    ". 15 ATAPI: Interleaved DMA supported [OBS-8]",
+    ". 14 ATAPI: Command queuing supported [OBS-8]",
+    ". 13 ATA: Standard standby timer values supported",
+    ". 13 ATAPI: Overlap operation supported [OBS-8]",
+    ". 12 ATA: Reserved for IDENTIFY PACKET DEVICE",
+    ". 12 ATAPI: ATA software reset required [OBS-5]",
+    ". 11 IORDY supported",
+    ". 10 IORDY may be disabled",
+    ". 9 LBA supported",
+    ". 8 DMA supported",
+    ". 7:0 Vendor specific [RET-4]",
+
+  " 50 Capabilities",
+    ". 15:14 Must be set to 0x1",
+    ". 13:2 Reserved",
+    ". 1 Reserved [OBS-6]",
+    ". 0 Vendor specific minimum standby timer value",
+
+  " 51 PIO data transfer mode [OBS-5]",
+  " 52 Single Word DMA data transfer mode [OBS-3]",
+
+  " 53 Field validity / Free-fall Control",
+    ". 15:8 Free-fall Control sensitivity",
+    ". 7:3 Reserved",
+    ". 2 Word 88 (Ultra DMA modes) is valid",
+    ". 1 Words 64-70 (PIO modes) are valid",
+    ". 0 Words 54-58 (CHS) are valid [OBS-6]",
+
+  " 54 Current cylinders [OBS-6]",
+  " 55 Current heads [OBS-6]",
+  " 56 Current sectors per track [OBS-6]",
+  " 57-58 Current capacity in sectors (DWord) [OBS-6]",
+
+  " 59 Sanitize Device - READ/WRITE MULTIPLE support",
+    ". 15 BLOCK ERASE EXT supported",
+    ". 14 OVERWRITE EXT supported",
+    ". 13 CRYPTO SCRAMBLE EXT supported",
+    ". 12 Sanitize Device feature set supported",
+    ". 11:9 Reserved",
+    ". 8 Bits 7:0 are valid",
+    ". 7:0 Current sectors per DRQ on READ/WRITE MULTIPLE",
+
+  " 60-61 User addressable sectors for 28-bit commands (DWord)",
+  " 62 Single Word DMA modes [OBS-3]",
+
+  " 63 Multiword DMA modes",
+    ". 15:11 Reserved",
+    ". 10 Multiword DMA mode 2 selected",
+    ". 9 Multiword DMA mode 1 selected",
+    ". 8 Multiword DMA mode 0 selected",
+    ". 7:3 Reserved",
+    ". 2 Multiword DMA mode 2 and below supported",
+    ". 1 Multiword DMA mode 1 and below supported",
+    ". 0 Multiword DMA mode 0 supported",
+
+  " 64 PIO modes",
+    ". 15:2 Reserved",
+    ". 1 PIO mode 4 supported",
+    ". 0 PIO mode 3 supported",
+
+  " 65 Minimum Multiword DMA cycle time per word in ns",
+  " 66 Recommended Multiword DMA cycle time in ns",
+  " 67 Minimum PIO cycle time without flow control in ns",
+  " 68 Minimum PIO cycle time with IORDY flow control in ns",
+
+  " 69 Additional support",
+    ". 15 CFast specification supported",
+    ". 14 Deterministic data after trim supported",
+    ". 13 LPS Alignment Error Reporting Control supported",
+    ". 12 DCO IDENTIFY/SET DMA supported [OBS-ACS-3]",
+    ". 11 READ BUFFER DMA supported",
+    ". 10 WRITE BUFFER DMA supported",
+    ". 9 SET MAX SET PASSWORD/UNLOCK DMA supported [OBS-ACS-3]",
+    ". 8 DOWNLOAD MICROCODE DMA supported",
+    ". 7 Reserved for IEEE 1667",
+    ". 6 Optional ATA device 28-bit commands supported",
+    ". 5 Trimmed LBA range(s) returning zeroed data supported",
+    ". 4 Device encrypts all user data",
+    ". 3 Extended number of user addressable sectors supported",
+    ". 2 All write cache is non-volatile",
+    ". 1:0 Reserved",
+
+  " 70 Reserved",
+  " 71-74 ATA: Reserved for IDENTIFY PACKET DEVICE",
+  " 71 ATAPI: Time in ns from PACKET to bus release [OBS-8]",
+  " 72 ATAPI: Time in ns from SERVICE to BSY cleared [OBS-8]",
+  " 73-74 ATAPI: Reserved",
+
+  " 75 Queue depth",
+    ". 15:5 Reserved",
+    ". 4:0 Maximum queue depth - 1",
+
+  " 76 Serial ATA capabilities",
+    ". 15 READ LOG DMA EXT as equiv to READ LOG EXT supported",
+    ". 14 Device Auto Partial to Slumber transitions supported",
+    ". 13 Host Auto Partial to Slumber transitions supported",
+    ". 12 NCQ priority information supported",
+    ". 11 Unload while NCQ commands are outstanding supported",
+    ". 10 Phy Event Counters supported",
+    ". 9 Receipt of host initiated PM requests supported",
+    ". 8 NCQ feature set supported",
+    ". 7:4 Reserved for Serial ATA",
+    ". 3 SATA Gen3 signaling speed (6.0 Gb/s) supported",
+    ". 2 SATA Gen2 signaling speed (3.0 Gb/s) supported",
+    ". 1 SATA Gen1 signaling speed (1.5 Gb/s) supported",
+    ". 0 Must be set to 0",
+
+  " 77 Serial ATA additional capabilities", // ACS-3
+    ". 15:7 Reserved for Serial ATA",
+    ". 6 RECEIVE/SEND FPDMA QUEUED supported",
+    ". 5 NCQ Queue Management supported",
+    ". 4 NCQ Streaming supported",
+    ". 3:1 Current Serial ATA signal speed",
+    ". 0 Must be set to 0",
+
+  " 78 Serial ATA features supported",
+    ". 15:8 Reserved for Serial ATA",
+    ". 7 NCQ Autosense supported", // ACS-3
+    ". 6 Software Settings Preservation supported",
+    ". 5 Hardware Feature Control supported", // ACS-3
+    ". 4 In-order data delivery supported",
+    ". 3 Device initiated power management supported",
+    ". 2 DMA Setup auto-activation supported",
+    ". 1 Non-zero buffer offsets supported",
+    ". 0 Must be set to 0",
+
+  " 79 Serial ATA features enabled",
+    ". 15:8 Reserved for Serial ATA",
+    ". 7 Automatic Partial to Slumber transitions enabled", // ACS-3
+    ". 6 Software Settings Preservation enabled",
+    ". 5 Hardware Feature Control enabled", // ACS-3
+    ". 4 In-order data delivery enabled",
+    ". 3 Device initiated power management enabled",
+    ". 2 DMA Setup auto-activation enabled",
+    ". 1 Non-zero buffer offsets enabled",
+    ". 0 Must be set to 0",
+
+  " 80 Major version number",
+    ". 15:11 Reserved",
+    ". 10 ACS-3 supported",
+    ". 9 ACS-2 supported",
+    ". 8 ATA8-ACS supported",
+    ". 7 ATA/ATAPI-7 supported",
+    ". 6 ATA/ATAPI-6 supported",
+    ". 5 ATA/ATAPI-5 supported",
+    ". 4 ATA/ATAPI-4 supported [OBS-8]",
+    ". 3 ATA-3 supported [OBS-7]",
+    ". 2 ATA-2 supported [OBS-6]",
+    ". 1 ATA-1 supported [OBS-5]",
+    ". 0 Reserved",
+
+  " 81 Minor version number",
+
+  " 82 Commands and feature sets supported",
+    ". 15 IDENTIFY DEVICE DMA supported [OBS-4]", // ATA-4 r07-r14 only
+    ". 14 NOP supported",
+    ". 13 READ BUFFER supported",
+    ". 12 WRITE BUFFER supported",
+    ". 11 WRITE VERIFY supported [OBS-4]", // ATA-4 r07-r13 only
+    ". 10 HPA feature set supported [OBS-ACS-3]",
+    ". 9 DEVICE RESET supported", // ATA:0, ATAPI:1
+    ". 8 SERVICE interrupt supported [OBS-ACS-2]",
+    ". 7 Release interrupt supported [OBS-ACS-2]",
+    ". 6 Read look-ahead supported",
+    ". 5 Volatile write cache supported",
+    ". 4 PACKET feature set supported", // ATA:0, ATAPI:1
+    ". 3 Power Management feature set supported",
+    ". 2 Removable Media feature set supported [OBS-8]",
+    ". 1 Security feature set supported",
+    ". 0 SMART feature set supported",
+
+  " 83 Commands and feature sets supported",
+    ". 15:14 Must be set to 0x1",
+    ". 13 FLUSH CACHE EXT supported",
+    ". 12 FLUSH CACHE supported",
+    ". 11 DCO feature set supported [OBS-ACS-3]",
+    ". 10 48-bit Address feature set supported",
+    ". 9 AAM feature set supported [OBS-ACS-2]",
+    ". 8 SET MAX security extension supported [OBS-ACS-3]",
+    ". 7 Reserved for Address Offset Reserved Area Boot Method",
+    ". 6 SET FEATURES subcommand required to spin-up",
+    ". 5 PUIS feature set supported",
+    ". 4 Removable Media Status Notification supported [OBS-8]",
+    ". 3 APM feature set supported",
+    ". 2 CFA feature set supported",
+    ". 1 TCQ feature set supported [OBS-ACS-2]",
+    ". 0 DOWNLOAD MICROCODE supported",
+
+  " 84 Commands and feature sets supported",
+    ". 15:14 Must be set to 0x1",
+    ". 13 IDLE IMMEDIATE with UNLOAD feature supported",
+    ". 12:11 Reserved for TLC [OBS-ACS-3]",
+    ". 10 URG bit for WRITE STREAM (DMA) EXT supported [OBS-8]",
+    ". 9 URG bit for READ STREAM (DMA) EXT supported [OBS-8]",
+    ". 8 64-bit World Wide Name supported",
+    ". 7 WRITE DMA QUEUED FUA EXT supported",
+    ". 6 WRITE DMA/MULTIPLE FUA EXT supported",
+    ". 5 GPL feature set supported",
+    ". 4 Streaming feature set supported [OBS-ACS-3]",
+    ". 3 Media Card Pass Through Command supported [OBS-ACS-2]",
+    ". 2 Media serial number supported", // ACS-3 r3 or later: Reserved
+    ". 1 SMART self-test supported",
+    ". 0 SMART error logging supported",
+
+  " 85 Commands and feature sets supported or enabled",
+    ". 15 IDENTIFY DEVICE DMA supported [OBS-4]", // ATA-4 r07-r14 only
+    ". 14 NOP supported",
+    ". 13 READ BUFFER supported",
+    ". 12 WRITE BUFFER supported",
+    ". 11 WRITE VERIFY supported [OBS-4]", // ATA-4 r07-r13 only
+    ". 10 HPA feature set supported [OBS-ACS-3]",
+    ". 9 DEVICE RESET supported", // ATA:0, ATAPI:1
+    ". 8 SERVICE interrupt enabled [OBS-ACS-2]",
+    ". 7 Release interrupt enabled [OBS-ACS-2]",
+    ". 6 Read look-ahead enabled",
+    ". 5 Write cache enabled",
+    ". 4 PACKET feature set supported", // ATA:0, ATAPI:1
+    ". 3 Power Management feature set supported",
+    ". 2 Removable Media feature set supported [OBS-8]",
+    ". 1 Security feature set enabled",
+    ". 0 SMART feature set enabled",
+
+  " 86 Commands and feature sets supported or enabled",
+    ". 15 Words 119-120 are valid",
+    ". 14 Reserved",
+    ". 13 FLUSH CACHE EXT supported",
+    ". 12 FLUSH CACHE supported",
+    ". 11 DCO feature set supported [OBS-ACS-3]",
+    ". 10 48-bit Address features set supported",
+    ". 9 AAM feature set enabled [OBS-ACS-2]",
+    ". 8 SET MAX security extension enabled [OBS-ACS-3]",
+    ". 7 Reserved for Address Offset Reserved Area Boot Method",
+    ". 6 SET FEATURES subcommand required to spin-up",
+    ". 5 PUIS feature set enabled",
+    ". 4 Removable Media Status Notification enabled [OBS-8]",
+    ". 3 APM feature set enabled",
+    ". 2 CFA feature set supported",
+    ". 1 TCQ feature set supported [OBS-ACS-2]",
+    ". 0 DOWNLOAD MICROCODE supported",
+
+  " 87 Commands and feature sets supported or enabled",
+    ". 15:14 Must be set to 0x1",
+    ". 13 IDLE IMMEDIATE with UNLOAD FEATURE supported",
+    ". 12:11 Reserved for TLC [OBS-ACS-3]",
+    ". 10 URG bit for WRITE STREAM (DMA) EXT supported [OBS-8]",
+    ". 9 URG bit for READ STREAM (DMA) EXT supported [OBS-8]",
+    ". 8 64-bit World Wide Name supported",
+    ". 7 WRITE DMA QUEUED FUA EXT supported [OBS-ACS-2]",
+    ". 6 WRITE DMA/MULTIPLE FUA EXT supported",
+    ". 5 GPL feature set supported",
+    ". 4 Valid CONFIGURE STREAM has been executed [OBS-8]",
+    ". 3 Media Card Pass Through Command supported [OBS-ACS-2]",
+    ". 2 Media serial number is valid",
+    ". 1 SMART self-test supported",
+    ". 0 SMART error logging supported",
+
+  " 88 Ultra DMA modes",
+    ". 15 Reserved",
+    ". 14 Ultra DMA mode 6 selected",
+    ". 13 Ultra DMA mode 5 selected",
+    ". 12 Ultra DMA mode 4 selected",
+    ". 11 Ultra DMA mode 3 selected",
+    ". 10 Ultra DMA mode 2 selected",
+    ". 9 Ultra DMA mode 1 selected",
+    ". 8 Ultra DMA mode 0 selected",
+    ". 7 Reserved",
+    ". 6 Ultra DMA mode 6 and below supported",
+    ". 5 Ultra DMA mode 5 and below supported",
+    ". 4 Ultra DMA mode 4 and below supported",
+    ". 3 Ultra DMA mode 3 and below supported",
+    ". 2 Ultra DMA mode 2 and below supported",
+    ". 1 Ultra DMA mode 1 and below supported",
+    ". 0 Ultra DMA mode 0 supported",
+
+  " 89 SECURITY ERASE UNIT time",
+  " 90 ENHANCED SECURITY ERASE UNIT time",
+  " 91 Current APM level",
+  " 92 Master password revision code",
+
+  " 93 Hardware reset result (PATA)",
+    ". 15:14 Must be set to 0x1",
+    ". 13 Device detected CBLID- above(1)/below(0) ViHB",
+    ". 12 Reserved",
+    ". 11 Device 1 asserted PDIAG-",
+    ". 10:9 Device 1 detection method: -, Jumper, CSEL, other",
+    ". 8 Must be set to 1",
+    ". 7 Reserved",
+    ". 6 Device 0 responds when device 1 selected",
+    ". 5 Device 0 detected the assertion of DASP-",
+    ". 4 Device 0 detected the assertion of PDIAG-",
+    ". 3 Device 0 passed diagnostics",
+    ". 2:1 Device 0 detection method: -, Jumper, CSEL, other",
+    ". 0 Must be set to 1",
+
+  " 94 AAM level [OBS-ACS-2]",
+    ". 15:8 Recommended AAM level [OBS-ACS-2]",
+    ". 7:0 Current AAM level [OBS-ACS-2]",
+
+  " 95 Stream Minimum Request Size",
+  " 96 Streaming Transfer Time - DMA",
+  " 97 Streaming Access Latency - DMA and PIO",
+  " 98-99 Streaming Performance Granularity (DWord)",
+  "100-103 User addressable sectors for 48-bit commands (QWord)",
+  "104 Streaming Transfer Time - PIO",
+  "105 Max blocks of LBA Range Entries per DS MANAGEMENT cmd",
+
+  "106 Physical sector size / logical sector size",
+    ". 15:14 Must be set to 0x1",
+    ". 13 Multiple logical sectors per physical sector",
+    ". 12 Logical Sector longer than 256 words",
+    ". 11:4 Reserved",
+    ". 3:0 2^X logical sectors per physical sector",
+
+  "107 Inter-seek delay for ISO 7779 acoustic testing",
+  "108-111 64-bit World Wide Name",
+  "112-115 Reserved for a 128-bit World Wide Name",
+  "116 Reserved for TLC [OBS-ACS-3]",
+  "117-118 Logical sector size (DWord)",
+
+  "119 Commands and feature sets supported",
+    ". 15:14 Must be set to 0x1",
+    ". 13:10 Reserved",
+    ". 9 DSN feature set supported", // ACS-3
+    ". 8 Accessible Max Address Config feature set supported", // ACS-3
+    ". 7 Extended Power Conditions feature set supported",
+    ". 6 Sense Data Reporting feature set supported",
+    ". 5 Free-fall Control feature set supported",
+    ". 4 DOWNLOAD MICROCODE with mode 3 supported",
+    ". 3 READ/WRITE LOG DMA EXT supported",
+    ". 2 WRITE UNCORRECTABLE EXT supported",
+    ". 1 Write-Read-Verify feature set supported",
+    ". 0 Reserved for DDT [OBS-ACS-3]",
+
+  "120 Commands and feature sets supported or enabled",
+    ". 15:14 Must be set to 0x1",
+    ". 13:10 Reserved",
+    ". 9 DSN feature set enabled", // ACS-3
+    ". 8 Reserved",
+    ". 7 Extended Power Conditions feature set enabled",
+    ". 6 Sense Data Reporting feature set enabled",
+    ". 5 Free-fall Control feature set enabled",
+    ". 4 DOWNLOAD MICROCODE with mode 3 supported",
+    ". 3 READ/WRITE LOG DMA EXT supported",
+    ". 2 WRITE UNCORRECTABLE EXT supported",
+    ". 1 Write-Read-Verify feature set enabled",
+    ". 0 Reserved for DDT [OBS-ACS-3]",
+
+  "121-126 ATA: Reserved",
+  "121-124 ATAPI: Reserved",
+  "125 ATAPI: Byte count = 0 behavior",
+  "126 ATAPI: Byte count = 0 behavior [OBS-6]",
+
+  "127 Removable Media Status Notification [OBS-8]",
+    ". 15:1 Reserved",
+    ". 0 Removable Media Status Notification supported",
+
+  "128 Security status",
+    ". 15:9 Reserved",
+    ". 8 Master password capability: 0 = High, 1 = Maximum",
+    ". 7:6 Reserved",
+    ". 5 Enhanced security erase supported",
+    ". 4 Security count expired",
+    ". 3 Security frozen",
+    ". 2 Security locked",
+    ". 1 Security enabled",
+    ". 0 Security supported",
+
+  "129-159 Vendor specific",
+
+  "160 CFA power mode",
+  // ". 15 Word 160 supported",
+  // ". 14 Reserved",
+  // ". 13 CFA power mode 1 is required for some commands",
+  // ". 12 CFA power mode 1 disabled",
+  // ". 11:0 Maximum current in mA",
+  "161-167 Reserved for CFA",
+
+  "168 Form factor",
+    ". 15:4 Reserved",
+    ". 3:0 Nominal form factor: -, 5.25, 3.5, 2.5, 1.8, <1.8",
+
+  "169 Data Set Management support",
+    ". 15:1 Reserved",
+    ". 0 Trim bit in DATA SET MANAGEMENT command supported",
+
+  "170-173 Additional product identifier (String)",
+  "174-175 Reserved",
+  "176-205 Current media serial number (String)",
+
+  "206 SCT Command Transport",
+    ". 15:12 Vendor Specific",
+    ". 11:8 Reserved",
+    ". 7 Reserved for Serial ATA",
+    ". 6 Reserved",
+    ". 5 SCT Data Tables supported",
+    ". 4 SCT Feature Control supported",
+    ". 3 SCT Error Recovery Control supported",
+    ". 2 SCT Write Same supported",
+    ". 1 SCT Read/Write Long supported [OBS-ACS-2]",
+    ". 0 SCT Command Transport supported",
+
+  "207-208 Reserved for CE-ATA",
+
+  "209 Alignment of logical sectors",
+    ". 15:14 Must be set to 0x1",
+    ". 13:0 Logical sector offset",
+
+  "210-211 Write-Read-Verify sector count mode 3 (DWord)",
+  "212-213 Write-Read-Verify sector count mode 2 (DWord)",
+
+  "214 NV Cache capabilities [OBS-ACS-3]",
+    ". 15:12 NV Cache feature set version [OBS-ACS-3]",
+    ". 11:8 NV Cache Power Mode feature set version [OBS-ACS-3]",
+    ". 7:5 Reserved [OBS-ACS-3]",
+    ". 4 NV Cache feature set enabled [OBS-ACS-3]",
+    ". 3:2 Reserved",
+    ". 1 NV Cache Power Mode feature set enabled [OBS-ACS-3]",
+    ". 0 NV Cache Power Mode feature set supported [OBS-ACS-3]",
+
+  "215-216 NV Cache size in logical blocks (DWord) [OBS-ACS-3]",
+  "217 Nominal media rotation rate",
+  "218 Reserved",
+
+  "219 NV Cache options [OBS-ACS-3]",
+    ". 15:8 Reserved [OBS-ACS-3]",
+    ". 7:0 Estimated time to spin up in seconds [OBS-ACS-3]",
+
+  "220 Write-Read-Verify mode",
+    ". 15:8 Reserved",
+    ". 7:0 Write-Read-Verify feature set current mode",
+
+  "221 Reserved",
+
+  "222 Transport major version number",
+    ". 15:12 Transport type: 0x0 = Parallel, 0x1 = Serial",
+    ". 11:7 Reserved    | Reserved",
+    ". 6 Reserved    | SATA 3.1",
+    ". 5 Reserved    | SATA 3.0",
+    ". 4 Reserved    | SATA 2.6",
+    ". 3 Reserved    | SATA 2.5",
+    ". 2 Reserved    | SATA II: Extensions",
+    ". 1 ATA/ATAPI-7 | SATA 1.0a",
+    ". 0 ATA8-APT    | ATA8-AST",
+
+  "223 Transport minor version number",
+  "224-229 Reserved",
+  "230-233 Extended number of user addressable sectors (QWord)",
+  "234 Minimum blocks per DOWNLOAD MICROCODE mode 3 command",
+  "235 Maximum blocks per DOWNLOAD MICROCODE mode 3 command",
+  "236-254 Reserved",
+
+  "255 Integrity word",
+    ". 15:8 Checksum",
+    ". 7:0 Signature"
+};
+
+const int num_identify_descriptions = sizeof(identify_descriptions)/sizeof(identify_descriptions[0]);
+
+static inline unsigned short get_word(const void * id, int word)
+{
+  const unsigned char * p = ((const unsigned char *)id) + 2 * word;
+  return p[0] + (p[1] << 8);
+}
+
+void ata_print_identify_data(const void * id, bool all_words, int bit_level)
+{
+  // ATA or ATAPI ?
+  unsigned short w = get_word(id, 0);
+  bool is_atapi = ((w & 0x8000) && (w != 0x848a/*CompactFlash Signature*/));
+
+  int prev_word = -1, prev_bit = -1;
+  pout("Word     %s Value   Description\n", (bit_level >= 0 ? "Bit    " : " "));
+
+  for (int i = 0; i < num_identify_descriptions; i++) {
+    // Parse table entry
+    const char * desc = identify_descriptions[i];
+
+    int word = prev_word, word2 = -1;
+    int bit = -1, bit2 = -1;
+
+    int nc;
+    unsigned v1, v2;
+    if (word >= 0 && sscanf(desc, ". %u:%u %n", &v1, &v2, (nc=-1, &nc)) == 2 && nc > 0 && 16 > v1 && v1 > v2) {
+      bit = v1; bit2 = v2;
+    }
+    else if (word >= 0 && sscanf(desc, ". %u %n", &v1, (nc=-1, &nc)) == 1 && nc > 0 && v1 < 16) {
+      bit = v1;
+    }
+    else if (sscanf(desc, "%u-%u %n", &v1, &v2, (nc=-1, &nc)) == 2 && nc > 0 && v1 < v2 && v2 < 256) {
+      word = v1, word2 = v2;
+    }
+    else if (sscanf(desc, "%u %n", &v1, (nc=-1, &nc)) == 1 && nc > 0 && v1 < 256) {
+      word = v1;
+    }
+    else {
+      pout("Error: #%d: Syntax\n", i);
+      continue;
+    }
+    desc += nc;
+
+    // Check for ATA/ATAPI specific entries
+    if (str_starts_with(desc, "ATA: ")) {
+      if (is_atapi)
+        continue;
+      desc += sizeof("ATA: ")-1;
+    }
+    else if (str_starts_with(desc, "ATAPI: ")) {
+      if (!is_atapi)
+        continue;
+    }
+
+    // Check table entry
+    if (bit < 0) {
+      if (word != prev_word+1) {
+        pout("Error: #%d: Missing word %d\n", i, prev_word+1);
+        return;
+      }
+      else if (prev_bit > 0) {
+        pout("Error: #%d: Missing bit 0 from word %d\n", i, prev_word);
+        return;
+      }
+    }
+    else if (!((prev_bit < 0 && bit == 15) || bit == prev_bit-1)) {
+      pout("Error: #%d: Missing bit %d from word %d\n", i, bit+1, word);
+      return;
+    }
+
+    w = get_word(id, word);
+    bool w_is_set = (w != 0x0000 && w != 0xffff);
+
+    if (bit >= 0) {
+      int b;
+      if (bit2 >= 0)
+        b = (w >> bit2) & ~(~0 << (bit-bit2+1));
+      else
+        b = (w >> bit) & 1;
+
+      if (   (bit_level >= 0 && b)
+          || (bit_level >= 1 && w_is_set)
+          || (bit_level >= 2 && all_words)) {
+        if (bit2 >= 0) {
+          // Print bitfield
+          char valstr[20];
+          snprintf(valstr, sizeof(valstr), "0x%0*x", (bit - bit2 + 4) >> 2, b);
+          pout("%4d     %2d:%-2d  %6s   %s\n", word, bit, bit2, valstr, desc);
+        }
+        else {
+          // Print bit
+          pout("%4d     %2d          %u   %s\n", word, bit, b, desc);
+        }
+      }
+
+      prev_bit = (bit2 >= 0 ? bit2 : bit);
+    }
+    else {
+      if (word2 >= 0) {
+        for (int j = word+1; !w_is_set && j <= word2; j++) {
+           if (get_word(id, j) != w)
+             w_is_set = true;
+        }
+
+        // Print word array
+        if (all_words || w_is_set) {
+          pout("%s%4d-%-3d  %s",
+               (bit_level >= 0 ? "\n" : ""), word, word2,
+               (bit_level >= 0 ? "-     " : ""));
+
+          if (!w_is_set) {
+            pout("0x%02x...  %s\n", w & 0xff, desc);
+          }
+          else {
+            bool is_str = !!strstr(desc, "(String)");
+            pout(".        %s", desc);
+
+            for (int j = word; j <= word2; j += 4) {
+              if (j + 2*4 < word2 && !nonempty((const unsigned char *)id + 2*j, 2*(word2-j+1))) {
+                // Remaining words are null
+                pout("\n%4d-%-3d  %s0x0000:0000:0000:00...", j, word2,
+                     (bit_level >= 0 ? ".     " : ""));
+                break;
+              }
+              // Print 4 words in a row
+              pout("\n%4d-%-3d  %s0x", j, (j+3 <= word2 ? j+3 : word2),
+                   (bit_level >= 0 ? ".     " : ""));
+              int k;
+              for (k = 0; k < 4 && j+k <= word2; k++)
+                pout("%s%04x",  (k == 0 ? "" : ":"), get_word(id, j+k));
+
+              if (is_str) {
+                // Append little endian string
+                pout("%*s  \"", 20 - 5 * k, "");
+                for (k = 0; k < 4 && j+k <= word2; k++) {
+                  char c2 = ((const char *)id)[2*(j+k)    ];
+                  char c1 = ((const char *)id)[2*(j+k) + 1];
+                  pout("%c%c", (' ' <= c1 && c1 <= '~' ? c1 : '.'),
+                               (' ' <= c2 && c2 <= '~' ? c2 : '.') );
+                }
+                pout("\"");
+              }
+            }
+
+            // Print decimal value of D/QWords
+            if (word + 1 == word2 && strstr(desc, "(DWord)"))
+              pout("  (%u)\n", ((unsigned)get_word(id, word2) << 16) | w);
+            else if (word + 3 == word2 && strstr(desc, "(QWord)"))
+              pout("  (%"PRIu64")\n", ((uint64_t)get_word(id, word + 3) << 48)
+                                    | ((uint64_t)get_word(id, word + 2) << 32)
+                                    | ((unsigned)get_word(id, word + 1) << 16) | (unsigned)w);
+            else
+              pout("\n");
+          }
+        }
+      }
+      else {
+        // Print word
+        if (all_words || w_is_set)
+          pout("%s%4d      %s0x%04x   %s\n",
+               (bit_level >= 0 ? "\n" : ""), word,
+               (bit_level >= 0 ? "-     " : ""), w, desc);
+      }
+
+      prev_word = (word2 >= 0 ? word2 : word);
+      prev_bit = -1;
+    }
+  }
+
+  pout("\n");
+}
diff --git a/ataidentify.h b/ataidentify.h
new file mode 100644 (file)
index 0000000..6375388
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * ataidentify.h
+ *
+ * Home page of code is: http://smartmontools.sourceforge.net
+ *
+ * Copyright (C) 2012 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/>.
+ *
+ */
+
+#ifndef ATAIDENTIFY_H
+#define ATAIDENTIFY_H
+
+#define ATAIDENTIFY_H_CVSID "$Id: ataidentify.h 3610 2012-09-20 21:27:19Z chrfranke $"
+
+void ata_print_identify_data(const void * id, bool all_words, int bit_level);
+
+#endif // ATAIDENTIFY_H
index 4fd2724f68c735f1741c1bed60bf0f02bd154465..51fe7d49c77ae99adb9e691cc29b97f84bd329cf 100644 (file)
@@ -4,7 +4,7 @@
  * Home page of code is: http://smartmontools.sourceforge.net
  *
  * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
 #include "int64.h"
 #include "atacmdnames.h"
 #include "atacmds.h"
+#include "ataidentify.h"
 #include "dev_interface.h"
 #include "ataprint.h"
 #include "smartctl.h"
 #include "utility.h"
 #include "knowndrives.h"
 
-const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3554 2012-06-01 20:11:46Z chrfranke $"
+const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3786 2013-03-07 22:09:17Z chrfranke $"
                                   ATAPRINT_H_CVSID;
 
 
@@ -60,10 +60,9 @@ static bool is_permissive()
 
 /* For the given Command Register (CR) and Features Register (FR), attempts
  * to construct a string that describes the contents of the Status
- * Register (ST) and Error Register (ER).  The caller passes the string
- * buffer and the return value is a pointer to this string.  If the
- * meanings of the flags of the error register are not known for the given
- * command then it returns NULL.
+ * Register (ST) and Error Register (ER).  If the meanings of the flags of
+ * the error register are not known for the given command then it returns an
+ * empty string.
  *
  * The meanings of the flags of the error register for all commands are
  * described in the ATA spec and could all be supported here in theory.
@@ -72,8 +71,7 @@ static bool is_permissive()
  * should probably be redesigned.
  */
 
-static const char * construct_st_er_desc(
-  char * s,
+static std::string format_st_er_desc(
   unsigned char CR, unsigned char FR,
   unsigned char ST, unsigned char ER,
   unsigned short SC,
@@ -111,6 +109,8 @@ static const char * construct_st_er_desc(
   for (i = 0; i < 8; i++)
     error_flag[i] = NULL;
 
+  std::string str;
+
   switch (CR) {
   case 0x10:  // RECALIBRATE
     error_flag[2] = abrt;
@@ -281,7 +281,7 @@ static const char * construct_st_er_desc(
       error_flag[2] = abrt;
       break;
     default:
-      return NULL;
+      return str; // ""
       break;
     }
     break;
@@ -291,7 +291,7 @@ static const char * construct_st_er_desc(
       error_flag[2] = abrt;
       break;
     default:
-      return NULL;
+      return str; // ""
       break;
     }
     break;
@@ -320,39 +320,34 @@ static const char * construct_st_er_desc(
     error_flag[2] = abrt;
     break;
   default:
-    return NULL;
+    return str; // ""
   }
 
-  s[0] = '\0';
-
   /* We ignore any status flags other than Device Fault and Error */
 
   if (uses_device_fault && (ST & (1 << 5))) {
-    strcat(s, "Device Fault");
+    str = "Device Fault";
     if (ST & 1)  // Error flag
-      strcat(s, "; ");
+      str += "; ";
   }
   if (ST & 1) {  // Error flag
     int count = 0;
 
-    strcat(s, "Error: ");
+    str += "Error: ";
     for (i = 7; i >= 0; i--)
       if ((ER & (1 << i)) && (error_flag[i])) {
         if (count++ > 0)
-           strcat(s, ", ");
-        strcat(s, error_flag[i]);
+           str += ", ";
+        str += error_flag[i];
       }
   }
 
   // If the error was a READ or WRITE error, print the Logical Block
   // Address (LBA) at which the read or write failed.
   if (print_lba) {
-    char tmp[128];
     // print number of sectors, if known, and append to print string
-    if (print_sector) {
-      snprintf(tmp, 128, " %d sectors", print_sector);
-      strcat(s, tmp);
-    }
+    if (print_sector)
+      str += strprintf(" %d sectors", print_sector);
 
     if (lba28_regs) {
       unsigned lba;
@@ -367,8 +362,7 @@ static const char * construct_st_er_desc(
       lba <<= 8;
       // bits 0-7:   SN
       lba  |= lba28_regs->sector_number;
-      snprintf(tmp, 128, " at LBA = 0x%08x = %u", lba, lba);
-      strcat(s, tmp);
+      str += strprintf(" at LBA = 0x%08x = %u", lba, lba);
     }
     else if (lba48_regs) {
       // This assumes that upper LBA registers are 0 for 28-bit commands
@@ -386,18 +380,17 @@ static const char * construct_st_er_desc(
       lba48  |= lba48_regs->lba_mid_register;
       lba48 <<= 8;
       lba48  |= lba48_regs->lba_low_register;
-      snprintf(tmp, 128, " at LBA = 0x%08"PRIx64" = %"PRIu64, lba48, lba48);
-      strcat(s, tmp);
+      str += strprintf(" at LBA = 0x%08"PRIx64" = %"PRIu64, lba48, lba48);
     }
   }
 
-  return s;
+  return str;
 }
 
-static inline const char * construct_st_er_desc(char * s,
+static inline std::string format_st_er_desc(
   const ata_smart_errorlog_struct * data)
 {
-  return construct_st_er_desc(s,
+  return format_st_er_desc(
     data->commands[4].commandreg,
     data->commands[4].featuresreg,
     data->error_struct.status,
@@ -406,10 +399,10 @@ static inline const char * construct_st_er_desc(char * s,
     &data->error_struct, (const ata_smart_exterrlog_error *)0);
 }
 
-static inline const char * construct_st_er_desc(char * s,
+static inline std::string format_st_er_desc(
   const ata_smart_exterrlog_error_log * data)
 {
-  return construct_st_er_desc(s,
+  return format_st_er_desc(
     data->commands[4].command_register,
     data->commands[4].features_register,
     data->error.status_register,
@@ -418,8 +411,141 @@ static inline const char * construct_st_er_desc(char * s,
     (const ata_smart_errorlog_error_struct *)0, &data->error);
 }
 
+
+static int find_msb(unsigned short word)
+{
+  for (int bit = 15; bit >= 0; bit--)
+    if (word & (1 << bit))
+      return bit;
+  return -1;
+}
+
+static const char * get_ata_major_version(const ata_identify_device * drive)
+{
+  switch (find_msb(drive->major_rev_num)) {
+    case 10: return "ACS-3";
+    case  9: return "ACS-2";
+    case  8: return "ATA8-ACS";
+    case  7: return "ATA/ATAPI-7";
+    case  6: return "ATA/ATAPI-6";
+    case  5: return "ATA/ATAPI-5";
+    case  4: return "ATA/ATAPI-4";
+    case  3: return "ATA-3";
+    case  2: return "ATA-2";
+    case  1: return "ATA-1";
+    default: return 0;
+  }
+}
+
+static const char * get_ata_minor_version(const ata_identify_device * drive)
+{
+  switch (drive->minor_rev_num) {
+    case 0x0001: return "ATA-1 X3T9.2/781D prior to revision 4";
+    case 0x0002: return "ATA-1 published, ANSI X3.221-1994";
+    case 0x0003: return "ATA-1 X3T9.2/781D revision 4";
+    case 0x0004: return "ATA-2 published, ANSI X3.279-1996";
+    case 0x0005: return "ATA-2 X3T10/948D prior to revision 2k";
+    case 0x0006: return "ATA-3 X3T10/2008D revision 1";
+    case 0x0007: return "ATA-2 X3T10/948D revision 2k";
+    case 0x0008: return "ATA-3 X3T10/2008D revision 0";
+    case 0x0009: return "ATA-2 X3T10/948D revision 3";
+    case 0x000a: return "ATA-3 published, ANSI X3.298-1997";
+    case 0x000b: return "ATA-3 X3T10/2008D revision 6"; // 1st ATA-3 revision with SMART
+    case 0x000c: return "ATA-3 X3T13/2008D revision 7 and 7a";
+    case 0x000d: return "ATA/ATAPI-4 X3T13/1153D revision 6";
+    case 0x000e: return "ATA/ATAPI-4 T13/1153D revision 13";
+    case 0x000f: return "ATA/ATAPI-4 X3T13/1153D revision 7";
+    case 0x0010: return "ATA/ATAPI-4 T13/1153D revision 18";
+    case 0x0011: return "ATA/ATAPI-4 T13/1153D revision 15";
+    case 0x0012: return "ATA/ATAPI-4 published, ANSI NCITS 317-1998";
+    case 0x0013: return "ATA/ATAPI-5 T13/1321D revision 3";
+    case 0x0014: return "ATA/ATAPI-4 T13/1153D revision 14";
+    case 0x0015: return "ATA/ATAPI-5 T13/1321D revision 1";
+    case 0x0016: return "ATA/ATAPI-5 published, ANSI NCITS 340-2000";
+    case 0x0017: return "ATA/ATAPI-4 T13/1153D revision 17";
+    case 0x0018: return "ATA/ATAPI-6 T13/1410D revision 0";
+    case 0x0019: return "ATA/ATAPI-6 T13/1410D revision 3a";
+    case 0x001a: return "ATA/ATAPI-7 T13/1532D revision 1";
+    case 0x001b: return "ATA/ATAPI-6 T13/1410D revision 2";
+    case 0x001c: return "ATA/ATAPI-6 T13/1410D revision 1";
+    case 0x001d: return "ATA/ATAPI-7 published, ANSI INCITS 397-2005";
+    case 0x001e: return "ATA/ATAPI-7 T13/1532D revision 0";
+    case 0x001f: return "ACS-3 T13/2161-D revision 3b";
+
+    case 0x0021: return "ATA/ATAPI-7 T13/1532D revision 4a";
+    case 0x0022: return "ATA/ATAPI-6 published, ANSI INCITS 361-2002";
+
+    case 0x0027: return "ATA8-ACS T13/1699-D revision 3c";
+    case 0x0028: return "ATA8-ACS T13/1699-D revision 6";
+    case 0x0029: return "ATA8-ACS T13/1699-D revision 4";
+
+    case 0x0031: return "ACS-2 T13/2015-D revision 2";
+
+    case 0x0033: return "ATA8-ACS T13/1699-D revision 3e";
+
+    case 0x0039: return "ATA8-ACS T13/1699-D revision 4c";
+
+    case 0x0042: return "ATA8-ACS T13/1699-D revision 3f";
+
+    case 0x0052: return "ATA8-ACS T13/1699-D revision 3b";
+
+    case 0x0107: return "ATA8-ACS T13/1699-D revision 2d";
+
+    case 0x0110: return "ACS-2 T13/2015-D revision 3";
+
+    default:     return 0;
+  }
+}
+
+static const char * get_sata_version(const ata_identify_device * drive)
+{
+  unsigned short word222 = drive->words088_255[222-88];
+  if ((word222 & 0xf000) != 0x1000)
+    return 0;
+  switch (find_msb(word222 & 0x0fff)) {
+    default: return "SATA >3.1";
+    case 6:  return "SATA 3.1";
+    case 5:  return "SATA 3.0";
+    case 4:  return "SATA 2.6";
+    case 3:  return "SATA 2.5";
+    case 2:  return "SATA II Ext";
+    case 1:  return "SATA 1.0a";
+    case 0:  return "ATA8-AST";
+    case -1: return 0;
+  }
+}
+
+static const char * get_sata_speed(int level)
+{
+  if (level <= 0)
+    return 0;
+  switch (level) {
+    default: return ">6.0 Gb/s";
+    case 3:  return "6.0 Gb/s";
+    case 2:  return "3.0 Gb/s";
+    case 1:  return "1.5 Gb/s";
+  }
+}
+
+static const char * get_sata_maxspeed(const ata_identify_device * drive)
+{
+  unsigned short word076 = drive->words047_079[76-47];
+  if (word076 & 0x0001)
+    return 0;
+  return get_sata_speed(find_msb(word076 & 0x00fe));
+}
+
+static const char * get_sata_curspeed(const ata_identify_device * drive)
+{
+  unsigned short word077 = drive->words047_079[77-47];
+  if (word077 & 0x0001)
+    return 0;
+  return get_sata_speed((word077 >> 1) & 0x7);
+}
+
+
 static void print_drive_info(const ata_identify_device * drive,
-                             const ata_size_info & sizes,
+                             const ata_size_info & sizes, int rpm,
                              const drive_settings * dbentry)
 {
   // format drive information (with byte swapping as needed)
@@ -440,6 +566,15 @@ static void print_drive_info(const ata_identify_device * drive,
     int naa = ata_get_wwn(drive, oui, unique_id);
     if (naa >= 0)
       pout("LU WWN Device Id: %x %06x %09"PRIx64"\n", naa, oui, unique_id);
+
+    // Additional Product Identifier (OEM Id) string in words 170-173
+    // (e08130r1, added in ACS-2 Revision 1, December 17, 2008)
+    if (0x2020 <= drive->words088_255[170-88] && drive->words088_255[170-88] <= 0x7e7e) {
+      char add[8+1];
+      ata_format_id_string(add, (const unsigned char *)(drive->words088_255+170-88), sizeof(add)-1);
+      if (add[0])
+        pout("Add. Product Id:  %s\n", add);
+    }
   }
   pout("Firmware Version: %s\n", infofound(firmware));
 
@@ -462,50 +597,58 @@ static void print_drive_info(const ata_identify_device * drive,
     }
   }
 
+  // Print nominal media rotation rate if reported
+  if (rpm) {
+    if (rpm == 1)
+      pout("Rotation Rate:    Solid State Device\n");
+    else if (rpm > 1)
+      pout("Rotation Rate:    %d rpm\n", rpm);
+    else
+      pout("Rotation Rate:    Unknown (0x%04x)\n", -rpm);
+  }
+
   // See if drive is recognized
   pout("Device is:        %s\n", !dbentry ?
        "Not in smartctl database [for details use: -P showall]":
        "In smartctl database [for details use: -P show]");
 
-  // now get ATA version info
-  const char *description; unsigned short minorrev;
-  int version = ataVersionInfo(&description, drive, &minorrev);
-
-  // SMART Support was first added into the ATA/ATAPI-3 Standard with
-  // Revision 3 of the document, July 25, 1995.  Look at the "Document
-  // Status" revision commands at the beginning of
-  // http://www.t13.org/Documents/UploadedDocuments/project/d2008r7b-ATA-3.pdf
-  // to see this.  So it's not enough to check if we are ATA-3.
-  // Version=-3 indicates ATA-3 BEFORE Revision 3.
-  // Version=0 indicates that no info is found. This may happen if
-  // the OS provides only part of the IDENTIFY data.
-
-  std::string majorstr, minorstr;
-  if (version) {
-    if (version <= 8) {
-      majorstr = strprintf("%d", abs(version));
-      if (description)
-        minorstr = description;
-      else if (!minorrev)
-        minorstr = "Exact ATA specification draft version not indicated";
-      else
-        minorstr = strprintf("Not recognized. Minor revision code: 0x%04x", minorrev);
+  // Print ATA version
+  std::string ataver;
+  if (   (drive->major_rev_num != 0x0000 && drive->major_rev_num != 0xffff)
+      || (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff)) {
+    const char * majorver = get_ata_major_version(drive);
+    const char * minorver = get_ata_minor_version(drive);
+
+    if (majorver && minorver && str_starts_with(minorver, majorver)) {
+      // Major and minor strings match, print minor string only
+      ataver = minorver;
     }
     else {
-      // Bit 9 in word 80 of ATA IDENTIFY data does not mean "ATA-9" but "ACS-2"
-      // TODO: handle this in ataVersionInfo()
-      majorstr = "8";
-      if (description)
-        minorstr = description;
-      else if (!minorrev)
-        minorstr = strprintf("ACS-%d (revision not indicated)", version-9+2);
+      if (majorver)
+        ataver = majorver;
+      else
+        ataver = strprintf("Unknown(0x%04x)", drive->major_rev_num);
+
+      if (minorver)
+        ataver += strprintf(", %s", minorver);
+      else if (drive->minor_rev_num != 0x0000 && drive->minor_rev_num != 0xffff)
+        ataver += strprintf(" (unknown minor revision code: 0x%04x)", drive->minor_rev_num);
       else
-        minorstr = strprintf("ACS-%d (unknown minor revision code: 0x%04x)", version-9+2, minorrev);
+        ataver += " (minor revision not indicated)";
     }
   }
+  pout("ATA Version is:   %s\n", infofound(ataver.c_str()));
 
-  pout("ATA Version is:   %s\n", infofound(majorstr.c_str()));
-  pout("ATA Standard is:  %s\n", infofound(minorstr.c_str()));
+  // If SATA drive print SATA version and speed
+  const char * sataver = get_sata_version(drive);
+  if (sataver) {
+    const char * maxspeed = get_sata_maxspeed(drive);
+    const char * curspeed = get_sata_curspeed(drive);
+    pout("SATA Version is:  %s%s%s%s%s%s\n", sataver,
+         (maxspeed ? ", " : ""), (maxspeed ? maxspeed : ""),
+         (curspeed ? " (current: " : ""), (curspeed ? curspeed : ""),
+         (curspeed ? ")" : ""));
+  }
 
   // print current time and date and timezone
   char timedatetz[DATEANDEPOCHLEN]; dateandtimezone(timedatetz);
@@ -514,12 +657,6 @@ static void print_drive_info(const ata_identify_device * drive,
   // Print warning message, if there is one
   if (dbentry && *dbentry->warningmsg)
     pout("\n==> WARNING: %s\n\n", dbentry->warningmsg);
-
-  if (!version || version >= 3)
-    return;
-  
-  pout("SMART is only available in ATA Version 3 Revision 3 or greater.\n");
-  pout("We will try to proceed in spite of this.\n");
 }
 
 static const char *OfflineDataCollectionStatus(unsigned char status_byte)
@@ -573,7 +710,7 @@ static void PrintSmartOfflineStatus(const ata_smart_values * data)
 }
 
 static void PrintSmartSelfExecStatus(const ata_smart_values * data,
-                                     unsigned char fix_firmwarebug)
+                                     firmwarebug_defs firmwarebugs)
 {
    pout("Self-test execution status:      ");
    
@@ -633,7 +770,7 @@ static void PrintSmartSelfExecStatus(const ata_smart_values * data,
           pout("damage.\n");
           break;
        case 15:
-          if (fix_firmwarebug == FIX_SAMSUNG3 && data->self_test_exec_status == 0xf0) {
+          if (firmwarebugs.is_set(BUG_SAMSUNG3) && data->self_test_exec_status == 0xf0) {
             pout("(%4d)\tThe previous self-test routine completed\n\t\t\t\t\t",
                     (int)data->self_test_exec_status);
             pout("with unknown result or self-test in\n\t\t\t\t\t");
@@ -798,7 +935,7 @@ static int find_failed_attr(const ata_smart_values * data,
 // onlyfailed=2:  ones that are failed, or have failed with or without prefailure bit set
 static void PrintSmartAttribWithThres(const ata_smart_values * data,
                                       const ata_smart_thresholds_pvt * thresholds,
-                                      const ata_vendor_attr_defs & defs,
+                                      const ata_vendor_attr_defs & defs, int rpm,
                                       int onlyfailed, unsigned char format)
 {
   bool brief  = !!(format & ata_print_options::FMT_BRIEF);
@@ -859,7 +996,7 @@ static void PrintSmartAttribWithThres(const ata_smart_values * data,
     // Print line for each valid attribute
     std::string idstr = (!hexid ? strprintf("%3d",    attr.id)
                                 : strprintf("0x%02x", attr.id));
-    std::string attrname = ata_get_smart_attr_name(attr.id, defs);
+    std::string attrname = ata_get_smart_attr_name(attr.id, defs, rpm);
     std::string rawstr = ata_format_attr_raw_value(attr, defs);
 
     if (!brief)
@@ -922,14 +1059,14 @@ static void ataPrintSCTCapability(const ata_identify_device *drive)
 
 
 static void PrintGeneralSmartValues(const ata_smart_values *data, const ata_identify_device *drive,
-                                    unsigned char fix_firmwarebug)
+                                    firmwarebug_defs firmwarebugs)
 {
   pout("General SMART Values:\n");
   
   PrintSmartOfflineStatus(data); 
   
   if (isSupportSelfTest(data)){
-    PrintSmartSelfExecStatus(data, fix_firmwarebug);
+    PrintSmartSelfExecStatus(data, firmwarebugs);
   }
   
   PrintSmartTotalTimeCompleteOffline(data);
@@ -971,7 +1108,7 @@ static unsigned GetNumLogSectors(const ata_smart_log_directory * logdir, unsigne
 }
 
 // Get name of log.
-// Table A.2 of T13/2161-D Revision 2 (ACS-3), February 21, 2012.
+// Table A.2 of T13/2161-D (ACS-3) Revision 4, September 4, 2012
 static const char * GetLogName(unsigned logaddr)
 {
     switch (logaddr) {
@@ -980,12 +1117,16 @@ static const char * GetLogName(unsigned logaddr)
       case 0x02: return "Comprehensive SMART error log";
       case 0x03: return "Ext. Comprehensive SMART error log";
       case 0x04: return "Device Statistics log";
-      case 0x05: return "Reserved for the CFA"; // ACS-2
+      case 0x05: return "Reserved for CFA"; // ACS-2
       case 0x06: return "SMART self-test log";
       case 0x07: return "Extended self-test log";
       case 0x08: return "Power Conditions log"; // ACS-2
       case 0x09: return "Selective self-test log";
+      case 0x0a: return "Device Statistics Notification"; // ACS-3
+      case 0x0b: return "Reserved for CFA"; // ACS-3
+
       case 0x0d: return "LPS Mis-alignment log"; // ACS-2
+
       case 0x10: return "NCQ Command Error log";
       case 0x11: return "SATA Phy Event Counters";
       case 0x12: return "SATA NCQ Queue Management log"; // ACS-3
@@ -993,14 +1134,18 @@ static const char * GetLogName(unsigned logaddr)
       case 0x14:
       case 0x15:
       case 0x16: return "Reserved for Serial ATA";
+
       case 0x19: return "LBA Status log"; // ACS-3
-      case 0x20: return "Streaming performance log"; // Obsolete
+
+      case 0x20: return "Streaming performance log [OBS-8]";
       case 0x21: return "Write stream error log";
       case 0x22: return "Read stream error log";
-      case 0x23: return "Delayed sector log"; // Obsolete
+      case 0x23: return "Delayed sector log [OBS-8]";
       case 0x24: return "Current Device Internal Status Data log"; // ACS-3
       case 0x25: return "Saved Device Internal Status Data log"; // ACS-3
+
       case 0x30: return "IDENTIFY DEVICE data log"; // ACS-3
+
       case 0xe0: return "SCT Command/Status";
       case 0xe1: return "SCT Data Transfer";
       default:
@@ -1013,6 +1158,44 @@ static const char * GetLogName(unsigned logaddr)
     /*NOTREACHED*/
 }
 
+// Get log access permissions
+static const char * get_log_rw(unsigned logaddr)
+{
+   if (   (                   logaddr <= 0x08)
+       || (0x0d == logaddr)
+       || (0x10 <= logaddr && logaddr <= 0x13)
+       || (0x19 == logaddr)
+       || (0x20 <= logaddr && logaddr <= 0x25)
+       || (0x30 == logaddr))
+      return "R/O";
+
+   if (   (0x09 <= logaddr && logaddr <= 0x0a)
+       || (0x80 <= logaddr && logaddr <= 0x9f)
+       || (0xe0 <= logaddr && logaddr <= 0xe1))
+      return "R/W";
+
+   if (0xa0 <= logaddr && logaddr <= 0xdf)
+      return "VS"; // Vendor specific
+
+   return "-"; // Unknown/Reserved
+}
+
+// Init a fake log directory, assume that standard logs are supported
+const ata_smart_log_directory * fake_logdir(ata_smart_log_directory * logdir,
+  const ata_print_options & options)
+{
+  memset(logdir, 0, sizeof(*logdir));
+  logdir->logversion = 255;
+  logdir->entry[0x01-1].numsectors = 1;
+  logdir->entry[0x03-1].numsectors = (options.smart_ext_error_log + (4-1)) / 4;
+  logdir->entry[0x04-1].numsectors = 8;
+  logdir->entry[0x06-1].numsectors = 1;
+  logdir->entry[0x07-1].numsectors = (options.smart_ext_selftest_log + (19-1)) / 19;
+  logdir->entry[0x09-1].numsectors = 1;
+  logdir->entry[0x11-1].numsectors = 1;
+  return logdir;
+}
+
 // Print SMART and/or GP Log Directory
 static void PrintLogDirectories(const ata_smart_log_directory * gplogdir,
                                 const ata_smart_log_directory * smartlogdir)
@@ -1024,6 +1207,8 @@ static void PrintLogDirectories(const ata_smart_log_directory * gplogdir,
          (gplogdir ? "          " : ""), smartlogdir->logversion,
          (smartlogdir->logversion==1 ? " [multi-sector log support]" : ""));
 
+  pout("Address    Access  R/W   Size  Description\n");
+
   for (unsigned i = 0; i <= 0xff; i++) {
     // Get number of sectors
     unsigned smart_numsect = GetNumLogSectors(smartlogdir, i, false);
@@ -1032,18 +1217,47 @@ static void PrintLogDirectories(const ata_smart_log_directory * gplogdir,
     if (!(smart_numsect || gp_numsect))
       continue; // Log does not exist
 
+    const char * acc; unsigned size;
+    if (smart_numsect == gp_numsect) {
+      acc = "GPL,SL"; size = gp_numsect;
+    }
+    else if (!smart_numsect) {
+      acc = "GPL"; size = gp_numsect;
+    }
+    else if (!gp_numsect) {
+      acc = "    SL"; size = smart_numsect;
+    }
+    else {
+      acc = 0; size = 0;
+    }
+
+    unsigned i2 = i;
+    if (acc && ((0x80 <= i && i < 0x9f) || (0xa0 <= i && i < 0xdf))) {
+      // Find range of Host/Device vendor specific logs with same size
+      unsigned imax = (i < 0x9f ? 0x9f : 0xdf);
+      for (unsigned j = i+1; j <= imax; j++) {
+          unsigned sn = GetNumLogSectors(smartlogdir, j, false);
+          unsigned gn = GetNumLogSectors(gplogdir   , j, true );
+
+          if (!(sn == smart_numsect && gn == gp_numsect))
+            break;
+          i2 = j;
+      }
+    }
+
     const char * name = GetLogName(i);
+    const char * rw = get_log_rw(i);
 
-    // Print name and length of log.
-    // If both SMART and GP exist, print separate entries if length differ.
-    if (smart_numsect == gp_numsect)
-      pout(  "GP/S  Log at address 0x%02x has %4d sectors [%s]\n", i, smart_numsect, name);
+    if (i2 > i) {
+      pout("0x%02x-0x%02x  %-6s  %-3s  %5u  %s\n", i, i2, acc, rw, size, name);
+      i = i2;
+    }
+    else if (acc)
+      pout(  "0x%02x       %-6s  %-3s  %5u  %s\n", i, acc, rw, size, name);
     else {
-      if (gp_numsect)
-        pout("GP %sLog at address 0x%02x has %4d sectors [%s]\n", (smartlogdir?"   ":""),
-             i, gp_numsect, name);
-      if (smart_numsect)
-        pout("SMART Log at address 0x%02x has %4d sectors [%s]\n", i, smart_numsect, name);
+      // GPL and SL support different sizes
+      pout(  "0x%02x       %-6s  %-3s  %5u  %s\n", i, "GPL", rw, gp_numsect, name);
+      pout(  "0x%02x       %-6s  %-3s  %5u  %s\n", i, "SL", rw, smart_numsect, name);
     }
   }
   pout("\n");
@@ -1227,7 +1441,7 @@ static void print_device_statistics_page(const unsigned char * data, int page,
     }
     else {
       // Value not known (yet)
-      strcpy(valstr, "-");
+      valstr[0] = '-'; valstr[1] = 0;
     }
 
     pout("%3d  0x%03x  %d%c %15s%c %s\n",
@@ -1247,12 +1461,14 @@ static bool print_device_statistics(ata_device * device, unsigned nsectors,
 {
   // Read list of supported pages from page 0
   unsigned char page_0[512] = {0, };
-  if (!ataReadLogExt(device, 0x04, 0, 0, page_0, 1))
+  if (!ataReadLogExt(device, 0x04, 0, 0, page_0, 1)) {
+    pout("Read Device Statistics page 0 failed\n\n");
     return false;
+  }
 
   unsigned char nentries = page_0[8];
   if (!(page_0[2] == 0 && nentries > 0)) {
-    pout("Device Statistics page 0 is invalid (page=%d, nentries=%d)\n", page_0[2], nentries);
+    pout("Device Statistics page 0 is invalid (page=%d, nentries=%d)\n\n", page_0[2], nentries);
     return false;
   }
 
@@ -1303,8 +1519,10 @@ static bool print_device_statistics(ata_device * device, unsigned nsectors,
     for (i = 0; i <  pages.size(); i++) {
       int page = pages[i];
       unsigned char page_n[512] = {0, };
-      if (!ataReadLogExt(device, 0x04, 0, page, page_n, 1))
+      if (!ataReadLogExt(device, 0x04, 0, page, page_n, 1)) {
+        pout("Read Device Statistics page %d failed\n\n", page);
         return false;
+      }
       print_device_statistics_page(page_n, page, need_trailer);
     }
 
@@ -1385,6 +1603,25 @@ static void PrintSataPhyEventCounters(const unsigned char * data, bool reset)
   pout("\n");
 }
 
+// Format milliseconds from error log entry as "DAYS+H:M:S.MSEC"
+static std::string format_milliseconds(unsigned msec)
+{
+  unsigned days  = msec  / 86400000U;
+  msec          -= days  * 86400000U;
+  unsigned hours = msec  / 3600000U;
+  msec          -= hours * 3600000U;
+  unsigned min   = msec  / 60000U;
+  msec          -= min   * 60000U;
+  unsigned sec   = msec  / 1000U;
+  msec          -= sec   * 1000U;
+
+  std::string str;
+  if (days)
+    str = strprintf("%2ud+", days);
+  str += strprintf("%02u:%02u:%02u.%03u", hours, min, sec, msec);
+  return str;
+}
+
 // Get description for 'state' value from SMART Error Logs
 static const char * get_error_log_state_desc(unsigned state)
 {
@@ -1403,7 +1640,7 @@ static const char * get_error_log_state_desc(unsigned state)
 
 // returns number of errors
 static int PrintSmartErrorlog(const ata_smart_errorlog *data,
-                              unsigned char fix_firmwarebug)
+                              firmwarebug_defs firmwarebugs)
 {
   pout("SMART Error Log Version: %d\n", (int)data->revnumber);
   
@@ -1422,7 +1659,7 @@ static int PrintSmartErrorlog(const ata_smart_errorlog *data,
   }
 
   // Some internal consistency checking of the data structures
-  if ((data->ata_error_count-data->error_log_pointer)%5 && fix_firmwarebug != FIX_SAMSUNG2) {
+  if ((data->ata_error_count-data->error_log_pointer) % 5 && !firmwarebugs.is_set(BUG_SAMSUNG2)) {
     pout("Warning: ATA error count %d inconsistent with error log pointer %d\n\n",
          data->ata_error_count,data->error_log_pointer);
   }
@@ -1481,10 +1718,9 @@ static int PrintSmartErrorlog(const ata_smart_errorlog *data,
            (int)summary->drive_head);
       // Add a description of the contents of the status and error registers
       // if possible
-      char descbuf[256];
-      const char * st_er_desc = construct_st_er_desc(descbuf, elog);
-      if (st_er_desc)
-        pout("  %s", st_er_desc);
+      std::string st_er_desc = format_st_er_desc(elog);
+      if (!st_er_desc.empty())
+        pout("  %s", st_er_desc.c_str());
       pout("\n\n");
       pout("  Commands leading to the command that caused the error were:\n"
            "  CR FR SC SN CL CH DH DC   Powered_Up_Time  Command/Feature_Name\n"
@@ -1494,11 +1730,6 @@ static int PrintSmartErrorlog(const ata_smart_errorlog *data,
 
         // Spec says: unused data command structures shall be zero filled
         if (nonempty(thiscommand, sizeof(*thiscommand))) {
-         char timestring[32];
-         
-         // Convert integer milliseconds to a text-format string
-         MsecToText(thiscommand->timestamp, timestring);
-         
           pout("  %02x %02x %02x %02x %02x %02x %02x %02x  %16s  %s\n",
                (int)thiscommand->commandreg,
                (int)thiscommand->featuresreg,
@@ -1508,7 +1739,7 @@ static int PrintSmartErrorlog(const ata_smart_errorlog *data,
                (int)thiscommand->cylinder_high,
                (int)thiscommand->drive_head,
                (int)thiscommand->devicecontrolreg,
-              timestring,
+               format_milliseconds(thiscommand->timestamp).c_str(),
                look_up_ata_command(thiscommand->commandreg, thiscommand->featuresreg));
        }
       }
@@ -1626,10 +1857,9 @@ static int PrintSmartExtErrorLog(const ata_smart_exterrlog * log,
 
     // Add a description of the contents of the status and error registers
     // if possible
-    char descbuf[256];
-    const char * st_er_desc = construct_st_er_desc(descbuf, &entry);
-    if (st_er_desc)
-      pout("  %s", st_er_desc);
+    std::string st_er_desc = format_st_er_desc(&entry);
+    if (!st_er_desc.empty())
+      pout("  %s", st_er_desc.c_str());
     pout("\n\n");
 
     // Print command history
@@ -1644,9 +1874,6 @@ static int PrintSmartExtErrorLog(const ata_smart_exterrlog * log,
         continue;
 
       // Print registers, timestamp and ATA command name
-      char timestring[32];
-      MsecToText(cmd.timestamp, timestring);
-
       pout("  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %16s  %s\n",
            cmd.command_register,
            cmd.features_register_hi,
@@ -1661,7 +1888,7 @@ static int PrintSmartExtErrorLog(const ata_smart_exterrlog * log,
            cmd.lba_low_register,
            cmd.device_register,
            cmd.device_control_register,
-           timestring,
+           format_milliseconds(cmd.timestamp).c_str(),
            look_up_ata_command(cmd.command_register, cmd.features_register));
     }
     pout("\n");
@@ -1869,16 +2096,15 @@ static void ataPrintSelectiveSelfTestLog(const ata_selective_self_test_log * log
 }
 
 // Format SCT Temperature value
-static const char * sct_ptemp(signed char x, char * buf)
+static const char * sct_ptemp(signed char x, char (& buf)[20])
 {
   if (x == -128 /*0x80 = unknown*/)
-    strcpy(buf, " ?");
-  else
-    sprintf(buf, "%2d", x);
+    return " ?";
+  snprintf(buf, sizeof(buf), "%2d", x);
   return buf;
 }
 
-static const char * sct_pbar(int x, char * buf)
+static const char * sct_pbar(int x, char (& buf)[64])
 {
   if (x <= 19)
     x = 0;
@@ -1957,8 +2183,9 @@ static int ataPrintSCTStatus(const ata_sct_status_response * sts)
 // Print SCT Temperature History Table
 static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh)
 {
-  char buf1[20], buf2[80];
-  pout("SCT Temperature History Version:     %u\n", tmh->format_version);
+  char buf1[20], buf2[20], buf3[64];
+  pout("SCT Temperature History Version:     %u%s\n", tmh->format_version,
+       (tmh->format_version != 2 ? " (Unknown, should be 2)" : ""));
   pout("Temperature Sampling Period:         %u minute%s\n",
     tmh->sampling_period, (tmh->sampling_period==1?"":"s"));
   pout("Temperature Logging Interval:        %u minute%s\n",
@@ -1968,8 +2195,12 @@ static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh)
   pout("Min/Max Temperature Limit:           %s/%s Celsius\n",
     sct_ptemp(tmh->under_limit, buf1), sct_ptemp(tmh->over_limit, buf2));
   pout("Temperature History Size (Index):    %u (%u)\n", tmh->cb_size, tmh->cb_index);
+
   if (!(0 < tmh->cb_size && tmh->cb_size <= sizeof(tmh->cb) && tmh->cb_index < tmh->cb_size)) {
-    pout("Error invalid Temperature History Size or Index\n");
+    if (!tmh->cb_size)
+      pout("Temperature History is empty\n");
+    else
+      pout("Invalid Temperature History Size or Index\n");
     return 0;
   }
 
@@ -1992,11 +2223,11 @@ static int ataPrintSCTTempHist(const ata_sct_temperature_history_table * tmh)
         // TODO: Don't print times < boot time
         strftime(date, sizeof(date), "%Y-%m-%d %H:%M", localtime(&t));
         pout(" %3u    %s    %s  %s\n", i, date,
-          sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf2));
+          sct_ptemp(tmh->cb[i], buf1), sct_pbar(tmh->cb[i], buf3));
       }
       else if (n == n1+1) {
         pout(" ...    ..(%3u skipped).    ..  %s\n",
-          n2-n1-2, sct_pbar(tmh->cb[i], buf2));
+          n2-n1-2, sct_pbar(tmh->cb[i], buf3));
       }
       t += interval * 60; i = (i+1) % tmh->cb_size; n++;
     }
@@ -2206,7 +2437,6 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
           options.gp_logdir
        || options.smart_ext_error_log
        || options.smart_ext_selftest_log
-       || options.sataphy
        || options.devstat_all_pages
        || options.devstat_ssd_page
        || !options.devstat_pages.empty()
@@ -2230,9 +2460,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   );
 
   // Exit if no further options specified
-  if (!(   options.drive_info || need_smart_support
-        || need_smart_logdir  || need_gp_logdir
-        || need_sct_support || options.get_set_used)) {
+  if (!(   options.drive_info || options.show_presets
+        || need_smart_support || need_smart_logdir
+        || need_gp_logdir     || need_sct_support
+        || options.sataphy
+        || options.identify_word_level >= 0
+        || options.get_set_used                      )) {
     if (powername)
       pout("Device is in %s mode\n", powername);
     else
@@ -2244,15 +2477,17 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   // Start by getting Drive ID information.  We need this, to know if SMART is supported.
   int returnval = 0;
   ata_identify_device drive; memset(&drive, 0, sizeof(drive));
+  unsigned char raw_drive[sizeof(drive)]; memset(&raw_drive, 0, sizeof(raw_drive));
+
   device->clear_err();
-  int retid = ata_read_identity(device, &drive, options.fix_swapped_id);
+  int retid = ata_read_identity(device, &drive, options.fix_swapped_id, raw_drive);
   if (retid < 0) {
-    pout("Smartctl: Device Read Identity Failed: %s\n\n",
+    pout("Read Device Identity failed: %s\n\n",
          (device->get_errno() ? device->get_errmsg() : "Unknown error"));
     failuretest(MANDATORY_CMD, returnval|=FAILID);
   }
   else if (!nonempty(&drive, sizeof(drive))) {
-    pout("Smartctl: Device Read Identity Failed: empty IDENTIFY data\n\n");
+    pout("Read Device Identity failed: empty IDENTIFY data\n\n");
     failuretest(MANDATORY_CMD, returnval|=FAILID);
   }
 
@@ -2264,20 +2499,28 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
   // Use preset vendor attribute options unless user has requested otherwise.
   ata_vendor_attr_defs attribute_defs = options.attribute_defs;
-  unsigned char fix_firmwarebug = options.fix_firmwarebug;
+  firmwarebug_defs firmwarebugs = options.firmwarebugs;
   const drive_settings * dbentry = 0;
   if (!options.ignore_presets)
     dbentry = lookup_drive_apply_presets(&drive, attribute_defs,
-      fix_firmwarebug);
+      firmwarebugs);
 
-  // Get capacity and sector sizes
+  // Get capacity, sector sizes and rotation rate
   ata_size_info sizes;
   ata_get_size_info(&drive, sizes);
+  int rpm = ata_get_rotation_rate(&drive);
+
+  // Print ATA IDENTIFY info if requested
+  if (options.identify_word_level >= 0) {
+    pout("=== ATA IDENTIFY DATA ===\n");
+    // Pass raw data without endianness adjustments
+    ata_print_identify_data(raw_drive, (options.identify_word_level > 0), options.identify_bit_level);
+  }
 
   // Print most drive identity information if requested
   if (options.drive_info) {
     pout("=== START OF INFORMATION SECTION ===\n");
-    print_drive_info(&drive, sizes, dbentry);
+    print_drive_info(&drive, sizes, rpm, dbentry);
   }
 
   // Check and print SMART support and state
@@ -2476,7 +2719,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   // Enable/Disable SMART commands
   if (options.smart_enable) {
     if (ataEnableSmart(device)) {
-      pout("Smartctl: SMART Enable Failed.\n\n");
+      pout("SMART Enable failed: %s\n\n", device->get_errmsg());
       failuretest(MANDATORY_CMD, returnval|=FAILSMART);
     }
     else {
@@ -2488,21 +2731,23 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   // Turn off SMART on device
   if (options.smart_disable) {
     if (ataDisableSmart(device)) {
-      pout( "Smartctl: SMART Disable Failed.\n\n");
+      pout("SMART Disable failed: %s\n\n", device->get_errmsg());
       failuretest(MANDATORY_CMD,returnval|=FAILSMART);
     }
   }
 
   // Exit if SMART is disabled but must be enabled to proceed
-  if (options.smart_disable || (smart_enabled <= 0 && need_smart_enabled)) {
+  if (options.smart_disable || (smart_enabled <= 0 && need_smart_enabled && !is_permissive())) {
     pout("SMART Disabled. Use option -s with argument 'on' to enable it.\n");
+    if (!options.smart_disable)
+      pout("(override with '-T permissive' option)\n");
     return returnval;
   }
 
   // Enable/Disable Auto-save attributes
   if (options.smart_auto_save_enable) {
     if (ataEnableAutoSave(device)){
-      pout( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n");
+      pout("SMART Enable Attribute Autosave failed: %s\n\n", device->get_errmsg());
       failuretest(MANDATORY_CMD, returnval|=FAILSMART);
     }
     else
@@ -2511,7 +2756,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
   if (options.smart_auto_save_disable) {
     if (ataDisableAutoSave(device)){
-      pout( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n");
+      pout("SMART Disable Attribute Autosave failed: %s\n\n", device->get_errmsg());
       failuretest(MANDATORY_CMD, returnval|=FAILSMART);
     }
     else
@@ -2525,7 +2770,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
   if (need_smart_val) {
     if (ataReadSmartValues(device, &smartval)) {
-      pout("Smartctl: SMART Read Values failed.\n\n");
+      pout("Read SMART Data failed: %s\n\n", device->get_errmsg());
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else {
@@ -2533,7 +2778,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
       if (options.smart_check_status || options.smart_vendor_attrib) {
         if (ataReadSmartThresholds(device, &smartthres)){
-          pout("Smartctl: SMART Read Thresholds failed.\n\n");
+          pout("Read SMART Thresholds failed: %s\n\n", device->get_errmsg());
           failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
         }
         else
@@ -2546,12 +2791,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   bool needupdate = false;
   if (options.smart_auto_offl_enable) {
     if (!isSupportAutomaticTimer(&smartval)){
-      pout("Warning: device does not support SMART Automatic Timers.\n\n");
+      pout("SMART Automatic Timers not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     needupdate = smart_val_ok;
     if (ataEnableAutoOffline(device)){
-      pout( "Smartctl: SMART Enable Automatic Offline Failed.\n\n");
+      pout("SMART Enable Automatic Offline failed: %s\n\n", device->get_errmsg());
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else
@@ -2560,12 +2805,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
   if (options.smart_auto_offl_disable) {
     if (!isSupportAutomaticTimer(&smartval)){
-      pout("Warning: device does not support SMART Automatic Timers.\n\n");
+      pout("SMART Automatic Timers not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     needupdate = smart_val_ok;
     if (ataDisableAutoOffline(device)){
-      pout("Smartctl: SMART Disable Automatic Offline Failed.\n\n");
+      pout("SMART Disable Automatic Offline failed: %s\n\n", device->get_errmsg());
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else
@@ -2573,7 +2818,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   }
 
   if (needupdate && ataReadSmartValues(device, &smartval)){
-    pout("Smartctl: SMART Read Values failed.\n\n");
+    pout("Read SMART Data failed: %s\n\n", device->get_errmsg());
     failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     smart_val_ok = false;
   }
@@ -2606,7 +2851,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         else {
           print_on();
           pout("Please note the following marginal Attributes:\n");
-          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2, options.output_format);
+          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format);
         } 
         returnval|=FAILAGE;
       }
@@ -2627,7 +2872,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         else {
           print_on();
           pout("Failed Attributes:\n");
-          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1, options.output_format);
+          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format);
         }
       }
       else
@@ -2660,7 +2905,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         else {
           print_on();
           pout("Failed Attributes:\n");
-          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 1, options.output_format);
+          PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 1, options.output_format);
         }
       }
       else {
@@ -2672,7 +2917,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
           else {
             print_on();
             pout("Please note the following marginal Attributes:\n");
-            PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, 2, options.output_format);
+            PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm, 2, options.output_format);
           } 
           returnval|=FAILAGE;
         }
@@ -2688,12 +2933,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   
   // Print general SMART values
   if (smart_val_ok && options.smart_general_values)
-    PrintGeneralSmartValues(&smartval, &drive, fix_firmwarebug);
+    PrintGeneralSmartValues(&smartval, &drive, firmwarebugs);
 
   // Print vendor-specific attributes
   if (smart_val_ok && options.smart_vendor_attrib) {
     print_on();
-    PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs,
+    PrintSmartAttribWithThres(&smartval, &smartthres, attribute_defs, rpm,
                               (printing_is_switchable ? 2 : 0), options.output_format);
     print_off();
   }
@@ -2710,8 +2955,10 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
   // Read SMART Log directory
   if (need_smart_logdir) {
-    if (ataReadLogDirectory(device, &smartlogdir_buf, false)) {
-      pout("Read SMART Log Directory failed.\n\n");
+    if (firmwarebugs.is_set(BUG_NOLOGDIR))
+      smartlogdir = fake_logdir(&smartlogdir_buf, options);
+    else if (ataReadLogDirectory(device, &smartlogdir_buf, false)) {
+      pout("Read SMART Log Directory failed: %s\n\n", device->get_errmsg());
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else
@@ -2720,8 +2967,10 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
 
   // Read GP Log directory
   if (need_gp_logdir) {
-    if (ataReadLogDirectory(device, &gplogdir_buf, true)) {
-      pout("Read GP Log Directory failed.\n\n");
+    if (firmwarebugs.is_set(BUG_NOLOGDIR))
+      gplogdir = fake_logdir(&gplogdir_buf, options);
+    else if (ataReadLogDirectory(device, &gplogdir_buf, true)) {
+      pout("Read GP Log Directory failed\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else
@@ -2729,8 +2978,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   }
 
   // Print log directories
-  if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir))
-    PrintLogDirectories(gplogdir, smartlogdir);
+  if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir)) {
+    if (firmwarebugs.is_set(BUG_NOLOGDIR))
+      pout("Log Directories not read due to '-F nologdir' option\n\n");
+    else
+      PrintLogDirectories(gplogdir, smartlogdir);
+  }
 
   // Print log pages
   for (i = 0; i < options.log_requests.size(); i++) {
@@ -2787,14 +3040,16 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     bool ok = false;
     unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true);
     if (!nsectors)
-      pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n");
+      pout("SMART Extended Comprehensive Error Log (GP Log 0x03) not supported\n\n");
     else if (nsectors >= 256)
-      pout("SMART Extended Comprehensive Error Log size %u not supported\n", nsectors);
+      pout("SMART Extended Comprehensive Error Log size %u not supported\n\n", nsectors);
     else {
       raw_buffer log_03_buf(nsectors * 512);
       ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data();
-      if (!ataReadExtErrorLog(device, log_03, nsectors))
+      if (!ataReadExtErrorLog(device, log_03, nsectors, firmwarebugs)) {
+        pout("Read SMART Extended Comprehensive Error Log failed\n\n");
         failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+      }
       else {
         if (PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log))
           returnval |= FAILERR;
@@ -2815,17 +3070,17 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     if (!(   ( smartlogdir && GetNumLogSectors(smartlogdir, 0x01, false))
           || (!smartlogdir && isSmartErrorLogCapable(&smartval, &drive) )
           || is_permissive()                                             )) {
-      pout("SMART Error Log not supported\n");
+      pout("SMART Error Log not supported\n\n");
     }
     else {
       ata_smart_errorlog smarterror; memset(&smarterror, 0, sizeof(smarterror));
-      if (ataReadErrorLog(device, &smarterror, fix_firmwarebug)) {
-        pout("Smartctl: SMART Error Log Read Failed\n");
+      if (ataReadErrorLog(device, &smarterror, firmwarebugs)) {
+        pout("Read SMART Error Log failed: %s\n\n", device->get_errmsg());
         failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
       }
       else {
         // quiet mode is turned on inside PrintSmartErrorLog()
-        if (PrintSmartErrorlog(&smarterror, fix_firmwarebug))
+        if (PrintSmartErrorlog(&smarterror, firmwarebugs))
          returnval|=FAILERR;
         print_off();
       }
@@ -2838,14 +3093,16 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     bool ok = false;
     unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true);
     if (!nsectors)
-      pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n");
+      pout("SMART Extended Self-test Log (GP Log 0x07) not supported\n\n");
     else if (nsectors >= 256)
-      pout("SMART Extended Self-test Log size %u not supported\n", nsectors);
+      pout("SMART Extended Self-test Log size %u not supported\n\n", nsectors);
     else {
       raw_buffer log_07_buf(nsectors * 512);
       ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data();
-      if (!ataReadExtSelfTestLog(device, log_07, nsectors))
+      if (!ataReadExtSelfTestLog(device, log_07, nsectors)) {
+        pout("Read SMART Extended Self-test Log failed\n\n");
         failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+      }
       else {
         if (PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log))
           returnval |= FAILLOG;
@@ -2866,17 +3123,17 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     if (!(   ( smartlogdir && GetNumLogSectors(smartlogdir, 0x06, false))
           || (!smartlogdir && isSmartTestLogCapable(&smartval, &drive)  )
           || is_permissive()                                             )) {
-      pout("SMART Self-test Log not supported\n");
+      pout("SMART Self-test Log not supported\n\n");
     }
     else {
       ata_smart_selftestlog smartselftest; memset(&smartselftest, 0, sizeof(smartselftest));
-      if (ataReadSelfTestLog(device, &smartselftest, fix_firmwarebug)) {
-        pout("Smartctl: SMART Self Test Log Read Failed\n");
+      if (ataReadSelfTestLog(device, &smartselftest, firmwarebugs)) {
+        pout("Read SMART Self-test Log failed: %s\n\n", device->get_errmsg());
         failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
       }
       else {
         print_on();
-        if (ataPrintSmartSelfTestlog(&smartselftest, !printing_is_switchable, fix_firmwarebug))
+        if (ataPrintSmartSelfTestlog(&smartselftest, !printing_is_switchable, firmwarebugs))
           returnval |= FAILLOG;
         print_off();
         pout("\n");
@@ -2889,9 +3146,9 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     ata_selective_self_test_log log;
 
     if (!isSupportSelectiveSelfTest(&smartval))
-      pout("Device does not support Selective Self Tests/Logging\n");
+      pout("Selective Self-tests/Logging not supported\n\n");
     else if(ataReadSelectiveSelfTestLog(device, &log)) {
-      pout("Smartctl: SMART Selective Self Test Log Read Failed\n");
+      pout("Read SMART Selective Self-test Log failed: %s\n\n", device->get_errmsg());
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else {
@@ -2910,7 +3167,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   bool sct_ok = false;
   if (need_sct_support) {
     if (!isSCTCapable(&drive)) {
-      pout("Warning: device does not support SCT Commands\n");
+      pout("SCT Commands not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else
@@ -2932,12 +3189,13 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         }
         else {
           if (!isSCTDataTableCapable(&drive)) {
-            pout("Warning: device does not support SCT Data Table command\n");
+            pout("SCT Data Table command not supported\n\n");
             failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
             break;
           }
           // Read SCT status and temperature history
           if (ataReadSCTTempHist(device, &tmh, &sts)) {
+            pout("Read SCT Temperature History failed\n\n");
             failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
             break;
           }
@@ -2951,11 +3209,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
       if (options.sct_temp_int) {
         // Set new temperature logging interval
         if (!isSCTFeatureControlCapable(&drive)) {
-          pout("Warning: device does not support SCT Feature Control command\n");
+          pout("SCT Feature Control command not supported\n\n");
           failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
           break;
         }
         if (ataSetSCTTempInterval(device, options.sct_temp_int, options.sct_temp_int_pers)) {
+          pout("Write Temperature Logging Interval failed\n\n");
           failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
           break;
         }
@@ -2970,7 +3229,7 @@ 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");
+      pout("SCT Error Recovery Control command not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     else {
@@ -2979,7 +3238,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         // 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("SCT (Set) Error Recovery Control command failed\n");
           if (!(   (options.sct_erc_readtime == 70 && options.sct_erc_writetime == 70)
                 || (options.sct_erc_readtime ==  0 && options.sct_erc_writetime ==  0)))
             pout("Retry with: 'scterc,70,70' to enable ERC or 'scterc,0,0' to disable\n");
@@ -2996,7 +3255,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         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");
+          pout("SCT (Get) Error Recovery Control command failed\n");
           if (options.sct_erc_set) {
             pout("The previous SCT (Set) Error Recovery Control command succeeded\n");
             ataPrintSCTErrorRecoveryControl(true, options.sct_erc_readtime,
@@ -3015,7 +3274,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   if (options.devstat_all_pages || options.devstat_ssd_page || !options.devstat_pages.empty()) {
     unsigned nsectors = GetNumLogSectors(gplogdir, 0x04, true);
     if (!nsectors)
-      pout("Device Statistics (GP Log 0x04) not supported\n");
+      pout("Device Statistics (GP Log 0x04) not supported\n\n");
     else if (!print_device_statistics(device, nsectors, options.devstat_pages,
                options.devstat_all_pages, options.devstat_ssd_page))
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
@@ -3024,15 +3283,20 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   // Print SATA Phy Event Counters
   if (options.sataphy) {
     unsigned nsectors = GetNumLogSectors(gplogdir, 0x11, true);
+    // Packet interface devices do not provide a log directory, check support bit
+    if (!nsectors && (drive.words047_079[76-47] & 0x0401) == 0x0400)
+      nsectors = 1;
     if (!nsectors)
-      pout("SATA Phy Event Counters (GP Log 0x11) not supported\n");
+      pout("SATA Phy Event Counters (GP Log 0x11) not supported\n\n");
     else if (nsectors != 1)
-      pout("SATA Phy Event Counters with %u sectors not supported\n", nsectors);
+      pout("SATA Phy Event Counters with %u sectors not supported\n\n", nsectors);
     else {
       unsigned char log_11[512] = {0, };
       unsigned char features = (options.sataphy_reset ? 0x01 : 0x00);
-      if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1))
+      if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1)) {
+        pout("Read SATA Phy Event Counters failed\n\n");
         failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+      }
       else
         PrintSataPhyEventCounters(log_11, options.sataphy_reset);
     }
@@ -3058,7 +3322,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   switch (options.smart_selftest_type) {
   case OFFLINE_FULL_SCAN:
     if (!isSupportExecuteOfflineImmediate(&smartval)){
-      pout("Warning: device does not support Execute Offline Immediate function.\n\n");
+      pout("Execute Offline Immediate function not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     break;
@@ -3068,21 +3332,21 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   case SHORT_CAPTIVE_SELF_TEST:
   case EXTEND_CAPTIVE_SELF_TEST:
     if (!isSupportSelfTest(&smartval)){
-      pout("Warning: device does not support Self-Test functions.\n\n");
+      pout("Self-test functions not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     break;
   case CONVEYANCE_SELF_TEST:
   case CONVEYANCE_CAPTIVE_SELF_TEST:
     if (!isSupportConveyanceSelfTest(&smartval)){
-      pout("Warning: device does not support Conveyance Self-Test functions.\n\n");
+      pout("Conveyance Self-test functions not supported\n\n");
       failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
     }
     break;
   case SELECTIVE_SELF_TEST:
   case SELECTIVE_CAPTIVE_SELF_TEST:
     if (!isSupportSelectiveSelfTest(&smartval)){
-      pout("Warning: device does not support Selective Self-Test functions.\n\n");
+      pout("Selective Self-test functions not supported\n\n");
       failuretest(MANDATORY_CMD, returnval|=FAILSMART);
     }
     break;
@@ -3105,7 +3369,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
       if (isSupportOfflineAbort(&smartval))
        pout("Note: giving further SMART commands will abort Offline testing\n");
       else if (ataReadSmartValues(device, &smartval)){
-       pout("Smartctl: SMART Read Values failed.\n");
+        pout("Read SMART Data failed: %s\n\n", device->get_errmsg());
        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
       }
     }
index 93fdb72cfa0faf7b12c421dd16fa1acfb3dc63bf..d8ca067581a17782527f89119cf71cbe1d58aa1a 100644 (file)
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -26,7 +25,7 @@
 #ifndef ATAPRINT_H_
 #define ATAPRINT_H_
 
-#define ATAPRINT_H_CVSID "$Id: ataprint.h 3530 2012-03-27 19:54:06Z chrfranke $\n"
+#define ATAPRINT_H_CVSID "$Id: ataprint.h 3609 2012-09-20 21:24:43Z chrfranke $\n"
 
 #include <vector>
 
@@ -47,6 +46,7 @@ struct ata_log_request
 struct ata_print_options
 {
   bool drive_info;
+  int identify_word_level, identify_bit_level;
   bool smart_check_status;
   bool smart_general_values;
   bool smart_vendor_attrib;
@@ -84,7 +84,7 @@ struct ata_print_options
   enum { FMT_BRIEF = 0x01, FMT_HEX_ID = 0x02, FMT_HEX_VAL = 0x04 };
   unsigned char output_format; // FMT_* flags
 
-  unsigned char fix_firmwarebug; // FIX_*, see atacmds.h
+  firmwarebug_defs firmwarebugs; // -F options
   bool fix_swapped_id; // Fix swapped ID strings returned by some buggy drivers
 
   ata_vendor_attr_defs attribute_defs; // -v options
@@ -109,6 +109,7 @@ struct ata_print_options
 
   ata_print_options()
     : drive_info(false),
+      identify_word_level(-1), identify_bit_level(-1),
       smart_check_status(false),
       smart_general_values(false),
       smart_vendor_attrib(false),
@@ -131,7 +132,6 @@ struct ata_print_options
       smart_selftest_type(-1), smart_selftest_force(false),
       sct_temp_int(0), sct_temp_int_pers(false),
       output_format(0),
-      fix_firmwarebug(FIX_NOTSPECIFIED),
       fix_swapped_id(false),
       ignore_presets(false),
       show_presets(false),
index 82da0ff990498b41c2f7de9926dfd57251f52f39..90d1e9561565cb1f845fa9e9fe1de5efdb501a8c 100755 (executable)
@@ -1,5 +1,5 @@
 #!/bin/sh
-# $Id: autogen.sh 3537 2012-04-28 13:22:41Z chrfranke $
+# $Id: autogen.sh 3748 2013-01-18 20:12:44Z chrfranke $
 #
 # Generate ./configure from config.in and Makefile.in from Makefile.am.
 # This also adds files like missing,depcomp,install-sh to the source
@@ -32,7 +32,8 @@ typep()
     return 1
 }
 
-test -x "$AUTOMAKE" || AUTOMAKE=`typep automake-1.11` || AUTOMAKE=`typep automake-1.10` ||
+test -x "$AUTOMAKE" || AUTOMAKE=`typep automake-1.12` ||
+    AUTOMAKE=`typep automake-1.11` || AUTOMAKE=`typep automake-1.10` ||
     AUTOMAKE=`typep automake-1.9` || AUTOMAKE=`typep automake-1.8` ||
     AUTOMAKE=`typep automake-1.7` || AUTOMAKE=`typep automake17` ||
 {
@@ -83,7 +84,7 @@ case "$ver" in
     rm -f casetest.tmp
     ;;
 
-  1.9.[1-6]|1.10|1.10.[12]|1.11|1.11.[1-3])
+  1.9.[1-6]|1.10|1.10.[12]|1.11|1.11.[1-6]|1.12.[3-5])
     # OK
     ;;
 
index 163491601b9c5941159f67735e1b37e6a4446f74..7d039b18dbf516d26cb7c4c2712aa4a3b2fab548 100644 (file)
--- a/cciss.cpp
+++ b/cciss.cpp
 #  define _HAVE_CCISS
 #elif defined(__FreeBSD_kernel__)
 #  include <endian.h>
+#  ifdef __GLIBC__
+#  include <bsd/sys/cdefs.h>
+#  include <stdint.h>
+#  endif
 #  include CISS_LOCATION
 #  define _HAVE_CCISS
 #endif
@@ -34,7 +38,7 @@
 #include "scsicmds.h"
 #include "utility.h"
 
-const char * cciss_cpp_cvsid = "$Id: cciss.cpp 3446 2011-10-13 22:36:28Z samm2 $"
+const char * cciss_cpp_cvsid = "$Id: cciss.cpp 3578 2012-07-20 17:26:32Z chrfranke $"
   CCISS_H_CVSID;
 
 typedef struct _ReportLUNdata_struct
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..912c0d2
--- /dev/null
@@ -0,0 +1,572 @@
+#
+# $Id: configure.ac 3811 2013-04-20 17:10:41Z chrfranke $
+#
+dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.50)
+AC_INIT(smartmontools, 6.2, 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.ac 3811 2013-04-20 17:10:41Z chrfranke $'`
+smartmontools_release_date=2013-03-16
+smartmontools_release_time="14:35:27 UTC"
+
+AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args",            [smartmontools Configure Arguments])
+AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_DATE, "$smartmontools_configure_date", [smartmontools Configure Date])
+AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_DATE,   "$smartmontools_release_date",   [smartmontools Release Date])
+AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_TIME,   "$smartmontools_release_time",   [smartmontools Release Time])
+AC_DEFINE_UNQUOTED(CONFIG_H_CVSID,               "$smartmontools_cvs_tag",        [smartmontools CVS Tag])
+AC_DEFINE_UNQUOTED(PACKAGE_HOMEPAGE,             "http://smartmontools.sourceforge.net/", [smartmontools Home Page])
+
+AM_CONFIG_HEADER(config.h)
+
+AM_INIT_AUTOMAKE([foreign])
+
+AM_MAINTAINER_MODE
+
+AC_LANG_CPLUSPLUS
+dnl Checks for programs.
+AC_PROG_CXX
+AM_PROG_AS
+AC_PROG_INSTALL
+
+m4_pattern_forbid([^PKG_PROG_])
+if test "$cross_compiling" = "no"; then
+  m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG],
+    [AC_MSG_WARN([m4/pkg.m4 missing, systemd detection disabled])])
+fi
+
+AC_ARG_VAR(WINDMC, [Windows message compiler command])
+AC_ARG_VAR(WINDRES, [Windows resource compiler command])
+AC_ARG_VAR(MAKENSIS, [NSIS compiler command])
+
+AC_CANONICAL_HOST
+case "${host}" in
+  *-*-mingw*)
+    # Cygwin gcc 4.x does no longer support '-mno-cygwin' to select MinGW gcc.
+    if test "${build}" = "${host}" && test -x /usr/bin/uname && \
+    /usr/bin/uname | grep -i '^CYGWIN' >/dev/null; then
+      AC_MSG_ERROR([Build with MinGW on Cygwin requires cross-compilation, see INSTALL file.])
+    fi
+    AC_CHECK_TOOL(WINDMC, [windmc])
+    AC_CHECK_TOOL(WINDRES, [windres])
+
+    AC_MSG_CHECKING([checking for makensis])
+    if test -z "$MAKENSIS"; then
+      if test -n "$PROGRAMFILES" && "$PROGRAMFILES/NSIS/makensis" -VERSION >/dev/null 2>&1; then
+        MAKENSIS="$PROGRAMFILES/NSIS/makensis"
+      elif makensis -VERSION >/dev/null 2>&1; then
+        MAKENSIS=makensis
+      fi
+    fi
+    AC_MSG_RESULT([${MAKENSIS:-no}])
+    ;;
+esac
+
+# Check for SVN.
+AC_MSG_CHECKING([whether this is a build from SVN])
+is_svn_build=no
+svn_deps=
+if test -f "$srcdir/.svn/entries"; then
+  is_svn_build=unknown
+  if (cd "$srcdir" && svn --version && svnversion && svn info) >/dev/null 2>&1; then
+    is_svn_build=yes
+    svn_deps='${srcdir}/.svn/entries'
+    # SVN 1.7 working copy?
+    test -f "$srcdir/.svn/wc.db" && svn_deps='${srcdir}/.svn/wc.db'
+  fi
+fi
+AC_SUBST([svn_deps])
+AM_CONDITIONAL(IS_SVN_BUILD, [test "$is_svn_build" = "yes"])
+AC_MSG_RESULT([$is_svn_build])
+
+# Note: On Linux, clock_gettime() requires -lrt which implies -lpthreads
+# Check ommitted for now, gettimeofday() provides reasonable precision
+# AC_SEARCH_LIBS(clock_gettime, rt)
+
+dnl Checks for header files.
+AC_CHECK_HEADERS([locale.h])
+AC_CHECK_HEADERS([dev/ata/atavar.h])
+AC_CHECK_HEADERS([netdb.h])
+dnl we need [u]int64_t and friends.
+AC_CHECK_HEADERS([inttypes.h])         dnl C99, UNIX98, solaris 2.6+
+AC_CHECK_HEADERS([stdint.h])           dnl C99
+AC_CHECK_HEADERS([sys/inttypes.h])     dnl pre-UNIX98
+AC_CHECK_HEADERS([sys/int_types.h])    dnl pre-UNIX98, solaris 2.6+
+dnl Check for FreeBSD twe include files...currently missing on 5.2, but should be there
+AC_CHECK_HEADERS([sys/tweio.h])
+AC_CHECK_HEADERS([sys/twereg.h])
+dnl Check for FreeBSD twa include files...
+AC_CHECK_HEADERS([sys/tw_osl_ioctl.h])
+dnl This header file is needed for cciss_ioctl.h at least on SuSE LINUX
+AC_CHECK_HEADERS([linux/compiler.h])
+dnl Check for the FreeBSD CCISS system header and use internal one if not found
+AC_CHECK_HEADERS([dev/ciss/cissio.h],
+    [AC_DEFINE([CISS_LOCATION],[<dev/ciss/cissio.h>],[freebsd ciss header location])],
+    [AC_DEFINE([CISS_LOCATION],["cissio_freebsd.h"],[freebsd ciss header location])]
+    )
+dnl Check for Linux CCISS include file
+AC_CHECK_HEADERS([linux/cciss_ioctl.h], [], [], [AC_INCLUDES_DEFAULT
+#ifdef HAVE_LINUX_COMPILER_H
+# include <linux/compiler.h>
+#endif
+])
+dnl Check for Windows DDK and WMI header files
+AC_CHECK_HEADERS([ntdddisk.h ddk/ntdddisk.h], [], [], [AC_INCLUDES_DEFAULT
+#include <windows.h>
+])
+AC_CHECK_HEADERS([wbemcli.h])
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_CHECK_TYPES([int64_t, uint64_t])
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS([getopt_long], [need_getopt_long=no], [need_getopt_long=yes])
+AM_CONDITIONAL(NEED_GETOPT_LONG, [test "$need_getopt_long" = "yes"])
+AC_CHECK_FUNCS([regcomp], [need_regex=no], [need_regex=yes])
+AM_CONDITIONAL(NEED_REGEX, [test "$need_regex" = "yes"])
+
+AC_CHECK_FUNCS([sigset])
+AC_CHECK_FUNCS([strtoull])
+AC_CHECK_FUNCS([uname])
+AC_CHECK_FUNCS([clock_gettime ftime gettimeofday])
+
+# Check byte ordering (defines WORDS_BIGENDIAN)
+AC_C_BIGENDIAN
+
+# Check whether snprintf appends null char and returns expected length on overflow
+AC_MSG_CHECKING([for working snprintf])
+AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[ char buf[]="ABCDEFGHI";
+               int i=snprintf(buf,8,"12345678"); return !(!buf[7] && i==8); ]])],
+              [libc_have_working_snprintf=yes],
+              [libc_have_working_snprintf=no],
+              [libc_have_working_snprintf=unknown])
+AC_SUBST(libc_have_working_snprintf)
+if test "$libc_have_working_snprintf" = "yes"; then
+  AC_DEFINE(HAVE_WORKING_SNPRINTF, 1, [Define to 1 if the `snprintf' function is sane])
+fi
+AC_MSG_RESULT([$libc_have_working_snprintf])
+
+# check for __attribute__((packed))
+# (sizeof() check is required to avoid false positives if other
+# __attribute__((x)) are supported)
+AC_MSG_CHECKING([whether $CXX supports __attribute__((packed))])
+AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [[
+    struct s { char a; short b; } __attribute__((packed));
+    typedef char t[sizeof(struct s) == 3 ? 1 : -1];]])],
+  [gcc_have_attr_packed=yes], [gcc_have_attr_packed=no])
+AC_SUBST(gcc_have_attr_packed)
+if test "$gcc_have_attr_packed" = "yes"; then
+  AC_DEFINE(HAVE_ATTR_PACKED, 1, [Define to 1 if C++ compiler supports __attribute__((packed))])
+fi
+AC_MSG_RESULT([$gcc_have_attr_packed])
+
+AC_SUBST(CPPFLAGS)
+AC_SUBST(LDFLAGS)
+AC_SUBST(ASFLAGS)
+
+AC_ARG_WITH(systemdsystemunitdir,
+  [AS_HELP_STRING([--with-systemdsystemunitdir@<:@=DIR|auto|yes|no@:>@], [Location of systemd service files [auto]])],
+  [], [with_systemdsystemunitdir=auto])
+
+systemdsystemunitdir=
+case "$with_systemdsystemunitdir" in
+ auto|yes)
+   if test -n "$PKG_CONFIG"; then
+     AC_MSG_CHECKING([for systemdsystemunitdir])
+     systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd`
+     AC_MSG_RESULT([${systemdsystemunitdir:-no}])
+   fi
+   case "$with_systemdsystemunitdir:$sysconfdir:$systemdsystemunitdir" in
+     yes:*:) AC_MSG_ERROR([Location of systemd service files not found]) ;;
+     yes:*:*|auto:*:|auto:/etc:*) ;;
+     *) systemdsystemunitdir='${prefix}'$systemdsystemunitdir ;;
+   esac ;;
+ no) ;;
+ *) systemdsystemunitdir="$with_systemdsystemunitdir" ;;
+esac
+AC_SUBST(systemdsystemunitdir)
+AM_CONDITIONAL(INSTALL_SYSTEMDUNIT, [test -n "$systemdsystemunitdir"])
+
+AC_ARG_WITH(initscriptdir,
+  [AC_HELP_STRING([--with-initscriptdir@<:@=DIR|auto|yes|no@:>@], [Location of init scripts [auto]])],
+  [], [with_initscriptdir=auto])
+
+initddir=
+case "$with_initscriptdir:$cross_compiling:$systemdsystemunitdir" in
+  auto:no:|yes:*)
+    AC_MSG_CHECKING([for init (rc) directory])
+    for dir in rc.d/init.d init.d rc.d; do
+      if test -d /etc/$dir; then
+        initddir='${sysconfdir}'/$dir
+        break
+      fi
+    done
+    AC_MSG_RESULT([${initddir:-no}])
+    case "$with_initscriptdir:$initddir" in
+      yes:) AC_MSG_ERROR([Location of init scripts not found]) ;;
+    esac ;;
+  auto:*|no:*) ;;
+  *) initddir="$with_initscriptdir" ;;
+esac
+AC_SUBST(initddir)
+AM_CONDITIONAL(INSTALL_INITSCRIPT, [test -n "$initddir"])
+
+# use different init script templates for different OS
+case "${host}" in
+  *-*-freebsd*)
+    initdfile="smartd.freebsd.initd"
+    ;;
+  *)
+    initdfile="smartd.initd"
+    ;;
+esac
+AC_SUBST(initdfile)
+
+AC_ARG_WITH(docdir,
+  [AC_HELP_STRING([--with-docdir=DIR],[Location of documentation [DATADIR/doc/smartmontools]])],
+  [docdir="$withval"],
+  [ if test -z "$docdir"; then
+      # autoconf 2.5x without '--docdir' support
+      docdir='${datadir}/doc/${PACKAGE}'
+    fi
+  ])
+AC_SUBST(docdir)
+
+AC_ARG_WITH(exampledir,
+  [AC_HELP_STRING([--with-exampledir=DIR],[Location of example scripts [DOCDIR/examplescripts]])],
+  [exampledir="$withval"], [exampledir='${docdir}/examplescripts'])
+AC_SUBST(exampledir)
+
+AC_ARG_ENABLE(drivedb,
+  [AC_HELP_STRING([--disable-drivedb],[Disables drive database file])],
+  [], [enable_drivedb=yes])
+
+AC_ARG_WITH(drivedbdir,
+  [AC_HELP_STRING([--with-drivedbdir=DIR],[Location of drive database file (implies --enable-drivedb) [DATADIR/smartmontools]])],
+  [drivedbdir="$withval"; enable_drivedb=yes],
+  [drivedbdir=; test "$enable_drivedb" = "yes" && drivedbdir='${datadir}/${PACKAGE}'])
+AC_SUBST(drivedbdir)
+AM_CONDITIONAL(ENABLE_DRIVEDB, [test "$enable_drivedb" = "yes"])
+
+AC_ARG_ENABLE(savestates, [AC_HELP_STRING([--enable-savestates],[Enables default smartd state files])])
+
+AC_ARG_WITH(savestates,
+  [AC_HELP_STRING([--with-savestates=PREFIX],[Prefix for default smartd state files (implies --enable-savestates) [LOCALSTATEDIR/lib/smartmontools/smartd.]])],
+  [savestates="$withval"; enable_savestates="yes"],
+  [savestates=; test "$enable_savestates" = "yes" && savestates='${localstatedir}/lib/${PACKAGE}/smartd.'])
+savestatesdir="${savestates%/*}"
+AC_SUBST(savestates)
+AC_SUBST(savestatesdir)
+AM_CONDITIONAL(ENABLE_SAVESTATES, [test "$enable_savestates" = "yes"])
+
+AC_ARG_ENABLE(attributelog, [AC_HELP_STRING([--enable-attributelog],[Enables default smartd attribute log files])])
+
+AC_ARG_WITH(attributelog,
+  [AC_HELP_STRING([--with-attributelog=PREFIX],[Prefix for default smartd attribute log files (implies --enable-attributelog) [LOCALSTATEDIR/lib/smartmontools/attrlog.]])],
+  [attributelog="$withval"; enable_attributelog="yes"],
+  [attributelog=; test "$enable_attributelog" = "yes" && attributelog='${localstatedir}/lib/${PACKAGE}/attrlog.'])
+attributelogdir="${attributelog%/*}"
+AC_SUBST(attributelog)
+AC_SUBST(attributelogdir)
+AM_CONDITIONAL(ENABLE_ATTRIBUTELOG, [test "$enable_attributelog" = "yes"])
+
+AC_ARG_ENABLE(sample,
+  [AC_HELP_STRING([--enable-sample],[Enables appending .sample to the installed smartd rc script and configuration file])],
+  [smartd_suffix=; test "$enableval" = "yes" && smartd_suffix=".sample"],
+  [smartd_suffix=;])
+AC_SUBST(smartd_suffix)
+
+AC_ARG_WITH(os-deps,
+  [AC_HELP_STRING([--with-os-deps='os_module.o ...'],[Specify OS dependent module(s) [guessed]])],
+  [ for x in $with_os_deps; do
+      case $x in
+        *.o) ;;
+        *) AC_MSG_ERROR([non-object file specified by --with-os-deps]) ;;
+      esac
+    done
+  ],[])
+
+AC_ARG_WITH(selinux,
+  [AC_HELP_STRING([--with-selinux@<:@=yes|no@:>@],[Enables SELinux support [no]])],
+  [ if test "$withval" = "yes"; then
+      AC_CHECK_HEADERS([selinux/selinux.h], [], [AC_MSG_ERROR([Missing SELinux header files])])
+      AC_CHECK_LIB(selinux, matchpathcon, [], [AC_MSG_ERROR([Missing or incorrect SELinux library files])])
+    fi
+  ],[])
+AC_SUBST(with_selinux)
+if test "$with_selinux" = "yes"; then
+  AC_DEFINE(WITH_SELINUX, 1, [Define to 1 if SELinux support is enabled])
+fi
+
+AC_ARG_WITH(libcap-ng,
+  [AC_HELP_STRING([--with-libcap-ng@<:@=auto|yes|no@:>@],[Add Libcap-ng support to smartd [auto]])],
+  [], [with_libcap_ng=auto])
+
+use_libcap_ng=no
+if test "$with_libcap_ng" != "no"; then
+  AC_CHECK_LIB(cap-ng, capng_clear,
+    [AC_DEFINE(HAVE_LIBCAP_NG, 1, [Define to 1 if you have the `cap-ng' library (-lcap-ng).])
+     CAPNG_LDADD="-lcap-ng"; use_libcap_ng=yes])
+
+  if test "$use_libcap_ng" = "yes"; then
+    AC_CHECK_HEADER(cap-ng.h, [], [AC_MSG_ERROR([libcap-ng libraries found but headers are missing])])
+  elif test "$with_libcap_ng" = "yes"; then
+    AC_MSG_ERROR([libcap-ng support was requested but the library was not found])
+  fi
+fi
+
+AC_MSG_CHECKING([whether to use libcap-ng])
+AC_SUBST(CAPNG_LDADD)
+AM_CONDITIONAL(ENABLE_CAPABILITIES, [test "$use_libcap_ng" = "yes"])
+AC_MSG_RESULT([$use_libcap_ng])
+
+if test "$prefix" = "NONE"; then
+    dnl no prefix and no mandir, so use ${prefix}/share/man as default
+    if test "$mandir" = '${prefix}/man'; then
+       AC_SUBST([mandir], ['${prefix}/share/man'])
+    fi
+fi
+
+AC_SUBST(releaseversion,['${PACKAGE}-${VERSION}'])
+AC_SUBST(smartmontools_release_date)
+AC_SUBST(smartmontools_release_time)
+
+# Set platform-specific modules and symbols
+os_libs=
+os_dltools='curl wget lynx'
+os_mailer=mail
+os_hostname="'hostname'"
+os_dnsdomainname=
+os_nisdomainname="'domainname'"
+os_darwin=no
+os_solaris=no
+os_win32=no
+os_win32_mingw=no
+os_win64=no
+os_man_filter=
+case "${host}" in
+  *-*-linux*)
+    os_deps='os_linux.o cciss.o dev_areca.o'
+    os_dnsdomainname="'dnsdomainname' 'hostname -d'"
+    os_nisdomainname="'nisdomainname' 'hostname -y' 'domainname'"
+    os_man_filter=Linux
+    ;;
+  *-*-freebsd*|*-*-dragonfly*|*-*-kfreebsd*-gnu*)
+    os_deps='os_freebsd.o cciss.o dev_areca.o'
+    os_libs='-lcam'
+    os_dltools='curl wget lynx fetch'
+    AC_CHECK_LIB(usb, libusb20_dev_get_device_desc)
+    os_man_filter=FreeBSD
+    ;;
+  sparc-*-solaris*)
+    os_deps='os_solaris.o os_solaris_ata.o'
+    os_mailer='mailx'
+    os_solaris=yes
+    os_man_filter=Solaris
+    ;;
+  *-pc-solaris*)
+    os_deps='os_solaris.o'
+    os_mailer='mailx'
+    os_solaris=yes
+    os_man_filter=Solaris
+    ;;
+  *-*-netbsd*)
+    os_deps='os_netbsd.o'
+    os_libs='-lutil'
+    os_man_filter=NetBSD
+    ;;
+  *-*-openbsd*)
+    os_deps='os_openbsd.o'
+    os_libs='-lutil'
+    os_dltools='curl wget lynx ftp'
+    os_man_filter=OpenBSD
+    ;;
+  *-*-cygwin*)
+    os_deps='os_win32.o dev_areca.o'
+    os_hostname="'hostname' 'echo "'"${HOSTNAME?unset}"'"'"
+    os_dnsdomainname="'dnsdomainname' 'hostname -d' 'echo "'"${USERDNSDOMAIN?unset}"'"'"
+    os_nisdomainname=
+    os_win32=yes
+    os_man_filter=Cygwin
+    ;;
+  x86_64-*-mingw*)
+    os_deps='os_win32.o dev_areca.o'
+    os_win32=yes
+    os_win32_mingw=yes
+    os_win64=yes
+    os_man_filter=Windows
+    ;;
+  *-*-mingw*)
+    os_deps='os_win32.o dev_areca.o'
+    os_win32=yes
+    os_win32_mingw=yes
+    os_man_filter=Windows
+    ;;
+  *-*-darwin*)
+    os_deps='os_darwin.o'
+    os_libs='-framework CoreFoundation -framework IOKit'
+    os_darwin=yes
+    os_man_filter=Darwin
+    ;;
+  *-*-nto-qnx*)
+    os_deps='os_qnxnto.o'
+    ;;
+  *)
+    os_deps='os_generic.o'
+    ;;
+esac
+
+# Replace if '--with-os-deps' was specified
+test -z "$with_os_deps" || os_deps="$with_os_deps"
+
+# Check if we need adapter to old interface (dev_legacy.cpp)
+os_src=`echo "${os_deps}"|sed -n 's,^\([[^ .]]*\)\.o.*$,\1.cpp,p'`
+AC_MSG_CHECKING([whether ${os_src} uses new interface])
+if grep "smart_interface" "${srcdir}/${os_src}" >/dev/null 2>&1; then
+  os_new_interface=yes
+else
+  os_new_interface=no
+  os_deps="${os_deps} dev_legacy.o"
+  AC_DEFINE(OLD_INTERFACE, 1, [Define to 1 if os_*.cpp still uses the old interface])
+fi
+AC_MSG_RESULT([$os_new_interface])
+
+AC_SUBST([os_deps])
+AC_SUBST([os_libs])
+AC_SUBST([os_dltools])
+AC_SUBST([os_mailer])
+AC_SUBST([os_hostname])
+AC_SUBST([os_dnsdomainname])
+AC_SUBST([os_nisdomainname])
+AC_SUBST([os_man_filter])
+
+# Create drivedb.h update branch name from version: 5.41[.X] -> RELEASE_5_41_DRIVEDB
+DRIVEDB_BRANCH=`echo $VERSION | sed 's,^\([[0-9]]*\.[[0-9]]*\)\..*$,\1,' \
+                | sed -n 's,^\([[0-9]][[0-9]]*\)\.\([[0-9]][[0-9]]*\)$,RELEASE_\1_\2_DRIVEDB,p'`
+if test -z "$DRIVEDB_BRANCH"; then
+  AC_MSG_ERROR([Unable to create DRIVEDB_BRANCH from VERSION=$VERSION])
+fi
+AC_SUBST([DRIVEDB_BRANCH])
+
+# Enable platform-specific makefile sections
+AM_CONDITIONAL(OS_DARWIN, [test "$os_darwin" = "yes"])
+AM_CONDITIONAL(OS_SOLARIS, [test "$os_solaris" = "yes"])
+AM_CONDITIONAL(OS_WIN32, [test "$os_win32" = "yes"])
+AM_CONDITIONAL(OS_WIN32_MINGW, [test "$os_win32_mingw" = "yes"])
+AM_CONDITIONAL(OS_WIN32_NSIS, [test -n "$MAKENSIS"])
+AM_CONDITIONAL(OS_WIN64, [test "$os_win64" = "yes"])
+
+dnl Add -Wall and -W if using g++ and its not already specified.
+if test "$GXX" = "yes"; then
+  if test -z "`echo "$CXXFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
+      CXXFLAGS="$CXXFLAGS -Wall"
+  fi
+# In the next line, do NOT delete the 2 spaces inside double quotes.
+  if test -z "`echo "$CXXFLAGS " | grep "\-W " 2> /dev/null`" ; then
+      CXXFLAGS="$CXXFLAGS -W"
+  fi
+
+else
+ dnl We are NOT using gcc, so enable host-specific compiler flags
+ case "${host}" in
+       sparc*-*-solaris*) 
+          dnl set CXXFLAGS for Solaris/SPARC C++ compiler
+          if test -z "`echo "$CXXFLAGS" | grep "\-xmemalign" 2> /dev/null`" ; then
+            dnl we have to tell the compilers about packed ATA structures
+            CXXFLAGS="-xmemalign=1i $CXXFLAGS"
+          fi
+ esac
+ case "${host}" in
+       *-*-solaris*) 
+          if test -z "`echo "$CXXFLAGS" | grep "\-xO" 2> /dev/null`" ; then
+            dnl turn on optimization if user has not explicitly set its value
+            CXXFLAGS="-xO2 $CXXFLAGS"
+          fi
+          if test -z "`echo "$CXXFLAGS" | grep "\-erroff" 2> /dev/null`" ; then
+           dnl suppress trivial warnings
+           CXXFLAGS="-erroff=%none,wbadinitl,wbadasgl,badargtypel2w,badargtype2w $CXXFLAGS"
+         fi
+ esac
+fi
+
+AC_DEFINE_UNQUOTED(SMARTMONTOOLS_BUILD_HOST,     "${host}",                       [smartmontools Build Host])
+
+AC_SUBST(CXXFLAGS)
+
+AC_CONFIG_FILES(Makefile)
+AC_OUTPUT
+AC_PROG_MAKE_SET
+
+echo "-----------------------------------------------------------------------------" >&AS_MESSAGE_FD
+echo "${PACKAGE}-${VERSION} configuration:" >&AS_MESSAGE_FD
+echo "host operating system:  $host" >&AS_MESSAGE_FD
+echo "C++ compiler:           $CXX" >&AS_MESSAGE_FD
+echo "C compiler:             $CC" >&AS_MESSAGE_FD
+echo "preprocessor flags:     $CPPFLAGS" >&AS_MESSAGE_FD
+echo "C++ compiler flags:     $CXXFLAGS" >&AS_MESSAGE_FD
+echo "C compiler flags:       $CFLAGS" >&AS_MESSAGE_FD
+echo "linker flags:           $LDFLAGS" >&AS_MESSAGE_FD
+echo "OS specific modules:    $os_deps $os_libs $LIBS" >&AS_MESSAGE_FD
+
+case "$host_os" in
+  mingw*)
+    echo "resource compiler:      $WINDRES" >&AS_MESSAGE_FD
+    echo "message compiler:       $WINDMC" >&AS_MESSAGE_FD
+    echo "NSIS compiler:          $MAKENSIS" >&AS_MESSAGE_FD
+    if test -n "$drivedbdir"; then
+      echo "drive database file:    EXEDIR/drivedb.h" >&AS_MESSAGE_FD
+      if test -n "$MAKENSIS"; then
+        echo "database update tool:   EXEDIR/update-smart-drivedb.exe" >&AS_MESSAGE_FD
+      fi
+    else
+      echo "drive database file:    [[disabled]]" >&AS_MESSAGE_FD
+    fi
+    if test -n "$savestates"; then
+      echo "smartd save files:      `eval eval eval echo $savestates`MODEL-SERIAL.TYPE.state" >&AS_MESSAGE_FD
+    fi
+    if test -n "$attributelog"; then
+      echo "smartd attribute logs:  `eval eval eval echo $attributelog`MODEL-SERIAL.TYPE.csv" >&AS_MESSAGE_FD
+    fi
+    ;;
+
+  *)
+    echo "binary install path:    `eval eval eval echo $sbindir`" >&AS_MESSAGE_FD
+    echo "man page install path:  `eval eval eval echo $mandir`" >&AS_MESSAGE_FD
+    echo "doc file install path:  `eval eval eval echo $docdir`" >&AS_MESSAGE_FD
+    echo "examples install path:  `eval eval eval echo $exampledir`" >&AS_MESSAGE_FD
+    if test -n "$drivedbdir"; then
+      echo "drive database file:    `eval eval eval echo $drivedbdir`/drivedb.h" >&AS_MESSAGE_FD
+      echo "database update script: `eval eval eval echo $sbindir`/update-smart-drivedb" >&AS_MESSAGE_FD
+      echo "download tools:         `eval eval eval echo $os_dltools`" >&AS_MESSAGE_FD
+    else
+      echo "drive database file:    [[disabled]]" >&AS_MESSAGE_FD
+    fi
+    echo "local drive database:   `eval eval eval echo $sysconfdir`/smart_drivedb.h" >&AS_MESSAGE_FD
+    echo "smartd config file:     `eval eval eval echo $sysconfdir`/smartd.conf${smartd_suffix}" >&AS_MESSAGE_FD
+    echo "smartd warning script:  `eval eval eval echo $sysconfdir`/smartd_warning.sh" >&AS_MESSAGE_FD
+    if test -n "$initddir"; then
+      echo "smartd initd script:    `eval eval eval echo $initddir`/smartd${smartd_suffix}" >&AS_MESSAGE_FD
+    elif test -z "$systemdsystemunitdir"; then
+      echo "smartd initd script:    [[disabled]]" >&AS_MESSAGE_FD
+    fi
+    if test -n "$systemdsystemunitdir"; then
+      echo "smartd systemd file:    `eval eval eval echo $systemdsystemunitdir`/smartd.service" >&AS_MESSAGE_FD
+    fi
+    if test -n "$savestates"; then
+      echo "smartd save files:      `eval eval eval echo $savestates`MODEL-SERIAL.TYPE.state" >&AS_MESSAGE_FD
+    else
+      echo "smartd save files:      [[disabled]]" >&AS_MESSAGE_FD
+    fi
+    if test -n "$attributelog"; then
+      echo "smartd attribute logs:  `eval eval eval echo $attributelog`MODEL-SERIAL.TYPE.csv" >&AS_MESSAGE_FD
+    else
+      echo "smartd attribute logs:  [[disabled]]" >&AS_MESSAGE_FD
+    fi
+    echo "libcap-ng support:      $use_libcap_ng" >&AS_MESSAGE_FD
+    case "$host_os" in
+      linux*) echo "SELinux support:        ${with_selinux-no}" >&AS_MESSAGE_FD ;;
+    esac
+    ;;
+esac
+echo "-----------------------------------------------------------------------------" >&AS_MESSAGE_FD
diff --git a/configure.in b/configure.in
deleted file mode 100644 (file)
index 5c3d352..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-#
-# $Id: configure.in 3527 2012-03-25 16:42:24Z chrfranke $
-#
-dnl Process this file with autoconf to produce a configure script.
-AC_PREREQ(2.50)
-AC_INIT(smartmontools, 5.43, 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 3527 2012-03-25 16:42:24Z chrfranke $'`
-smartmontools_release_date=2011-10-20
-smartmontools_release_time="19:19:34 UTC"
-
-AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_ARGS, "$ac_configure_args",            [smartmontools Configure Arguments])
-AC_DEFINE_UNQUOTED(SMARTMONTOOLS_CONFIGURE_DATE, "$smartmontools_configure_date", [smartmontools Configure Date])
-AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_DATE,   "$smartmontools_release_date",   [smartmontools Release Date])
-AC_DEFINE_UNQUOTED(SMARTMONTOOLS_RELEASE_TIME,   "$smartmontools_release_time",   [smartmontools Release Time])
-AC_DEFINE_UNQUOTED(CONFIG_H_CVSID,               "$smartmontools_cvs_tag",        [smartmontools CVS Tag])
-AC_DEFINE_UNQUOTED(PACKAGE_HOMEPAGE,             "http://smartmontools.sourceforge.net/", [smartmontools Home Page])
-
-AM_CONFIG_HEADER(config.h)
-
-AM_INIT_AUTOMAKE([foreign])
-
-AM_MAINTAINER_MODE
-
-AC_LANG_CPLUSPLUS
-dnl Checks for programs.
-AC_PROG_CXX
-AM_PROG_AS
-AC_PROG_INSTALL
-
-m4_pattern_forbid([^PKG_PROG_])
-if test "$cross_compiling" = "no"; then
-  m4_ifdef([PKG_PROG_PKG_CONFIG], [PKG_PROG_PKG_CONFIG],
-    [AC_MSG_WARN([m4/pkg.m4 missing, systemd detection disabled])])
-fi
-
-AC_ARG_VAR(WINDMC, [Windows message compiler command])
-AC_ARG_VAR(WINDRES, [Windows resource compiler command])
-AC_ARG_VAR(MAKENSIS, [NSIS compiler command])
-
-AC_CANONICAL_HOST
-case "${host}" in
-  *-*-mingw*)
-    # Cygwin gcc 4.x does no longer support '-mno-cygwin' to select MinGW gcc.
-    if test "${build}" = "${host}" && test -x /usr/bin/uname && \
-    /usr/bin/uname | grep -i '^CYGWIN' >/dev/null; then
-      AC_MSG_ERROR([Build with MinGW on Cygwin requires cross-compilation, see INSTALL file.])
-    fi
-    AC_CHECK_PROGS(WINDMC, [${host}-windmc windmc])
-    AC_CHECK_PROGS(WINDRES, [${host}-windres windres])
-
-    AC_MSG_CHECKING([checking for makensis])
-    if test -z "$MAKENSIS"; then
-      if test -n "$PROGRAMFILES" && "$PROGRAMFILES/NSIS/makensis" -VERSION >/dev/null 2>&1; then
-        MAKENSIS="$PROGRAMFILES/NSIS/makensis"
-      elif makensis -VERSION >/dev/null 2>&1; then
-        MAKENSIS=makensis
-      fi
-    fi
-    AC_MSG_RESULT([${MAKENSIS:-no}])
-    ;;
-esac
-
-# Check for SVN.
-AC_MSG_CHECKING([whether this is a build from SVN])
-is_svn_build=no
-svn_deps=
-if test -f "$srcdir/.svn/entries"; then
-  is_svn_build=unknown
-  if (cd "$srcdir" && svn --version && svnversion && svn info) >/dev/null 2>&1; then
-    is_svn_build=yes
-    svn_deps='${srcdir}/.svn/entries'
-    # SVN 1.7 working copy?
-    test -f "$srcdir/.svn/wc.db" && svn_deps='${srcdir}/.svn/wc.db'
-  fi
-fi
-AC_SUBST([svn_deps])
-AM_CONDITIONAL(IS_SVN_BUILD, [test "$is_svn_build" = "yes"])
-AC_MSG_RESULT([$is_svn_build])
-
-dnl Checks for libraries needed for name services (Solaris needs
-dnl libnsl, might in the future also need libsocket)
-#  AC_SEARCH_LIBS (FUNCTION, SEARCH-LIBS, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], [OTHER-LIBRARIES])
-AC_SEARCH_LIBS(socket, socket)
-AC_SEARCH_LIBS(gethostbyname, nsl)
-AC_SEARCH_LIBS(getaddrinfo, nsl)
-AC_SEARCH_LIBS(getdomainname, nsl)
-
-# Note: On Linux, clock_gettime() requires -lrt which implies -lpthreads
-# Check ommitted for now, gettimeofday() provides reasonable precision
-# AC_SEARCH_LIBS(clock_gettime, rt)
-
-dnl Checks for header files.
-AC_CHECK_HEADERS([locale.h])
-AC_CHECK_HEADERS([dev/ata/atavar.h])
-AC_CHECK_HEADERS([netdb.h])
-dnl we need [u]int64_t and friends.
-AC_CHECK_HEADERS([inttypes.h])         dnl C99, UNIX98, solaris 2.6+
-AC_CHECK_HEADERS([stdint.h])           dnl C99
-AC_CHECK_HEADERS([sys/inttypes.h])     dnl pre-UNIX98
-AC_CHECK_HEADERS([sys/int_types.h])    dnl pre-UNIX98, solaris 2.6+
-dnl Check for FreeBSD twe include files...currently missing on 5.2, but should be there
-AC_CHECK_HEADERS([sys/tweio.h])
-AC_CHECK_HEADERS([sys/twereg.h])
-dnl Check for FreeBSD twa include files...
-AC_CHECK_HEADERS([sys/tw_osl_ioctl.h])
-dnl This header file is needed for cciss_ioctl.h at least on SuSE LINUX
-AC_CHECK_HEADERS([linux/compiler.h])
-dnl Check for the FreeBSD CCISS system header and use internal one if not found
-AC_CHECK_HEADERS([dev/ciss/cissio.h],
-    [AC_DEFINE([CISS_LOCATION],[<dev/ciss/cissio.h>],[freebsd ciss header location])],
-    [AC_DEFINE([CISS_LOCATION],["cissio_freebsd.h"],[freebsd ciss header location])]
-    )
-dnl Check for Linux CCISS include file
-AC_CHECK_HEADERS([linux/cciss_ioctl.h], [], [], [AC_INCLUDES_DEFAULT
-#ifdef HAVE_LINUX_COMPILER_H
-# include <linux/compiler.h>
-#endif
-])
-dnl Check for Windows DDK and WMI header files
-AC_CHECK_HEADERS([ntdddisk.h ddk/ntdddisk.h], [], [], [AC_INCLUDES_DEFAULT
-#include <windows.h>
-])
-AC_CHECK_HEADERS([wbemcli.h])
-
-dnl Checks for typedefs, structures, and compiler characteristics.
-AC_CHECK_TYPES([int64_t, uint64_t])
-
-dnl Checks for library functions.
-AC_CHECK_FUNCS([getopt_long], [need_getopt_long=no], [need_getopt_long=yes])
-AM_CONDITIONAL(NEED_GETOPT_LONG, [test "$need_getopt_long" = "yes"])
-AC_CHECK_FUNCS([regcomp], [need_regex=no], [need_regex=yes])
-AM_CONDITIONAL(NEED_REGEX, [test "$need_regex" = "yes"])
-
-AC_CHECK_FUNCS([getdomainname])
-AC_CHECK_FUNCS([gethostname])
-AC_CHECK_FUNCS([getaddrinfo])
-AC_CHECK_FUNCS([gethostbyname])
-AC_CHECK_FUNCS([sigset])
-AC_CHECK_FUNCS([strtoull])
-AC_CHECK_FUNCS([uname])
-AC_CHECK_FUNCS([clock_gettime ftime gettimeofday])
-
-# Check byte ordering (defines WORDS_BIGENDIAN)
-AC_C_BIGENDIAN
-
-# Check whether snprintf appends null char and returns expected length on overflow
-AC_MSG_CHECKING([for working snprintf])
-AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[ char buf[]="ABCDEFGHI";
-               int i=snprintf(buf,8,"12345678"); return !(!buf[7] && i==8); ]])],
-              [libc_have_working_snprintf=yes],
-              [libc_have_working_snprintf=no],
-              [libc_have_working_snprintf=unknown])
-AC_SUBST(libc_have_working_snprintf)
-if test "$libc_have_working_snprintf" = "yes"; then
-  AC_DEFINE(HAVE_WORKING_SNPRINTF, 1, [Define to 1 if the `snprintf' function is sane])
-fi
-AC_MSG_RESULT([$libc_have_working_snprintf])
-
-# check for __attribute__((packed))
-# (sizeof() check is required to avoid false positives if other
-# __attribute__((x)) are supported)
-AC_MSG_CHECKING([whether $CXX supports __attribute__((packed))])
-AC_COMPILE_IFELSE([AC_LANG_PROGRAM(, [[
-    struct s { char a; short b; } __attribute__((packed));
-    typedef char t[sizeof(struct s) == 3 ? 1 : -1];]])],
-  [gcc_have_attr_packed=yes], [gcc_have_attr_packed=no])
-AC_SUBST(gcc_have_attr_packed)
-if test "$gcc_have_attr_packed" = "yes"; then
-  AC_DEFINE(HAVE_ATTR_PACKED, 1, [Define to 1 if C++ compiler supports __attribute__((packed))])
-fi
-AC_MSG_RESULT([$gcc_have_attr_packed])
-
-AC_SUBST(CPPFLAGS)
-AC_SUBST(LDFLAGS)
-AC_SUBST(ASFLAGS)
-
-AC_ARG_WITH(systemdsystemunitdir,
-  [AS_HELP_STRING([--with-systemdsystemunitdir@<:@=DIR|auto|yes|no@:>@], [Location of systemd service files [auto]])],
-  [], [with_systemdsystemunitdir=auto])
-
-systemdsystemunitdir=
-case "$with_systemdsystemunitdir" in
- auto|yes)
-   if test -n "$PKG_CONFIG"; then
-     AC_MSG_CHECKING([for systemdsystemunitdir])
-     systemdsystemunitdir=`$PKG_CONFIG --variable=systemdsystemunitdir systemd`
-     AC_MSG_RESULT([${systemdsystemunitdir:-no}])
-   fi
-   case "$with_systemdsystemunitdir:$sysconfdir:$systemdsystemunitdir" in
-     yes:*:) AC_MSG_ERROR([Location of systemd service files not found]) ;;
-     yes:*:*|auto:*:|auto:/etc:*) ;;
-     *) systemdsystemunitdir='${prefix}'$systemdsystemunitdir ;;
-   esac ;;
- no) ;;
- *) systemdsystemunitdir="$with_systemdsystemunitdir" ;;
-esac
-AC_SUBST(systemdsystemunitdir)
-AM_CONDITIONAL(INSTALL_SYSTEMDUNIT, [test -n "$systemdsystemunitdir"])
-
-AC_ARG_WITH(initscriptdir,
-  [AC_HELP_STRING([--with-initscriptdir@<:@=DIR|auto|yes|no@:>@], [Location of init scripts [auto]])],
-  [], [with_initscriptdir=auto])
-
-initddir=
-case "$with_initscriptdir:$cross_compiling:$systemdsystemunitdir" in
-  auto:no:|yes:*)
-    AC_MSG_CHECKING([for init (rc) directory])
-    for dir in rc.d/init.d init.d rc.d; do
-      if test -d /etc/$dir; then
-        initddir='${sysconfdir}'/$dir
-        break
-      fi
-    done
-    AC_MSG_RESULT([${initddir:-no}])
-    case "$with_initscriptdir:$initddir" in
-      yes:) AC_MSG_ERROR([Location of init scripts not found]) ;;
-    esac ;;
-  auto:*|no:*) ;;
-  *) initddir="$with_initscriptdir" ;;
-esac
-AC_SUBST(initddir)
-AM_CONDITIONAL(INSTALL_INITSCRIPT, [test -n "$initddir"])
-
-# use different init script templates for different OS
-case "${host}" in
-  *-*-freebsd*)
-    initdfile="smartd.freebsd.initd"
-    ;;
-  *)
-    initdfile="smartd.initd"
-    ;;
-esac
-AC_SUBST(initdfile)
-
-AC_ARG_WITH(docdir,
-  [AC_HELP_STRING([--with-docdir=DIR],[Location of documentation [DATADIR/doc/smartmontools]])],
-  [docdir="$withval"],
-  [ if test -z "$docdir"; then
-      # autoconf 2.5x without '--docdir' support
-      docdir='${datadir}/doc/${PACKAGE}'
-    fi
-  ])
-AC_SUBST(docdir)
-
-AC_ARG_WITH(exampledir,
-  [AC_HELP_STRING([--with-exampledir=DIR],[Location of example scripts [DOCDIR/examplescripts]])],
-  [exampledir="$withval"], [exampledir='${docdir}/examplescripts'])
-AC_SUBST(exampledir)
-
-AC_ARG_ENABLE(drivedb,
-  [AC_HELP_STRING([--disable-drivedb],[Disables drive database file])],
-  [], [enable_drivedb=yes])
-
-AC_ARG_WITH(drivedbdir,
-  [AC_HELP_STRING([--with-drivedbdir=DIR],[Location of drive database file (implies --enable-drivedb) [DATADIR/smartmontools]])],
-  [drivedbdir="$withval"; enable_drivedb=yes],
-  [drivedbdir=; test "$enable_drivedb" = "yes" && drivedbdir='${datadir}/${PACKAGE}'])
-AC_SUBST(drivedbdir)
-AM_CONDITIONAL(ENABLE_DRIVEDB, [test "$enable_drivedb" = "yes"])
-
-AC_ARG_ENABLE(savestates, [AC_HELP_STRING([--enable-savestates],[Enables default smartd state files])])
-
-AC_ARG_WITH(savestates,
-  [AC_HELP_STRING([--with-savestates=PREFIX],[Prefix for default smartd state files (implies --enable-savestates) [LOCALSTATEDIR/lib/smartmontools/smartd.]])],
-  [savestates="$withval"; enable_savestates="yes"],
-  [savestates=; test "$enable_savestates" = "yes" && savestates='${localstatedir}/lib/${PACKAGE}/smartd.'])
-savestatesdir="${savestates%/*}"
-AC_SUBST(savestates)
-AC_SUBST(savestatesdir)
-AM_CONDITIONAL(ENABLE_SAVESTATES, [test "$enable_savestates" = "yes"])
-
-AC_ARG_ENABLE(attributelog, [AC_HELP_STRING([--enable-attributelog],[Enables default smartd attribute log files])])
-
-AC_ARG_WITH(attributelog,
-  [AC_HELP_STRING([--with-attributelog=PREFIX],[Prefix for default smartd attribute log files (implies --enable-attributelog) [LOCALSTATEDIR/lib/smartmontools/attrlog.]])],
-  [attributelog="$withval"; enable_attributelog="yes"],
-  [attributelog=; test "$enable_attributelog" = "yes" && attributelog='${localstatedir}/lib/${PACKAGE}/attrlog.'])
-attributelogdir="${attributelog%/*}"
-AC_SUBST(attributelog)
-AC_SUBST(attributelogdir)
-AM_CONDITIONAL(ENABLE_ATTRIBUTELOG, [test "$enable_attributelog" = "yes"])
-
-AC_ARG_ENABLE(sample,
-  [AC_HELP_STRING([--enable-sample],[Enables appending .sample to the installed smartd rc script and configuration file])],
-  [smartd_suffix=; test "$enableval" = "yes" && smartd_suffix=".sample"],
-  [smartd_suffix=;])
-AC_SUBST(smartd_suffix)
-
-AC_ARG_WITH(os-deps,
-  [AC_HELP_STRING([--with-os-deps='os_module.o ...'],[Specify OS dependent module(s) [guessed]])],
-  [ for x in $with_os_deps; do
-      case $x in
-        *.o) ;;
-        *) AC_MSG_ERROR([non-object file specified by --with-os-deps]) ;;
-      esac
-    done
-  ],[])
-
-AC_ARG_WITH(selinux,
-  [AC_HELP_STRING([--with-selinux@<:@=yes|no@:>@],[Enables SELinux support [no]])],
-  [ if test "$withval" = "yes"; then
-      AC_CHECK_HEADERS([selinux/selinux.h], [], [AC_MSG_ERROR([Missing SELinux header files])])
-      AC_CHECK_LIB(selinux, matchpathcon, [], [AC_MSG_ERROR([Missing or incorrect SELinux library files])])
-    fi
-  ],[])
-AC_SUBST(with_selinux)
-if test "$with_selinux" = "yes"; then
-  AC_DEFINE(WITH_SELINUX, 1, [Define to 1 if SELinux support is enabled])
-fi
-
-AC_ARG_WITH(libcap-ng,
-  [AC_HELP_STRING([--with-libcap-ng@<:@=auto|yes|no@:>@],[Add Libcap-ng support to smartd [auto]])],
-  [], [with_libcap_ng=auto])
-
-use_libcap_ng=no
-if test "$with_libcap_ng" != "no"; then
-  AC_CHECK_LIB(cap-ng, capng_clear,
-    [AC_DEFINE(HAVE_LIBCAP_NG, 1, [Define to 1 if you have the `cap-ng' library (-lcap-ng).])
-     CAPNG_LDADD="-lcap-ng"; use_libcap_ng=yes])
-
-  if test "$use_libcap_ng" = "yes"; then
-    AC_CHECK_HEADER(cap-ng.h, [], [AC_MSG_ERROR([libcap-ng libraries found but headers are missing])])
-  elif test "$with_libcap_ng" = "yes"; then
-    AC_MSG_ERROR([libcap-ng support was requested but the library was not found])
-  fi
-fi
-
-AC_MSG_CHECKING([whether to use libcap-ng])
-AC_SUBST(CAPNG_LDADD)
-AM_CONDITIONAL(ENABLE_CAPABILITIES, [test "$use_libcap_ng" = "yes"])
-AC_MSG_RESULT([$use_libcap_ng])
-
-if test "$prefix" = "NONE"; then
-    dnl no prefix and no mandir, so use ${prefix}/share/man as default
-    if test "$mandir" = '${prefix}/man'; then
-       AC_SUBST([mandir], ['${prefix}/share/man'])
-    fi
-fi
-
-AC_SUBST(releaseversion,['${PACKAGE}-${VERSION}'])
-AC_SUBST(smartmontools_release_date)
-AC_SUBST(smartmontools_release_time)
-
-# Set platform-specific modules and symbols
-os_libs=
-os_dltools='curl wget lynx'
-os_mailer=
-os_darwin=no
-os_solaris=no
-os_win32=no
-os_win32_mingw=no
-os_win64=no
-os_man_filter=
-case "${host}" in
-  *-*-linux*)
-    os_deps='os_linux.o cciss.o'
-    os_man_filter=Linux
-    ;;
-  *-*-freebsd*|*-*-dragonfly*|*-*-kfreebsd*-gnu*)
-    os_deps='os_freebsd.o cciss.o'
-    os_libs='-lcam'
-    os_dltools='curl wget lynx fetch'
-    AC_CHECK_LIB(usb, libusb20_dev_get_device_desc)
-    os_man_filter=FreeBSD
-    ;;
-  sparc-*-solaris*)
-    os_deps='os_solaris.o os_solaris_ata.o'
-    os_mailer='mailx'
-    os_solaris=yes
-    os_man_filter=Solaris
-    ;;
-  *-pc-solaris*)
-    os_deps='os_solaris.o'
-    os_mailer='mailx'
-    os_solaris=yes
-    os_man_filter=Solaris
-    ;;
-  *-*-netbsd*)
-    os_deps='os_netbsd.o'
-    os_libs='-lutil'
-    os_man_filter=NetBSD
-    ;;
-  *-*-openbsd*)
-    os_deps='os_openbsd.o'
-    os_libs='-lutil'
-    os_dltools='curl wget lynx ftp'
-    os_man_filter=OpenBSD
-    ;;
-  *-*-cygwin*)
-    os_deps='os_win32.o'
-    os_win32=yes
-    os_man_filter=Cygwin
-    ;;
-  x86_64-*-mingw*)
-    os_deps='os_win32.o'
-    os_win32=yes
-    os_win32_mingw=yes
-    os_win64=yes
-    os_man_filter=Windows
-    ;;
-  *-*-mingw*)
-    os_deps='os_win32.o'
-    os_win32=yes
-    os_win32_mingw=yes
-    os_man_filter=Windows
-    ;;
-  *-*-darwin*)
-    os_deps='os_darwin.o'
-    os_libs='-framework CoreFoundation -framework IOKit'
-    os_darwin=yes
-    os_man_filter=Darwin
-    ;;
-  *-*-nto-qnx*)
-    os_deps='os_qnxnto.o'
-    ;;
-  *)
-    os_deps='os_generic.o'
-    ;;
-esac
-
-# Replace if '--with-os-deps' was specified
-test -z "$with_os_deps" || os_deps="$with_os_deps"
-
-# Check if we need adapter to old interface (dev_legacy.cpp)
-os_src=`echo "${os_deps}"|sed -n 's,^\([[^ .]]*\)\.o.*$,\1.cpp,p'`
-AC_MSG_CHECKING([whether ${os_src} uses new interface])
-if grep "smart_interface" "${srcdir}/${os_src}" >/dev/null 2>&1; then
-  os_new_interface=yes
-else
-  os_new_interface=no
-  os_deps="${os_deps} dev_legacy.o"
-  AC_DEFINE(OLD_INTERFACE, 1, [Define to 1 if os_*.cpp still uses the old interface])
-fi
-AC_MSG_RESULT([$os_new_interface])
-
-AC_SUBST([os_deps])
-AC_SUBST([os_libs])
-AC_SUBST([os_dltools])
-AC_SUBST([os_man_filter])
-if test -n "$os_mailer"; then
-  AC_DEFINE_UNQUOTED(DEFAULT_MAILER, "$os_mailer", [Default mailer if "mail" is unavailable])
-fi
-
-# Create drivedb.h update branch name from version: 5.41[.X] -> RELEASE_5_41_DRIVEDB
-DRIVEDB_BRANCH=`echo $VERSION | sed 's,^\([[0-9]]*\.[[0-9]]*\)\..*$,\1,' \
-                | sed -n 's,^\([[0-9]][[0-9]]*\)\.\([[0-9]][[0-9]]*\)$,RELEASE_\1_\2_DRIVEDB,p'`
-if test -z "$DRIVEDB_BRANCH"; then
-  AC_MSG_ERROR([Unable to create DRIVEDB_BRANCH from VERSION=$VERSION])
-fi
-AC_SUBST([DRIVEDB_BRANCH])
-
-# Enable platform-specific makefile sections
-AM_CONDITIONAL(OS_DARWIN, [test "$os_darwin" = "yes"])
-AM_CONDITIONAL(OS_SOLARIS, [test "$os_solaris" = "yes"])
-AM_CONDITIONAL(OS_WIN32, [test "$os_win32" = "yes"])
-AM_CONDITIONAL(OS_WIN32_MINGW, [test "$os_win32_mingw" = "yes"])
-AM_CONDITIONAL(OS_WIN32_NSIS, [test -n "$MAKENSIS"])
-AM_CONDITIONAL(OS_WIN32_WINDMC, [test -n "$WINDMC" && test "$WINDMC" != "no" && test -n "$WINDRES"])
-AM_CONDITIONAL(OS_WIN64, [test "$os_win64" = "yes"])
-
-dnl Add -Wall and -W if using g++ and its not already specified.
-if test "$GXX" = "yes"; then
-  if test -z "`echo "$CXXFLAGS" | grep "\-Wall" 2> /dev/null`" ; then
-      CXXFLAGS="$CXXFLAGS -Wall"
-  fi
-# In the next line, do NOT delete the 2 spaces inside double quotes.
-  if test -z "`echo "$CXXFLAGS " | grep "\-W " 2> /dev/null`" ; then
-      CXXFLAGS="$CXXFLAGS -W"
-  fi
-
-else
- dnl We are NOT using gcc, so enable host-specific compiler flags
- case "${host}" in
-       sparc*-*-solaris*) 
-          dnl set CXXFLAGS for Solaris/SPARC C++ compiler
-          if test -z "`echo "$CXXFLAGS" | grep "\-xmemalign" 2> /dev/null`" ; then
-            dnl we have to tell the compilers about packed ATA structures
-            CXXFLAGS="-xmemalign=1i $CXXFLAGS"
-          fi
- esac
- case "${host}" in
-       *-*-solaris*) 
-          if test -z "`echo "$CXXFLAGS" | grep "\-xO" 2> /dev/null`" ; then
-            dnl turn on optimization if user has not explicitly set its value
-            CXXFLAGS="-xO2 $CXXFLAGS"
-          fi
-          if test -z "`echo "$CXXFLAGS" | grep "\-erroff" 2> /dev/null`" ; then
-           dnl suppress trivial warnings
-           CXXFLAGS="-erroff=%none,wbadinitl,wbadasgl,badargtypel2w,badargtype2w $CXXFLAGS"
-         fi
- esac
-fi
-
-AC_DEFINE_UNQUOTED(SMARTMONTOOLS_BUILD_HOST,     "${host}",                       [smartmontools Build Host])
-
-AC_SUBST(CXXFLAGS)
-
-AC_CONFIG_FILES(Makefile)
-AC_OUTPUT
-AC_PROG_MAKE_SET
-
-echo "-----------------------------------------------------------------------------" >&AS_MESSAGE_FD
-echo "${PACKAGE}-${VERSION} configuration:" >&AS_MESSAGE_FD
-echo "host operating system:  $host" >&AS_MESSAGE_FD
-echo "C++ compiler:           $CXX" >&AS_MESSAGE_FD
-echo "C compiler:             $CC" >&AS_MESSAGE_FD
-echo "preprocessor flags:     $CPPFLAGS" >&AS_MESSAGE_FD
-echo "C++ compiler flags:     $CXXFLAGS" >&AS_MESSAGE_FD
-echo "C compiler flags:       $CFLAGS" >&AS_MESSAGE_FD
-echo "linker flags:           $LDFLAGS" >&AS_MESSAGE_FD
-echo "OS specific modules:    $os_deps $os_libs $LIBS" >&AS_MESSAGE_FD
-
-case "$host_os" in
-  mingw*)
-    echo "resource compiler:      $WINDRES" >&AS_MESSAGE_FD
-    echo "message compiler:       $WINDMC" >&AS_MESSAGE_FD
-    echo "NSIS compiler:          $MAKENSIS" >&AS_MESSAGE_FD
-    if test -n "$drivedbdir"; then
-      echo "drive database file:    EXEDIR/drivedb.h" >&AS_MESSAGE_FD
-      if test -n "$MAKENSIS"; then
-        echo "database update tool:   EXEDIR/update-smart-drivedb.exe" >&AS_MESSAGE_FD
-      fi
-    else
-      echo "drive database file:    [[disabled]]" >&AS_MESSAGE_FD
-    fi
-    if test -n "$savestates"; then
-      echo "smartd save files:      `eval eval eval echo $savestates`MODEL-SERIAL.TYPE.state" >&AS_MESSAGE_FD
-    fi
-    if test -n "$attributelog"; then
-      echo "smartd attribute logs:  `eval eval eval echo $attributelog`MODEL-SERIAL.TYPE.csv" >&AS_MESSAGE_FD
-    fi
-    ;;
-
-  *)
-    echo "binary install path:    `eval eval eval echo $sbindir`" >&AS_MESSAGE_FD
-    echo "man page install path:  `eval eval eval echo $mandir`" >&AS_MESSAGE_FD
-    echo "doc file install path:  `eval eval eval echo $docdir`" >&AS_MESSAGE_FD
-    echo "examples install path:  `eval eval eval echo $exampledir`" >&AS_MESSAGE_FD
-    if test -n "$drivedbdir"; then
-      echo "drive database file:    `eval eval eval echo $drivedbdir`/drivedb.h" >&AS_MESSAGE_FD
-      echo "database update script: `eval eval eval echo $sbindir`/update-smart-drivedb" >&AS_MESSAGE_FD
-      echo "download tools:         `eval eval eval echo $os_dltools`" >&AS_MESSAGE_FD
-    else
-      echo "drive database file:    [[disabled]]" >&AS_MESSAGE_FD
-    fi
-    echo "local drive database:   `eval eval eval echo $sysconfdir`/smart_drivedb.h" >&AS_MESSAGE_FD
-    echo "smartd config file:     `eval eval eval echo $sysconfdir`/smartd.conf${smartd_suffix}" >&AS_MESSAGE_FD
-    if test -n "$initddir"; then
-      echo "smartd initd script:    `eval eval eval echo $initddir`/smartd${smartd_suffix}" >&AS_MESSAGE_FD
-    elif test -z "$systemdsystemunitdir"; then
-      echo "smartd initd script:    [[disabled]]" >&AS_MESSAGE_FD
-    fi
-    if test -n "$systemdsystemunitdir"; then
-      echo "smartd systemd file:    `eval eval eval echo $systemdsystemunitdir`/smartd.service" >&AS_MESSAGE_FD
-    fi
-    if test -n "$savestates"; then
-      echo "smartd save files:      `eval eval eval echo $savestates`MODEL-SERIAL.TYPE.state" >&AS_MESSAGE_FD
-    else
-      echo "smartd save files:      [[disabled]]" >&AS_MESSAGE_FD
-    fi
-    if test -n "$attributelog"; then
-      echo "smartd attribute logs:  `eval eval eval echo $attributelog`MODEL-SERIAL.TYPE.csv" >&AS_MESSAGE_FD
-    else
-      echo "smartd attribute logs:  [[disabled]]" >&AS_MESSAGE_FD
-    fi
-    echo "libcap-ng support:      $use_libcap_ng" >&AS_MESSAGE_FD
-    case "$host_os" in
-      linux*) echo "SELinux support:        ${with_selinux-no}" >&AS_MESSAGE_FD ;;
-    esac
-    ;;
-esac
-echo "-----------------------------------------------------------------------------" >&AS_MESSAGE_FD
index 087fa780c0a3fda5ae1f5519a8b0c0d87991a0a0..3e5aa213763e8981c209841d22f2fa768ca7bfd0 100644 (file)
--- a/csmisas.h
+++ b/csmisas.h
@@ -236,7 +236,11 @@ typedef struct _IOCTL_HEADER {
 
 #define __u8    unsigned char
 #define __u16   unsigned short
+#ifndef __LP64__  // ILP32 (32-bit), LLP64 (64-bit MSVC, MinGW)
 #define __u32   unsigned long
+#else             // LP64 (64-bit Cygwin)
+#define __u32   unsigned int
+#endif
 #define __u64   unsigned __int64
 
 #define __i8    char
diff --git a/dev_areca.cpp b/dev_areca.cpp
new file mode 100644 (file)
index 0000000..9ee8be7
--- /dev/null
@@ -0,0 +1,704 @@
+/*
+ * dev_areca.cpp
+ *
+ * Home page of code is: http://smartmontools.sourceforge.net
+ *
+ * Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
+ *
+ * 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/>.
+ *
+ */
+
+#include "config.h"
+#include "int64.h"
+
+#include "dev_interface.h"
+#include "dev_areca.h"
+
+const char * dev_areca_cpp_cvsid = "$Id: dev_areca.cpp 3803 2013-03-24 18:52:54Z chrfranke $"
+  DEV_ARECA_H_CVSID;
+
+#include "atacmds.h"
+#include "scsicmds.h"
+
+#include <errno.h>
+
+#if 0 // For debugging areca code
+static void dumpdata(unsigned char *block, int len)
+{
+  int ln = (len / 16) + 1;   // total line#
+  unsigned char c;
+  int pos = 0;
+
+  printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
+  printf("      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F      ASCII      \n");
+  printf("=====================================================================\n");
+
+  for ( int l = 0; l < ln && len; l++ )
+  {
+    // printf the line# and the HEX data
+    // if a line data length < 16 then append the space to the tail of line to reach 16 chars
+    printf("%02X | ", l);
+    for ( pos = 0; pos < 16 && len; pos++, len-- )
+    {
+      c = block[l*16+pos];
+      printf("%02X ", c);
+    }
+
+    if ( pos < 16 )
+    {
+      for ( int loop = pos; loop < 16; loop++ )
+      {
+        printf("   ");
+      }
+    }
+
+    // print ASCII char
+    for ( int loop = 0; loop < pos; loop++ )
+    {
+      c = block[l*16+loop];
+      if ( c >= 0x20 && c <= 0x7F )
+      {
+        printf("%c", c);
+      }
+      else
+      {
+        printf(".");
+      }
+    }
+    printf("\n");
+  }
+  printf("=====================================================================\n");
+}
+#endif
+
+generic_areca_device::generic_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca"),
+  m_disknum(disknum),
+  m_encnum(encnum)
+{
+  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
+}
+
+generic_areca_device::~generic_areca_device() throw()
+{
+
+}
+
+// PURPOSE
+//   This is an interface routine meant to isolate the OS dependent
+//   parts of the code, and to provide a debugging interface.  Each
+//   different port and OS needs to provide it's own interface.  This
+//   is the Windows interface to the Areca "arcmsr" driver.  It allows ATA
+//   commands to be passed through the SCSI driver.
+// DETAILED DESCRIPTION OF ARGUMENTS
+//   fd: is the file descriptor provided by open()
+//   disknum is the disk number (0 to 127) in the RAID array
+//   command: defines the different operations.
+//   select: additional input data if needed (which log, which type of
+//           self-test).
+//   data:   location to write output data, if needed (512 bytes).
+//   Note: not all commands use all arguments.
+// RETURN VALUES
+//  -1 if the command failed
+//   0 if the command succeeded,
+//   STATUS_CHECK routine:
+//  -1 if the command failed
+//   0 if the command succeeded and disk SMART status is "OK"
+//   1 if the command succeeded and disk SMART status is "FAILING"
+int generic_areca_device::arcmsr_command_handler(unsigned long arcmsr_cmd, unsigned char *data, int data_len)
+{
+  unsigned int cmds[] =
+  {
+    ARCMSR_IOCTL_READ_RQBUFFER,
+    ARCMSR_IOCTL_WRITE_WQBUFFER,
+    ARCMSR_IOCTL_CLEAR_RQBUFFER,
+    ARCMSR_IOCTL_CLEAR_WQBUFFER,
+    ARCMSR_IOCTL_RETURN_CODE_3F
+  };
+
+  int ioctlreturn = 0;
+  sSRB_BUFFER sBuf;
+  struct scsi_cmnd_io iop;
+  int dir = DXFER_TO_DEVICE;
+
+  UINT8 cdb[10]={0};
+  UINT8 sense[32]={0};
+
+  unsigned char *areca_return_packet;
+  int total = 0;
+  int expected = -1;
+  unsigned char return_buff[2048]={0};
+  unsigned char *ptr = &return_buff[0];
+
+  memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
+  memset(&iop, 0, sizeof(iop));
+
+  sBuf.srbioctl.HeaderLength = sizeof(sARCMSR_IO_HDR);
+  memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
+  sBuf.srbioctl.Timeout = 10000;
+  sBuf.srbioctl.ControlCode = cmds[arcmsr_cmd];
+
+  if(arcmsr_cmd >= ARCMSR_CMD_TOTAL)
+  {
+      return -1;
+  }
+
+  switch ( arcmsr_cmd )
+  {
+  // command for writing data to driver
+  case ARCMSR_WRITE_WQBUFFER:
+    if ( data && data_len )
+    {
+      sBuf.srbioctl.Length = data_len;
+      memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
+    }
+    // commands for clearing related buffer of driver
+  case ARCMSR_CLEAR_RQBUFFER:
+  case ARCMSR_CLEAR_WQBUFFER:
+    cdb[0] = 0x3B; //SCSI_WRITE_BUF command;
+    break;
+  // command for reading data from driver
+  case ARCMSR_READ_RQBUFFER:
+  // command for identifying driver
+  case ARCMSR_RETURN_CODE_3F:
+    cdb[0] = 0x3C; //SCSI_READ_BUF command;
+    dir = DXFER_FROM_DEVICE;
+    break;
+  default:
+    // unknown arcmsr commands
+    return -1;
+  }
+
+  cdb[1] = 0x01;
+  cdb[2] = 0xf0;
+  cdb[5] = cmds[arcmsr_cmd] >> 24;
+  cdb[6] = cmds[arcmsr_cmd] >> 16;
+  cdb[7] = cmds[arcmsr_cmd] >> 8;
+  cdb[8] = cmds[arcmsr_cmd] & 0x0F;
+
+  iop.dxfer_dir = dir;
+  iop.dxfer_len = sizeof(sBuf);
+  iop.dxferp = (unsigned char *)&sBuf;
+  iop.cmnd = cdb;
+  iop.cmnd_len = sizeof(cdb);
+  iop.sensep = sense;
+  iop.max_sense_len = sizeof(sense);
+  iop.timeout = SCSI_TIMEOUT_DEFAULT;
+
+  while ( 1 )
+  {
+    ioctlreturn = arcmsr_do_scsi_io(&iop);
+    if(ioctlreturn || iop.scsi_status)
+    {
+      break;
+    }
+
+    if ( arcmsr_cmd != ARCMSR_READ_RQBUFFER )
+    {
+      // if succeeded, just returns the length of outgoing data
+      return data_len;
+    }
+
+    if ( sBuf.srbioctl.Length )
+    {
+      memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
+      ptr += sBuf.srbioctl.Length;
+      total += sBuf.srbioctl.Length;
+      // the returned bytes enough to compute payload length ?
+      if ( expected < 0 && total >= 5 )
+      {
+        areca_return_packet = (unsigned char *)&return_buff[0];
+        if ( areca_return_packet[0] == 0x5E &&
+           areca_return_packet[1] == 0x01 &&
+           areca_return_packet[2] == 0x61 )
+        {
+          // valid header, let's compute the returned payload length,
+          // we expected the total length is
+          // payload + 3 bytes header + 2 bytes length + 1 byte checksum
+          expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
+        }
+      }
+
+      if ( total >= 7 && total >= expected )
+      {
+        //printf("total bytes received = %d, expected length = %d\n", total, expected);
+
+        // ------ Okay! we received enough --------
+        break;
+      }
+    }
+  }
+
+  // Deal with the different error cases
+  if ( arcmsr_cmd == ARCMSR_RETURN_CODE_3F )
+  {
+    // Silence the ARCMSR_IOCTL_RETURN_CODE_3F's error, no pout(...)
+    return -4;
+  }
+
+  if ( ioctlreturn )
+  {
+    pout("do_scsi_cmnd_io with write buffer failed code = %x\n", ioctlreturn);
+    return -2;
+  }
+
+  if ( iop.scsi_status )
+  {
+    pout("io_hdr.scsi_status with write buffer failed code = %x\n", iop.scsi_status);
+    return -3;
+  }
+
+  if ( data )
+  {
+    memcpy(data, return_buff, total);
+  }
+
+  return total;
+}
+
+bool generic_areca_device::arcmsr_probe()
+{
+  if(!is_open())
+  {
+    open();
+  }
+
+  if(arcmsr_command_handler(ARCMSR_RETURN_CODE_3F, NULL, 0) != 0)
+  {
+    return false;
+  }
+  return true;
+}
+
+int generic_areca_device::arcmsr_ui_handler(unsigned char *areca_packet, int areca_packet_len, unsigned char *result)
+{
+  int expected = 0;
+  unsigned char return_buff[2048];
+  unsigned char cs = 0;
+  int cs_pos = 0;
+
+  // ----- ADD CHECKSUM -----
+  cs_pos = areca_packet_len - 1;
+  for(int i = 3; i < cs_pos; i++)
+  {
+      areca_packet[cs_pos] += areca_packet[i];
+  }
+
+  if(!arcmsr_lock())
+  {
+    return -1;
+  }
+  expected = arcmsr_command_handler(ARCMSR_CLEAR_RQBUFFER, NULL, 0);
+  if (expected==-3) {
+    return set_err(EIO);
+  }
+  expected = arcmsr_command_handler(ARCMSR_CLEAR_WQBUFFER, NULL, 0);
+  expected = arcmsr_command_handler(ARCMSR_WRITE_WQBUFFER, areca_packet, areca_packet_len);
+  if ( expected > 0 )
+  {
+    expected = arcmsr_command_handler(ARCMSR_READ_RQBUFFER, return_buff, sizeof(return_buff));
+  }
+
+  if ( expected < 0 )
+  {
+    return -1;
+  }
+
+  if(!arcmsr_unlock())
+  {
+    return -1;
+  }
+
+  // ----- VERIFY THE CHECKSUM -----
+  cs = 0;
+  for ( int loop = 3; loop < expected - 1; loop++ )
+  {
+      cs += return_buff[loop];
+  }
+
+  if ( return_buff[expected - 1] != cs )
+  {
+    return -1;
+  }
+
+  memcpy(result, return_buff, expected);
+
+  return expected;
+}
+
+int generic_areca_device::arcmsr_get_controller_type()
+{
+  int expected = 0;
+  unsigned char return_buff[2048];
+  unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x01, 0x00, 0x23, 0x00};
+
+  memset(return_buff, 0, sizeof(return_buff));
+  expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
+  if ( expected < 0 )
+  {
+    return -1;
+  }
+
+  return return_buff[0xc2];
+}
+
+int generic_areca_device::arcmsr_get_dev_type()
+{
+  int expected = 0;
+  unsigned char return_buff[2048];
+  int ctlr_type = -1;
+  int encnum = get_encnum();
+  int disknum = get_disknum();
+  unsigned char areca_packet[] = {0x5E, 0x01, 0x61, 0x03, 0x00, 0x22,
+    (unsigned char)(disknum - 1), (unsigned char)(encnum - 1), 0x00};
+
+  memset(return_buff, 0, sizeof(return_buff));
+  expected = arcmsr_ui_handler(areca_packet, sizeof(areca_packet), return_buff);
+  if ( expected < 0 )
+  {
+    return -1;
+  }
+
+  ctlr_type = arcmsr_get_controller_type();
+
+  if( ctlr_type < 0 )
+  {
+    return ctlr_type;
+  }
+
+  if( ctlr_type == 0x02/* SATA Controllers */ ||
+     (ctlr_type == 0x03 /* SAS Controllers */ && return_buff[0x52] & 0x01 /* SATA devices behind SAS Controller */) )
+  {
+    // SATA device
+    return 1;
+  }
+
+  // SAS device
+  return 0;
+}
+
+bool generic_areca_device::arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
+{
+  // ATA input registers
+  typedef struct _ATA_INPUT_REGISTERS
+  {
+    unsigned char features;
+    unsigned char sector_count;
+    unsigned char sector_number;
+    unsigned char cylinder_low;
+    unsigned char cylinder_high;
+    unsigned char device_head;
+    unsigned char command;
+    unsigned char reserved[8];
+    unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
+  } sATA_INPUT_REGISTERS;
+
+  // ATA output registers
+  // Note: The output registers is re-sorted for areca internal use only
+  typedef struct _ATA_OUTPUT_REGISTERS
+  {
+    unsigned char error;
+    unsigned char status;
+    unsigned char sector_count;
+    unsigned char sector_number;
+    unsigned char cylinder_low;
+    unsigned char cylinder_high;
+  } sATA_OUTPUT_REGISTERS;
+
+  // Areca packet format for outgoing:
+  // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
+  // B[3~4] : 2 bytes command length + variant data length, little endian
+  // B[5]   : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
+  // B[6~last-1] : variant bytes payload data
+  // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
+  //
+  //
+  //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte
+  // +--------------------------------------------------------------------------------+
+  // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
+  // +--------------------------------------------------------------------------------+
+  //
+
+  //Areca packet format for incoming:
+  // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
+  // B[3~4] : 2 bytes payload length, little endian
+  // B[5~last-1] : variant bytes returned payload data
+  // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
+  //
+  //
+  //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte
+  // +-------------------------------------------------------------------+
+  // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
+  // +-------------------------------------------------------------------+
+  unsigned char    areca_packet[640];
+  int areca_packet_len = sizeof(areca_packet);
+  unsigned char return_buff[2048];
+  int expected = 0;
+
+  sATA_INPUT_REGISTERS *ata_cmd;
+
+  // For debugging
+#if 0
+  memset(sInq, 0, sizeof(sInq));
+  scsiStdInquiry(fd, (unsigned char *)sInq, (int)sizeof(sInq));
+  dumpdata((unsigned char *)sInq, sizeof(sInq));
+#endif
+  memset(areca_packet, 0, areca_packet_len);
+
+  // ----- BEGIN TO SETUP HEADERS -------
+  areca_packet[0] = 0x5E;
+  areca_packet[1] = 0x01;
+  areca_packet[2] = 0x61;
+  areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
+  areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
+  areca_packet[5] = 0x1c;  // areca defined code for ATA passthrough command
+
+  // ----- BEGIN TO SETUP PAYLOAD DATA -----
+  memcpy(&areca_packet[7], "SmrT", 4);  // areca defined password
+  ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
+
+  // Set registers
+  {
+    const ata_in_regs & r = in.in_regs;
+    ata_cmd->features      = r.features;
+    ata_cmd->sector_count  = r.sector_count;
+    ata_cmd->sector_number = r.lba_low;
+    ata_cmd->cylinder_low  = r.lba_mid;
+    ata_cmd->cylinder_high = r.lba_high;
+    ata_cmd->device_head   = r.device;
+    ata_cmd->command       = r.command;
+  }
+  bool readdata = false;
+  if (in.direction == ata_cmd_in::data_in) {
+      readdata = true;
+      // the command will read data
+      areca_packet[6] = 0x13;
+  }
+  else if ( in.direction == ata_cmd_in::no_data )
+  {
+    // the commands will return no data
+    areca_packet[6] = 0x15;
+  }
+  else if (in.direction == ata_cmd_in::data_out)
+  {
+    // the commands will write data
+    memcpy(ata_cmd->data, in.buffer, in.size);
+    areca_packet[6] = 0x14;
+  }
+  else {
+      // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
+      return set_err(ENOSYS);
+  }
+
+  areca_packet[11] = get_disknum() - 1;  // disk#
+  areca_packet[19] = get_encnum() - 1;   // enc#
+
+  // ----- BEGIN TO SEND TO ARECA DRIVER ------
+  expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
+  if ( expected < 0 )
+  {
+    return set_err(EIO);
+  }
+
+  sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
+  if ( ata_out->status )
+  {
+    if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
+     && !nonempty((unsigned char *)in.buffer, in.size))
+     {
+        return set_err(ENODEV, "No drive on port %d", get_disknum());
+     }
+  }
+
+  // returns with data
+  if (readdata)
+  {
+    memcpy(in.buffer, &return_buff[7], in.size);
+  }
+
+  // Return register values
+  {
+    ata_out_regs & r = out.out_regs;
+    r.error          = ata_out->error;
+    r.sector_count   = ata_out->sector_count;
+    r.lba_low        = ata_out->sector_number;
+    r.lba_mid        = ata_out->cylinder_low;
+    r.lba_high       = ata_out->cylinder_high;
+    r.status         = ata_out->status;
+  }
+  return true;
+}
+
+bool generic_areca_device::arcmsr_scsi_pass_through(struct scsi_cmnd_io * iop)
+{
+  // Areca packet format for outgoing:
+  // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
+  // B[3~4] : 2 bytes command length + variant data length, little endian
+  // B[5]   : 1 bytes areca defined command code
+  // B[6~last-1] : variant bytes payload data
+  // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
+  //
+  //
+  //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte
+  // +--------------------------------------------------------------------------------+
+  // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
+  // +--------------------------------------------------------------------------------+
+  //
+
+  //Areca packet format for incoming:
+  // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
+  // B[3~4] : 2 bytes payload length, little endian
+  // B[5~last-1] : variant bytes returned payload data
+  // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
+  //
+  //
+  //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte
+  // +-------------------------------------------------------------------+
+  // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
+  // +-------------------------------------------------------------------+
+  unsigned char    areca_packet[640];
+  int areca_packet_len = sizeof(areca_packet);
+  unsigned char return_buff[2048];
+  int expected = 0;
+
+  if (iop->cmnd_len > 16) {
+    set_err(EINVAL, "cmnd_len too large");
+    return false;
+  }
+
+  memset(areca_packet, 0, areca_packet_len);
+
+  // ----- BEGIN TO SETUP HEADERS -------
+  areca_packet[0] = 0x5E;
+  areca_packet[1] = 0x01;
+  areca_packet[2] = 0x61;
+  areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
+  areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
+  areca_packet[5] = 0x1c;
+
+  // ----- BEGIN TO SETUP PAYLOAD DATA -----
+  areca_packet[6] = 0x16; // scsi pass through
+  memcpy(&areca_packet[7], "SmrT", 4);  // areca defined password
+  areca_packet[12] = iop->cmnd_len; // cdb length
+  memcpy( &areca_packet[35], iop->cmnd, iop->cmnd_len); // cdb
+  areca_packet[15] = (unsigned char)iop->dxfer_len; // 15(LSB) ~ 18(MSB): data length ( max=512 bytes)
+  areca_packet[16] = (unsigned char)(iop->dxfer_len >> 8);
+  areca_packet[17] = (unsigned char)(iop->dxfer_len >> 16);
+  areca_packet[18] = (unsigned char)(iop->dxfer_len >> 24);
+  if(iop->dxfer_dir == DXFER_TO_DEVICE)
+  {
+    areca_packet[13] |= 0x01;
+    memcpy(&areca_packet[67], iop->dxferp, iop->dxfer_len);
+  }
+  else if (iop->dxfer_dir == DXFER_FROM_DEVICE)
+  {
+  }
+  else if( iop->dxfer_dir == DXFER_NONE)
+  {
+  }
+  else {
+    // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
+    return set_err(ENOSYS);
+  }
+
+  areca_packet[11] = get_disknum() - 1;  // disk#
+  areca_packet[19] = get_encnum() - 1;   // enc#
+
+  // ----- BEGIN TO SEND TO ARECA DRIVER ------
+  expected = arcmsr_ui_handler(areca_packet, areca_packet_len, return_buff);
+  if ( expected < 0 )
+  {
+    return set_err(EIO);
+  }
+
+  int scsi_status = return_buff[5];
+  int in_data_len = return_buff[11] | return_buff[12] << 8 | return_buff[13] << 16 | return_buff[14] << 24;
+
+  if (iop->dxfer_dir == DXFER_FROM_DEVICE)
+  {
+    memset(iop->dxferp, 0, iop->dxfer_len); // need?
+    memcpy(iop->dxferp, &return_buff[15], in_data_len);
+  }
+
+  if(scsi_status == 0xE1 /* Underrun, actual data length < requested data length */)
+  {
+      // don't care, just ignore
+      scsi_status = 0x0;
+  }
+
+  if(scsi_status != 0x00 && scsi_status != SCSI_STATUS_CHECK_CONDITION)
+  {
+    return set_err(EIO);
+  }
+
+  if(scsi_status == SCSI_STATUS_CHECK_CONDITION)
+  {
+    // check condition
+    iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
+    iop->resp_sense_len = 4;
+    iop->sensep[0] = return_buff[7];
+    iop->sensep[1] = return_buff[8];
+    iop->sensep[2] = return_buff[9];
+    iop->sensep[3] = return_buff[10];
+  }
+
+  return true;
+}
+
+/////////////////////////////////////////////////////////////
+areca_ata_device::areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca")
+{
+  set_encnum(encnum);
+  set_disknum(disknum);
+  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
+}
+
+areca_ata_device::~areca_ata_device() throw()
+{
+
+}
+
+bool areca_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
+{
+  if (!ata_cmd_is_supported(in,
+    ata_device::supports_data_out |
+    ata_device::supports_output_regs |
+  //ata_device::supports_multi_sector | // TODO
+    ata_device::supports_48bit_hi_null,
+    "Areca")
+  )
+    return false;
+
+  return arcmsr_ata_pass_through(in, out);
+}
+
+/////////////////////////////////////////////////////////////
+areca_scsi_device::areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca")
+{
+  set_encnum(encnum);
+  set_disknum(disknum);
+  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
+}
+
+areca_scsi_device::~areca_scsi_device() throw()
+{
+
+}
+
+bool areca_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
+{
+  return arcmsr_scsi_pass_through(iop);
+}
+
+
+
+
diff --git a/dev_areca.h b/dev_areca.h
new file mode 100644 (file)
index 0000000..ace29cb
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * dev_areca.h
+ *
+ * Home page of code is: http://smartmontools.sourceforge.net
+ *
+ * Copyright (C) 2012 Hank Wu <hank@areca.com.tw>
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef DEV_ARECA_H
+#define DEV_ARECA_H
+
+#define DEV_ARECA_H_CVSID "$Id: dev_areca.h 3763 2013-01-31 22:25:25Z chrfranke $"
+
+/////////////////////////////////////////////////////////////////////////////
+/// Areca RAID support
+
+/* GENERIC ARECA IO CONTROL CODE*/
+enum _GENERIC_ARCMSR_CMDS
+{
+ARCMSR_READ_RQBUFFER = 0,
+ARCMSR_WRITE_WQBUFFER,
+ARCMSR_CLEAR_RQBUFFER,
+ARCMSR_CLEAR_WQBUFFER,
+ARCMSR_RETURN_CODE_3F,
+ARCMSR_CMD_TOTAL
+};
+
+#define ARECA_SIG_STR  "ARCMSR"
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define ARCMSR_IOCTL_READ_RQBUFFER           0x90002004
+#define ARCMSR_IOCTL_WRITE_WQBUFFER          0x90002008
+#define ARCMSR_IOCTL_CLEAR_RQBUFFER          0x9000200C
+#define ARCMSR_IOCTL_CLEAR_WQBUFFER          0x90002010
+#define ARCMSR_IOCTL_RETURN_CODE_3F          0x90002018
+#elif defined(__linux__)
+/*DeviceType*/
+#define ARECA_SATA_RAID                      0x90000000
+/*FunctionCode*/
+#define FUNCTION_READ_RQBUFFER               0x0801
+#define FUNCTION_WRITE_WQBUFFER              0x0802
+#define FUNCTION_CLEAR_RQBUFFER              0x0803
+#define FUNCTION_CLEAR_WQBUFFER              0x0804
+#define FUNCTION_RETURN_CODE_3F              0x0806
+
+/* ARECA IO CONTROL CODE*/
+#define ARCMSR_IOCTL_READ_RQBUFFER           (ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER)
+#define ARCMSR_IOCTL_WRITE_WQBUFFER          (ARECA_SATA_RAID | FUNCTION_WRITE_WQBUFFER)
+#define ARCMSR_IOCTL_CLEAR_RQBUFFER          (ARECA_SATA_RAID | FUNCTION_CLEAR_RQBUFFER)
+#define ARCMSR_IOCTL_CLEAR_WQBUFFER          (ARECA_SATA_RAID | FUNCTION_CLEAR_WQBUFFER)
+#define ARCMSR_IOCTL_RETURN_CODE_3F          (ARECA_SATA_RAID | FUNCTION_RETURN_CODE_3F)
+#elif defined(__FreeBSD__)
+#include <sys/ioctl.h> // _IOWR
+
+/*FunctionCode*/
+#define FUNCTION_READ_RQBUFFER               0x0801
+#define FUNCTION_WRITE_WQBUFFER              0x0802
+#define FUNCTION_CLEAR_RQBUFFER              0x0803
+#define FUNCTION_CLEAR_WQBUFFER              0x0804
+#define FUNCTION_RETURN_CODE_3F              0x0806
+
+/* ARECA IO CONTROL CODE*/
+#define ARCMSR_IOCTL_READ_RQBUFFER           _IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
+#define ARCMSR_IOCTL_WRITE_WQBUFFER          _IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
+#define ARCMSR_IOCTL_CLEAR_RQBUFFER          _IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
+#define ARCMSR_IOCTL_CLEAR_WQBUFFER          _IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
+#define ARCMSR_IOCTL_RETURN_CODE_3F          _IOWR('F', FUNCTION_RETURN_CODE_3F, sSRB_BUFFER)
+#endif
+
+
+// The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
+typedef struct _ARCMSR_IO_HDR
+{
+  unsigned int HeaderLength;
+  unsigned char Signature[8];
+  unsigned int Timeout;
+  unsigned int ControlCode;
+  unsigned int ReturnCode;
+  unsigned int Length;
+} sARCMSR_IO_HDR;
+
+typedef struct _SRB_BUFFER
+{
+  sARCMSR_IO_HDR  srbioctl;
+  unsigned char   ioctldatabuffer[1032]; // the buffer to put the command data to/from firmware
+} sSRB_BUFFER;
+
+class generic_areca_device :
+virtual public smart_device
+{
+public:
+  generic_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  ~generic_areca_device() throw();
+
+  /////////////////////////////////////////////////////////////////////
+  // OS-dependent functions
+  virtual bool arcmsr_lock() = 0;
+  virtual bool arcmsr_unlock() = 0;
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop) = 0;
+
+  /////////////////////////////////////////////////////////////////////
+  // OS-independent functions
+  virtual int arcmsr_command_handler(unsigned long arcmsr_cmd, unsigned char *data, int data_len);
+  virtual int arcmsr_ui_handler(unsigned char *areca_packet, int areca_packet_len, unsigned char *result);
+  virtual bool arcmsr_probe();
+  virtual int arcmsr_get_dev_type();
+  virtual int arcmsr_get_controller_type();
+  virtual bool arcmsr_scsi_pass_through(scsi_cmnd_io * iop);
+  virtual bool arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
+
+protected:
+  generic_areca_device() : smart_device(never_called)
+  {
+  }
+
+  void set_disknum(int disknum)
+  {m_disknum = disknum;}
+
+  void set_encnum(int encnum)
+  {m_encnum = encnum;}
+
+  int get_disknum()
+  {return m_disknum;}
+
+  int get_encnum()
+  {return m_encnum;}
+
+private:
+  int m_disknum; ///< Disk number.
+  int m_encnum;  ///< Enclosure number.
+ };
+
+// SATA(ATA) device behind Areca RAID Controller
+class areca_ata_device
+: public ata_device,
+  public generic_areca_device
+{
+public:
+  areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  ~areca_ata_device() throw();
+  bool arcmsr_lock() { return true; }
+  bool arcmsr_unlock() { return true; }
+  int arcmsr_do_scsi_io(struct scsi_cmnd_io * /* iop */)
+  {
+      return -1;
+  }
+protected:
+  areca_ata_device(): smart_device(never_called)
+  {
+  }
+  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
+};
+
+// SAS(SCSI) device behind Areca RAID Controller
+class areca_scsi_device
+: public scsi_device,
+  public generic_areca_device
+{
+public:
+  areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  ~areca_scsi_device() throw();
+  bool arcmsr_lock() { return true; }
+  bool arcmsr_unlock() { return true; }
+  int arcmsr_do_scsi_io(struct scsi_cmnd_io * /* iop */)
+  {
+      return -1;
+  }
+protected:
+  areca_scsi_device(): smart_device(never_called)
+  {
+  }
+  virtual bool scsi_pass_through(scsi_cmnd_io * iop);
+};
+
+#endif
index 7651244aeb069e88d6bbf16775e3c50e53e7f02d..71bf8bcd35cf2fe30e0a2a0947649c5785da0afa 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-13 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
@@ -19,6 +19,7 @@
 #include "int64.h"
 #include "dev_interface.h"
 #include "dev_tunnelled.h"
+#include "atacmds.h" // ATA_SMART_CMD/STATUS
 #include "utility.h"
 
 #include <errno.h>
@@ -31,7 +32,7 @@
 #include <sys/timeb.h>
 #endif
 
-const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 3554 2012-06-01 20:11:46Z chrfranke $"
+const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 3741 2013-01-02 17:06:54Z chrfranke $"
   DEV_INTERFACE_H_CVSID;
 
 /////////////////////////////////////////////////////////////////////////////
@@ -138,10 +139,8 @@ bool ata_device::ata_pass_through(const ata_cmd_in & in)
   return ata_pass_through(in, dummy);
 }
 
-bool ata_device::ata_cmd_is_ok(const ata_cmd_in & in,
-  bool data_out_support /*= false*/,
-  bool multi_sector_support /*= false*/,
-  bool ata_48bit_support /*= false*/)
+bool ata_device::ata_cmd_is_supported(const ata_cmd_in & in,
+  unsigned flags, const char * type /* = 0 */)
 {
   // Check DATA IN/OUT
   switch (in.direction) {
@@ -167,12 +166,25 @@ bool ata_device::ata_cmd_is_ok(const ata_cmd_in & in,
   }
 
   // Check features
-  if (in.direction == ata_cmd_in::data_out && !data_out_support)
-    return set_err(ENOSYS, "DATA OUT ATA commands not supported");
-  if (!(in.size == 0 || in.size == 512) && !multi_sector_support)
-    return set_err(ENOSYS, "Multi-sector ATA commands not supported");
-  if (in.in_regs.is_48bit_cmd() && !ata_48bit_support)
-    return set_err(ENOSYS, "48-bit ATA commands not supported");
+  const char * errmsg = 0;
+  if (in.direction == ata_cmd_in::data_out && !(flags & supports_data_out))
+    errmsg = "DATA OUT ATA commands not implemented";
+  else if (   in.out_needed.is_set() && !(flags & supports_output_regs)
+           && !(   in.in_regs.command == ATA_SMART_CMD
+                && in.in_regs.features == ATA_SMART_STATUS
+                && (flags & supports_smart_status)))
+    errmsg = "Read of ATA output registers not implemented";
+  else if (!(in.size == 0 || in.size == 512) && !(flags & supports_multi_sector))
+    errmsg = "Multi-sector ATA commands not implemented";
+  else if (in.in_regs.is_48bit_cmd() && !(flags & (supports_48bit_hi_null|supports_48bit)))
+    errmsg = "48-bit ATA commands not implemented";
+  else if (in.in_regs.is_real_48bit_cmd() && !(flags & supports_48bit))
+    errmsg = "48-bit ATA commands not fully implemented";
+
+  if (errmsg)
+    return set_err(ENOSYS, "%s%s%s%s", errmsg,
+                   (type ? " [" : ""), (type ? type : ""), (type ? "]" : ""));
+
   return true;
 }
 
@@ -246,7 +258,7 @@ std::string smart_interface::get_valid_dev_types_str()
 {
   // default
   std::string s =
-    "ata, scsi, sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,x][,N], usbsunplus";
+    "ata, scsi, sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,p][,x][,N], usbsunplus";
   // append custom
   std::string s2 = get_valid_custom_dev_types_str();
   if (!s2.empty()) {
index 136831cc41edfb0466ecb97ae5e95b3ced6004fd..fe3bb2a38d4f7a81208337e635cd0b5bd373c68b 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef DEV_INTERFACE_H
 #define DEV_INTERFACE_H
 
-#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3554 2012-06-01 20:11:46Z chrfranke $\n"
+#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3663 2012-10-24 20:35:55Z chrfranke $\n"
 
 #include "utility.h"
 
@@ -506,12 +506,35 @@ public:
   virtual bool ata_identify_is_cached() const;
 
 protected:
+  /// Flags for ata_cmd_is_supported().
+  enum {
+    supports_data_out = 0x01, // PIO DATA OUT
+    supports_smart_status = 0x02, // read output registers for SMART STATUS only
+    supports_output_regs = 0x04, // read output registers for all commands
+    supports_multi_sector = 0x08, // more than one sector (1 DRQ/sector variant)
+    supports_48bit_hi_null = 0x10, // 48-bit commands with null high bytes only
+    supports_48bit = 0x20, // all 48-bit commands
+  };
+
   /// Check command input parameters.
+  /// Return false if required features are not implemented.
   /// Calls set_err(...) accordingly.
+  bool ata_cmd_is_supported(const ata_cmd_in & in, unsigned flags,
+    const char * type = 0);
+
+  /// Check command input parameters (old version).
+  // TODO: Remove if no longer used.
   bool ata_cmd_is_ok(const ata_cmd_in & in,
     bool data_out_support = false,
     bool multi_sector_support = false,
-    bool ata_48bit_support = false);
+    bool ata_48bit_support = false)
+    {
+      return ata_cmd_is_supported(in,
+        (data_out_support ? supports_data_out : 0) |
+        supports_output_regs |
+        (multi_sector_support ? supports_multi_sector : 0) |
+        (ata_48bit_support ? supports_48bit : 0));
+    }
 
   /// Hide/unhide ATA interface.
   void hide_ata(bool hide = true)
index 66c6fc76f2f87d67957cf3da64b829728f5ef7cf..f88d4a43a497c1cb096629e239e59454926b036f 100755 (executable)
@@ -3,27 +3,27 @@
 # do a smartmontools release
 # (C) 2003-11 Bruce Allen <ballen4705@users.sourceforge.net>,
 #             Guido Guenther <agx@sigxcpu.org>
-#             Christian Franke <smartmontools-support@lists.sourceforge.net>
-# $Id: do_release 3282 2011-03-04 19:26:59Z chrfranke $
+# (C) 2006-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
+# $Id: do_release 3765 2013-02-05 17:17:13Z chrfranke $
 
 # Notes on generating releases:
 # (1) update NEWS
-# (2) update CHANGELOG -- put in release number
-# (3) update release number in configure.in 
+# (2) update ChangeLog -- put in release number
+# (3) update release number in configure.ac
 # (4) to test, run without '--commit'
 # (5) when satisfied, add option '--commit'
 
 set -e
 
-# Smartmontools Signing Key (through 2012)
-KEYID=0x2753E77A
+# Smartmontools Signing Key (through 2014)
+KEYID=0x8F6ED8AA
 
 inc_release()
 {
   MINOR=`echo $VERSION | cut -d. -f2`
   MAJOR=`echo $VERSION | cut -d. -f1`
   PERL_OLD=$MAJOR\\.$MINOR
-  ((MINOR++))
+  ((++MINOR))
   NEW_VERSION=$MAJOR.$MINOR
   PERL_NEW=$MAJOR\\.$MINOR     
   NEW_RELEASE="RELEASE_${NEW_VERSION//\./_}"
@@ -63,9 +63,9 @@ fi
 
 (cd $WDROOT && svn status) | while read s; do
   case "`echo $s | tr -s ' '`" in
-    "M "$DIRPAT/smartmontools/CHANGELOG)    echo "$s: OK";;
+    "M "$DIRPAT/smartmontools/ChangeLog)    echo "$s: OK";;
     "M "$DIRPAT/smartmontools/NEWS)         echo "$s: OK";;
-    "M "$DIRPAT/smartmontools/configure.in) echo "$s: OK";;
+    "M "$DIRPAT/smartmontools/configure.ac) echo "$s: OK";;
     *) echo "$s: not allowed"; exit 1;;
   esac
 done
@@ -74,9 +74,9 @@ if [ $? -ne 0 ]; then
 fi
 
 # Get release number
-VERSION=`sed -n 's|^AC_INIT[^,]*, *\([0-9.]*\) *,.*$|\1|p' configure.in`
+VERSION=`sed -n 's|^AC_INIT[^,]*, *\([0-9.]*\) *,.*$|\1|p' configure.ac`
 if [ -z "$VERSION" ]; then
-  echo "AC_INIT not found in configure.in"; exit 1
+  echo "AC_INIT not found in configure.ac"; exit 1
 fi
 VERSIONRC="$VERSION"
 RELEASE="RELEASE_${VERSION//\./_}"
@@ -95,8 +95,8 @@ echo "r$REV: Release $VERSIONRC $RELEASE"
 # Update timestamp
 smartmontools_release_date=`date -u +"%Y-%m-%d"`
 smartmontools_release_time=`date -u +"%T %Z"`
-cat configure.in  | sed "s|smartmontools_release_date=.*|smartmontools_release_date=${smartmontools_release_date}|" > configure.tmp
-cat configure.tmp | sed "s|smartmontools_release_time=.*|smartmontools_release_time=\"${smartmontools_release_time}\"|" > configure.in
+cat configure.ac  | sed "s|smartmontools_release_date=.*|smartmontools_release_date=${smartmontools_release_date}|" > configure.tmp
+cat configure.tmp | sed "s|smartmontools_release_time=.*|smartmontools_release_time=\"${smartmontools_release_time}\"|" > configure.ac
 rm -f configure.tmp
 
 # Review changes
@@ -134,8 +134,8 @@ md5sum $TARFILE > $TARFILE.md5
 if [ -z "$RC" -a "$DIRPAT" = "trunk" ]; then
   inc_release
   if [ "$COMMIT" = "yes" ]; then
-    perl -p -i.bak -e "s/$PERL_OLD/$PERL_NEW/" configure.in
-    # svn commit -m "Bump release number to $NEW_VERSION" configure.in
+    perl -p -i.bak -e "s/$PERL_OLD/$PERL_NEW/" configure.ac
+    # svn commit -m "Bump release number to $NEW_VERSION" configure.ac
   fi
 fi
 
index 31cce28db3e4bd4b09d03e84a8121b7bf0ef61db..5d60396c27b04a91dd243d1b0da858d8a2d5a8ec 100644 (file)
--- a/drivedb.h
+++ b/drivedb.h
@@ -4,7 +4,7 @@
  * Home page of code is: http://smartmontools.sourceforge.net
  *
  * Copyright (C) 2003-11 Philip Williams, Bruce Allen
- * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-13 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
@@ -75,7 +75,7 @@
 /*
 const drive_settings builtin_knowndrives[] = {
  */
-  { "$Id: drivedb.h 3559 2012-06-05 18:35:10Z chrfranke $",
+  { "$Id: drivedb.h 3812 2013-04-20 18:59:19Z chrfranke $",
     "-", "-",
     "This is a dummy entry to hold the SVN-Id of drivedb.h",
     ""
@@ -85,72 +85,72 @@ const drive_settings builtin_knowndrives[] = {
     "-v 3,raw16(avg16),Spin_Up_Time "
     "-v 4,raw48,Start_Stop_Count "
     "-v 5,raw16(raw16),Reallocated_Sector_Ct "
-    "-v 6,raw48,Read_Channel_Margin "
-    "-v 7,raw48,Seek_Error_Rate "
-    "-v 8,raw48,Seek_Time_Performance "
-    "-v 9,raw24(raw8),Power_On_Hours " // smartmontools <= r3527: raw48
-    "-v 10,raw48,Spin_Retry_Count "
-    "-v 11,raw48,Calibration_Retry_Count "
+    "-v 6,raw48,Read_Channel_Margin "             // HDD only
+    "-v 7,raw48,Seek_Error_Rate "                 // HDD only
+    "-v 8,raw48,Seek_Time_Performance "           // HDD only
+    "-v 9,raw24(raw8),Power_On_Hours "
+    "-v 10,raw48,Spin_Retry_Count "               // HDD only
+    "-v 11,raw48,Calibration_Retry_Count "        // HDD only
     "-v 12,raw48,Power_Cycle_Count "
     "-v 13,raw48,Read_Soft_Error_Rate "
     //  14-174 Unknown_Attribute
-    "-v 175,raw48,Program_Fail_Count_Chip "
-    "-v 176,raw48,Erase_Fail_Count_Chip "
-    "-v 177,raw48,Wear_Leveling_Count "
-    "-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip "
-    "-v 179,raw48,Used_Rsvd_Blk_Cnt_Tot "
-    "-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot "
+    "-v 175,raw48,Program_Fail_Count_Chip "       // SSD only
+    "-v 176,raw48,Erase_Fail_Count_Chip "         // SSD only
+    "-v 177,raw48,Wear_Leveling_Count "           // SSD only
+    "-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip "        // SSD only
+    "-v 179,raw48,Used_Rsvd_Blk_Cnt_Tot "         // SSD only
+    "-v 180,raw48,Unused_Rsvd_Blk_Cnt_Tot "       // SSD only
     "-v 181,raw48,Program_Fail_Cnt_Total "
-    "-v 182,raw48,Erase_Fail_Count_Total "
+    "-v 182,raw48,Erase_Fail_Count_Total "        // SSD only
     "-v 183,raw48,Runtime_Bad_Block "
     "-v 184,raw48,End-to-End_Error "
     //  185-186 Unknown_Attribute
     "-v 187,raw48,Reported_Uncorrect "
     "-v 188,raw48,Command_Timeout "
-    "-v 189,raw48,High_Fly_Writes "
+    "-v 189,raw48,High_Fly_Writes "               // HDD only
     "-v 190,tempminmax,Airflow_Temperature_Cel "
-    "-v 191,raw48,G-Sense_Error_Rate "
+    "-v 191,raw48,G-Sense_Error_Rate "            // HDD only
     "-v 192,raw48,Power-Off_Retract_Count "
-    "-v 193,raw48,Load_Cycle_Count "
+    "-v 193,raw48,Load_Cycle_Count "              // HDD only
     "-v 194,tempminmax,Temperature_Celsius "
     "-v 195,raw48,Hardware_ECC_Recovered "
     "-v 196,raw16(raw16),Reallocated_Event_Count "
     "-v 197,raw48,Current_Pending_Sector "
     "-v 198,raw48,Offline_Uncorrectable "
     "-v 199,raw48,UDMA_CRC_Error_Count "
-    "-v 200,raw48,Multi_Zone_Error_Rate "
-    "-v 201,raw48,Soft_Read_Error_Rate "
-    "-v 202,raw48,Data_Address_Mark_Errs "
+    "-v 200,raw48,Multi_Zone_Error_Rate "         // HDD only
+    "-v 201,raw48,Soft_Read_Error_Rate "          // HDD only
+    "-v 202,raw48,Data_Address_Mark_Errs "        // HDD only
     "-v 203,raw48,Run_Out_Cancel "
     "-v 204,raw48,Soft_ECC_Correction "
     "-v 205,raw48,Thermal_Asperity_Rate "
-    "-v 206,raw48,Flying_Height "
-    "-v 207,raw48,Spin_High_Current "
-    "-v 208,raw48,Spin_Buzz "
-    "-v 209,raw48,Offline_Seek_Performnce "
+    "-v 206,raw48,Flying_Height "                 // HDD only
+    "-v 207,raw48,Spin_High_Current "             // HDD only
+    "-v 208,raw48,Spin_Buzz "                     // HDD only
+    "-v 209,raw48,Offline_Seek_Performnce "       // HDD only
     //  210-219 Unknown_Attribute
-    "-v 220,raw48,Disk_Shift "
-    "-v 221,raw48,G-Sense_Error_Rate "
-    "-v 222,raw48,Loaded_Hours "
-    "-v 223,raw48,Load_Retry_Count "
-    "-v 224,raw48,Load_Friction "
-    "-v 225,raw48,Load_Cycle_Count "
-    "-v 226,raw48,Load-in_Time "
-    "-v 227,raw48,Torq-amp_Count "
+    "-v 220,raw48,Disk_Shift "                    // HDD only
+    "-v 221,raw48,G-Sense_Error_Rate "            // HDD only
+    "-v 222,raw48,Loaded_Hours "                  // HDD only
+    "-v 223,raw48,Load_Retry_Count "              // HDD only
+    "-v 224,raw48,Load_Friction "                 // HDD only
+    "-v 225,raw48,Load_Cycle_Count "              // HDD only
+    "-v 226,raw48,Load-in_Time "                  // HDD only
+    "-v 227,raw48,Torq-amp_Count "                // HDD only
     "-v 228,raw48,Power-off_Retract_Count "
     //  229 Unknown_Attribute
-    "-v 230,raw48,Head_Amplitude "
+    "-v 230,raw48,Head_Amplitude "                // HDD only
     "-v 231,raw48,Temperature_Celsius "
     "-v 232,raw48,Available_Reservd_Space "
-    "-v 233,raw48,Media_Wearout_Indicator "
+    "-v 233,raw48,Media_Wearout_Indicator "       // SSD only
     //  234-239 Unknown_Attribute
-    "-v 240,raw48,Head_Flying_Hours "
+    "-v 240,raw48,Head_Flying_Hours "             // HDD only
     "-v 241,raw48,Total_LBAs_Written "
     "-v 242,raw48,Total_LBAs_Read "
     //  243-249 Unknown_Attribute
     "-v 250,raw48,Read_Error_Retry_Rate "
     //  251-253 Unknown_Attribute
-    "-v 254,raw48,Free_Fall_Sensor "
+    "-v 254,raw48,Free_Fall_Sensor "              // HDD only
   */
   },
   { "Apple SSD SM128", // Samsung?
@@ -161,10 +161,9 @@ const drive_settings builtin_knowndrives[] = {
     "ASUS-PHISON SSD",
     "", "", ""
   },
-  { "Crucial/Micron RealSSD C300/C400/m4",
-    "C300-CTFDDA[AC](064|128|256)MAG|" // Marvell 88SS9174 BJP2, tested with C300-CTFDDAC128MAG/0002
-    "C400-MTFDDA[ACK](064|128|256|512)MAM|" // Marvel 9176, tested with C400-MTFDDAC256MAM/0002
-    "M4-CT(064|128|256|512)M4SSD2", // tested with M4-CT064M4SSD2/0002, M4-CT512M4SSD2/0309
+  { "Crucial/Micron RealSSD C300", // Marvell 88SS9174 BJP2
+    "C300-CTFDDA[AC](064|128|256)MAG", // tested with C300-CTFDDAC128MAG/0002,
+      // C300-CTFDDAC064MAG/0006
     "", "",
   //"-v 1,raw48,Raw_Read_Error_Rate "
   //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
@@ -173,7 +172,7 @@ const drive_settings builtin_knowndrives[] = {
     "-v 170,raw48,Grown_Failing_Block_Ct "
     "-v 171,raw48,Program_Fail_Count "
     "-v 172,raw48,Erase_Fail_Count "
-    "-v 173,raw48,Wear_Levelling_Count "
+    "-v 173,raw48,Wear_Leveling_Count "
     "-v 174,raw48,Unexpect_Power_Loss_Ct "
     "-v 181,raw16,Non4k_Aligned_Access "
     "-v 183,raw48,SATA_Iface_Downshift "
@@ -190,18 +189,78 @@ const drive_settings builtin_knowndrives[] = {
     "-v 202,raw48,Perc_Rated_Life_Used "
     "-v 206,raw48,Write_Error_Rate"
   },
+  { "Crucial/Micron RealSSD m4/C400", // Marvell 9176, fixed firmware
+    "C400-MTFDDA[ACK](064|128|256|512)MAM|"
+    "M4-CT(064|128|256|512)M4SSD[23]", // tested with M4-CT512M4SSD2/0309
+    "030[9-Z]|03[1-Z].|0[4-Z]..|[1-Z]....*", // >= "0309"
+    "",
+  //"-v 1,raw48,Raw_Read_Error_Rate "
+  //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 170,raw48,Grown_Failing_Block_Ct "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+    "-v 173,raw48,Wear_Leveling_Count "
+    "-v 174,raw48,Unexpect_Power_Loss_Ct "
+    "-v 181,raw16,Non4k_Aligned_Access "
+    "-v 183,raw48,SATA_Iface_Downshift "
+  //"-v 184,raw48,End-to-End_Error "
+  //"-v 187,raw48,Reported_Uncorrect "
+  //"-v 188,raw48,Command_Timeout "
+    "-v 189,raw48,Factory_Bad_Block_Ct "
+  //"-v 194,tempminmax,Temperature_Celsius "
+  //"-v 195,raw48,Hardware_ECC_Recovered "
+  //"-v 196,raw16(raw16),Reallocated_Event_Count "
+  //"-v 197,raw48,Current_Pending_Sector "
+  //"-v 198,raw48,Offline_Uncorrectable "
+  //"-v 199,raw48,UDMA_CRC_Error_Count "
+    "-v 202,raw48,Perc_Rated_Life_Used "
+    "-v 206,raw48,Write_Error_Rate"
+  },
+  { "Crucial/Micron RealSSD m4/C400", // Marvell 9176, buggy or unknown firmware
+    "C400-MTFDDA[ACK](064|128|256|512)MAM|" // tested with C400-MTFDDAC256MAM/0002
+    "M4-CT(064|128|256|512)M4SSD[23]", // tested with M4-CT064M4SSD2/0002,
+      // M4-CT064M4SSD2/0009, M4-CT256M4SSD3/000F
+    "",
+    "This drive may hang after 5184 hours of power-on time:\n"
+    "http://www.tomshardware.com/news/Crucial-m4-Firmware-BSOD,14544.html\n"
+    "See the following web pages for firmware updates:\n"
+    "http://www.crucial.com/support/firmware.aspx\n"
+    "http://www.micron.com/products/solid-state-storage/client-ssd#software",
+    "-v 170,raw48,Grown_Failing_Block_Ct "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+    "-v 173,raw48,Wear_Leveling_Count "
+    "-v 174,raw48,Unexpect_Power_Loss_Ct "
+    "-v 181,raw16,Non4k_Aligned_Access "
+    "-v 183,raw48,SATA_Iface_Downshift "
+    "-v 189,raw48,Factory_Bad_Block_Ct "
+    "-v 202,raw48,Perc_Rated_Life_Used "
+    "-v 206,raw48,Write_Error_Rate"
+  },
   { "SandForce Driven SSDs",
     "SandForce 1st Ed\\.|" // Demo Drive, tested with firmware 320A13F0
-    "ADATA SSD S(510|599) .?..GB|" // tested with ADATA SSD S510 60GB/320ABBF0,
+    "ADATA SSD S(396|510|599) .?..GB|" // tested with ADATA SSD S510 60GB/320ABBF0,
       // ADATA SSD S599 256GB/3.1.0, 64GB/3.4.6
-    "Corsair CSSD-F(40|60|80|120|160|240)GBP?2.*|" // Corsair Force, tested with
-      // Corsair CSSD-F40GB2/1.1
-    "Corsair Force (3 SSD|GT)|" // SF-2281, tested with Corsair Force 3 SSD/1.3.2, GT/1.3.3
+    "Corsair CSSD-F(40|60|80|115|120|160|240)GBP?2.*|" // Corsair Force, tested with
+      // Corsair CSSD-F40GB2/1.1, Corsair CSSD-F115GB2-A/2.1a
+    "Corsair Force (3 SSD|GS|GT)|" // SF-2281, tested with
+      // Corsair Force 3 SSD/1.3.2, GT/1.3.3, GS/5.03
     "FM-25S2S-(60|120|240)GBP2|" // G.SKILL Phoenix Pro, SF-1200, tested with
       // FM-25S2S-240GBP2/4.2
     "FTM(06|12|24|48)CT25H|" // Supertalent TeraDrive CT, tested with
       // FTM24CT25H/STTMP2P1
-    "KINGSTON SH100S3(120|240)G|" // Hyper-X, SF-2281, tested with SH100S3240G/320ABBF0
+    "KINGSTON SH10[03]S3(90|120|240|480)G|" // HyperX (3K), SF-2281, tested with
+      // SH100S3240G/320ABBF0, SH103S3120G/505ABBF0
+    "KINGSTON SVP200S3(7A)?(60|90|120|240|480)G|" // V+ 200, SF-2281, tested with
+      // SVP200S37A480G/502ABBF0, SVP200S390G/332ABBF0
+    "KINGSTON SMS450S3(32|64|128)G|" // mSATA, SF-2281, tested with SMS450S3128G/503ABBF0
+    "KINGSTON (SV300|SKC100|SE100)S3.*G|" // other SF-2281
+    "MKNSSDCR(45|60|90|120|180|240|480)GB(-DX)?|" // Mushkin Chronos (deluxe), SF-2281,
+      // tested with MKNSSDCR120GB
+    "Mushkin MKNSSDCL(40|60|80|90|115|120|180|240|480)GB-DX2?|" // Mushkin Callisto deluxe,
+      // SF-1200/1222, Mushkin MKNSSDCL60GB-DX/361A13F0
     "OCZ[ -](AGILITY2([ -]EX)?|COLOSSUS2|ONYX2|VERTEX(2|-LE))( [123]\\..*)?|" // SF-1200,
       // tested with OCZ-VERTEX2/1.11, OCZ-VERTEX2 3.5/1.11
     "OCZ-NOCTI|" // mSATA, SF-2100, tested with OCZ-NOCTI/2.15
@@ -215,15 +274,22 @@ const drive_settings builtin_knowndrives[] = {
       // OCZ-AGILITY3/2.11, OCZ-SOLID3/2.15, OCZ-VERTEX3 MI/2.15
     "OCZ Z-DRIVE R4 [CR]M8[48]|" // PCIe, SF-2282/2582, tested with OCZ Z-DRIVE R4 CM84/2.13
       // (Bogus attributes under Linux)
+    "TALOS2|" // OCZ Talos 2 C/R, SAS (works with -d sat), 2*SF-2282, tested with TALOS2/3.20E
     "(APOC|DENC|DENEVA|FTNC|GFGC|MANG|MMOC|NIMC|TMSC).*|" // other OCZ SF-1200,
       // tested with DENCSTE251M11-0120/1.33, DENEVA PCI-E/1.33
     "(DENR|DRSAK|EC188|NIMR|PSIR|TRSAK).*|" // other OCZ SF-1500
+    "OWC Mercury Electra [36]G SSD|" // tested with
+      // OWC Mercury Electra 6G SSD/502ABBF0
     "OWC Mercury Extreme Pro (RE )?SSD|" // tested with
       // OWC Mercury Extreme Pro SSD/360A13F0
     "Patriot Pyro|" // tested with Patriot Pyro/332ABBF0
-    "(TX32|TX31C1|VN0..GCNMK|VN0...GCNMK).*|" // Smart Storage Systems XceedSTOR
+    "SanDisk SDSSDX(60|120|240|480)GG25|" // SanDisk Extreme, SF-2281, tested with
+      // SDSSDX240GG25/R201
+    "SuperSSpeed S301 [0-9]*GB|" // SF-2281, tested with SuperSSpeed S301 128GB/503
+    "(TX32|TX31C1|VN0.?..GCNMK).*|" // Smart Storage Systems XceedSTOR
     "(TX22D1|TX21B1).*|" // Smart Storage Systems XceedIOPS2
     "TX52D1.*|" // Smart Storage Systems Xcel-200
+    "TS(64|128|256|512)GSSD320|" // Transcend SSD320, SF-2281, tested with TS128GSSD320
     "UGB(88P|99S)GC...H[BF].", // Unigen, tested with
       // UGB88PGC100HF2/MP Rev2, UGB99SGC100HB3/RC Rev3
     "", "",
@@ -242,10 +308,11 @@ const drive_settings builtin_knowndrives[] = {
     "-v 182,raw48,Erase_Fail_Count "
     "-v 184,raw48,IO_Error_Detect_Code_Ct "
   //"-v 187,raw48,Reported_Uncorrect "
+    "-v 189,tempminmax,Airflow_Temperature_Cel "
   //"-v 194,tempminmax,Temperature_Celsius "
     "-v 195,raw24/raw32,ECC_Uncorr_Error_Count "
   //"-v 196,raw16(raw16),Reallocated_Event_Count "
-    "-v 198,hex48,Uncorrectable_Sector_Ct "
+    "-v 198,raw24/raw32:210zr54,Uncorrectable_Sector_Ct " // KINGSTON SE100S3100G/510ABBF0
     "-v 199,raw48,SATA_CRC_Error_Count "
     "-v 201,raw24/raw32,Unc_Soft_Read_Err_Rate "
     "-v 204,raw24/raw32,Soft_ECC_Correct_Rate "
@@ -295,9 +362,12 @@ const drive_settings builtin_knowndrives[] = {
     "-v 212,raw64,SATA_Error_Ct_Handshake "
     "-v 213,raw64,Indilinx_Internal"
   },
-  { "Indilinx Everest/Martini based SSDs",
-    "OCZ VERTEX-PLUS|" // tested with OCZ VERTEX-PLUS/3.55
-    "OCZ-PETROL", // tested with OCZ-PETROL/3.12
+  { "Indilinx Barefoot_2/Everest/Martini based SSDs",
+    "OCZ VERTEX[ -]PLUS|" // tested with OCZ VERTEX-PLUS/3.55, OCZ VERTEX PLUS/3.55
+    "OCZ-VERTEX PLUS R2|" // Barefoot 2, tested with OCZ-VERTEX PLUS R2/1.2
+    "OCZ-PETROL|" // Everest 1, tested with OCZ-PETROL/3.12
+    "OCZ-AGILITY4|" // Everest 2, tested with OCZ-AGILITY4/1.5.2
+    "OCZ-VERTEX4", // Everest 2, tested with OCZ-VERTEX4/1.5
     "", "", ""
   //"-v 1,raw48,Raw_Read_Error_Rate "
   //"-v 3,raw16(avg16),Spin_Up_Time "
@@ -305,9 +375,52 @@ const drive_settings builtin_knowndrives[] = {
   //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
   //"-v 9,raw24(raw8),Power_On_Hours "
   //"-v 12,raw48,Power_Cycle_Count "
-  //"-v 232,raw48,Available_Reservd_Space "
+    "-v 232,raw48,Lifetime_Writes " // LBA?
   //"-v 233,raw48,Media_Wearout_Indicator"
   },
+  { "Indilinx Barefoot 3 based SSDs",
+    "OCZ-VECTOR", // tested with OCZ-VECTOR/1.03
+    "", "", ""
+    "-v 5,raw48,Runtime_Bad_Block "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 171,raw48,Avail_OP_Block_Count "
+    "-v 174,raw48,Pwr_Cycle_Ct_Unplanned "
+    "-v 187,raw48,Total_Unc_NAND_Reads "
+    "-v 195,raw48,Total_Prog_Failures "
+    "-v 196,raw48,Total_Erase_Failures "
+    "-v 197,raw48,Total_Unc_Read_Failures "
+    "-v 198,raw48,Host_Reads_GiB "
+    "-v 199,raw48,Host_Writes_GiB "
+    "-v 208,raw48,Average_Erase_Count "
+    "-v 210,raw48,SATA_CRC_Error_Count "
+    "-v 233,raw48,Remaining_Lifetime_Perc "
+    "-v 249,raw48,Total_NAND_Prog_Ct_GiB"
+  },
+  { "InnoDisk InnoLite SATADOM D150QV-L SSDs", // tested with InnoLite SATADOM D150QV-L/120319
+    "InnoLite SATADOM D150QV-L",
+    "", "",
+  //"-v 1,raw48,Raw_Read_Error_Rate "
+  //"-v 2,raw48,Throughput_Performance "
+  //"-v 3,raw16(avg16),Spin_Up_Time "
+  //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
+  //"-v 7,raw48,Seek_Error_Rate " // from InnoDisk iSMART Linux tool, useless for SSD
+  //"-v 8,raw48,Seek_Time_Performance "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 10,raw48,Spin_Retry_Count "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 168,raw48,SATA_PHY_Error_Count "
+    "-v 170,raw48,Bad_Block_Count "
+    "-v 173,raw48,Erase_Count "
+    "-v 175,raw48,Bad_Cluster_Table_Count "
+    "-v 192,raw48,Unexpect_Power_Loss_Ct "
+  //"-v 194,tempminmax,Temperature_Celsius "
+  //"-v 197,raw48,Current_Pending_Sector "
+    "-v 229,hex48,Flash_ID "
+    "-v 235,raw48,Later_Bad_Block "
+    "-v 236,raw48,Unstable_Power_Count "
+    "-v 240,raw48,Write_Head"
+  },
   { "Intel X25-E SSDs",
     "SSDSA2SH(032|064)G1.* INTEL",  // G1 = first generation
     "", "",
@@ -372,9 +485,35 @@ const drive_settings builtin_knowndrives[] = {
     "-v 227,raw48,Workld_Host_Reads_Perc "
     "-v 228,raw48,Workload_Minutes"
   },
-  { "Intel 320 Series SSDs", // tested with INTEL SSDSA2CT040G3/4PC10362
-    "INTEL SSDSA[12]C[WT](040|080|120|160|300|600)G3",
+  { "Intel 313 Series SSDs", // tested with INTEL SSDSA2VP020G3/9CV10379
+    "INTEL SSDSA2VP(020|024)G3",
+    "", "",
+  //"-v 3,raw16(avg16),Spin_Up_Time "
+  //"-v 4,raw48,Start_Stop_Count "
+  //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 170,raw48,Reserve_Block_Count "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+    "-v 183,raw48,SATA_Downshift_Count "
+  //"-v 184,raw48,End-to-End_Error "
+  //"-v 187,raw48,Reported_Uncorrect "
+    "-v 192,raw48,Unsafe_Shutdown_Count "
+    "-v 225,raw48,Host_Writes_32MiB "
+    "-v 226,raw48,Workld_Media_Wear_Indic " // Timed Workload Media Wear Indicator (percent*1024)
+    "-v 227,raw48,Workld_Host_Reads_Perc "  // Timed Workload Host Reads Percentage
+    "-v 228,raw48,Workload_Minutes " // 226,227,228 can be reset by 'smartctl -t vendor,0x40'
+  //"-v 232,raw48,Available_Reservd_Space "
+  //"-v 233,raw48,Media_Wearout_Indicator "
+    "-v 241,raw48,Host_Writes_32MiB "
+    "-v 242,raw48,Host_Reads_32MiB"
+  },
+  { "Intel 320 Series SSDs", // tested with INTEL SSDSA2CT040G3/4PC10362,
+      // INTEL SSDSA2CW160G3/4PC10362, INTEL SSDSA2BT040G3/4PC10362
+    "INTEL SSDSA[12][BC][WT](040|080|120|160|300|600)G3",
     "", "",
+    "-F nologdir "
   //"-v 3,raw16(avg16),Spin_Up_Time "
   //"-v 4,raw48,Start_Stop_Count "
   //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
@@ -395,9 +534,10 @@ const drive_settings builtin_knowndrives[] = {
     "-v 241,raw48,Host_Writes_32MiB "
     "-v 242,raw48,Host_Reads_32MiB"
   },
-  { "Intel 710 Series SSDs", // tested with INTEL SSDSA2BZ100G3/6PB10362
+  { "Intel 710 Series SSDs", // tested with INTEL SSDSA2BZ[12]00G3/6PB10362
     "INTEL SSDSA2BZ(100|200|300)G3",
     "", "",
+    "-F nologdir "
   //"-v 3,raw16(avg16),Spin_Up_Time "
   //"-v 4,raw48,Start_Stop_Count "
   //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
@@ -406,7 +546,7 @@ const drive_settings builtin_knowndrives[] = {
     "-v 170,raw48,Reserve_Block_Count "
     "-v 171,raw48,Program_Fail_Count "
     "-v 172,raw48,Erase_Fail_Count "
-  //"-v 174,raw48,Unknown_Attribute "
+    "-v 174,raw48,Unexpect_Power_Loss_Ct " // Missing in 710 specification from September 2011
     "-v 183,raw48,SATA_Downshift_Count "
   //"-v 184,raw48,End-to-End_Error "
   //"-v 187,raw48,Reported_Uncorrect "
@@ -434,8 +574,8 @@ const drive_settings builtin_knowndrives[] = {
   //"-v 232,raw48,Available_Reservd_Space "
   //"-v 233,raw48,Media_Wearout_Indicator"
   },
-  { "Intel 520 Series SSDs", // tested with INTEL SSDSC2CW120A3/400i
-    "INTEL SSDSC2CW(060|120|180|240|480)A3",
+  { "Intel 520 Series SSDs", // tested with INTEL SSDSC2CW120A3/400i, SSDSC2BW480A3F/400i
+    "INTEL SSDSC2[BC]W(060|120|180|240|480)A3F?",
     "", "",
   //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
     "-v 9,msec24hour32,Power_On_Hours_and_Msec "
@@ -457,8 +597,8 @@ const drive_settings builtin_knowndrives[] = {
     "-v 242,raw48,Host_Reads_32MiB "
     "-v 249,raw48,NAND_Writes_1GiB"
   },
-  { "Intel 330 Series SSDs", // tested with INTEL SSDSC2CT180A3/300i
-    "INTEL SSDSC2CT(060|120|180)A3",
+  { "Intel 330 Series SSDs", // tested with INTEL SSDSC2CT180A3/300i, SSDSC2CT240A3/300i
+    "INTEL SSDSC2CT(060|120|180|240)A3",
     "", "",
   //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
     "-v 9,msec24hour32,Power_On_Hours_and_Msec "
@@ -473,6 +613,37 @@ const drive_settings builtin_knowndrives[] = {
     "-v 242,raw48,Host_Reads_32MiB "
     "-v 249,raw48,NAND_Writes_1GiB"
   },
+  { "Intel DC S3700 Series SSDs", // tested with INTEL SSDSC2BA200G3/5DV10250
+    "INTEL SSDSC(1N|2B)A(100|200|400|800)G3",
+    "", "",
+  //"-v 3,raw16(avg16),Spin_Up_Time "
+  //"-v 4,raw48,Start_Stop_Count "
+  //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 170,raw48,Available_Reservd_Space "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+    "-v 174,raw48,Unsafe_Shutdown_Count "
+    "-v 175,raw48,Power_Loss_Cap_Test "
+    "-v 183,raw48,SATA_Downshift_Count "
+  //"-v 184,raw48,End-to-End_Error "
+  //"-v 187,raw48,Reported_Uncorrect "
+    "-v 190,tempminmax,Temperature_Case "
+    "-v 192,raw48,Unsafe_Shutdown_Count "
+    "-v 194,tempminmax,Temperature_Internal "
+  //"-v 197,raw48,Current_Pending_Sector "
+    "-v 199,raw48,CRC_Error_Count "
+    "-v 225,raw48,Host_Writes_32MiB "
+    "-v 226,raw48,Workld_Media_Wear_Indic " // Timed Workload Media Wear Indicator (percent*1024)
+    "-v 227,raw48,Workld_Host_Reads_Perc "  // Timed Workload Host Reads Percentage
+    "-v 228,raw48,Workload_Minutes " // 226,227,228 can be reset by 'smartctl -t vendor,0x40'
+  //"-v 232,raw48,Available_Reservd_Space "
+  //"-v 233,raw48,Media_Wearout_Indicator "
+    "-v 234,raw48,Thermal_Throttle "
+    "-v 241,raw48,Host_Writes_32MiB "
+    "-v 242,raw48,Host_Reads_32MiB"
+  },
   { "Kingston branded X25-V SSDs", // fixed firmware
     "KINGSTON SSDNow 40GB",
     "2CV102(J[89A-Z]|[K-Z].)", // >= "2CV102J8"
@@ -507,23 +678,24 @@ const drive_settings builtin_knowndrives[] = {
     "-v 229,hex64:w012345r,Halt_System/Flash_ID " // Halt, Flash[7]
     "-v 232,hex64:w012345r,Firmware_Version_Info " // "YYMMDD", #Channels, #Banks
     "-v 233,hex48:w01234,ECC_Fail_Record " // Fail number, Row[3], Channel, Bank
-    "-v 234,raw24/raw24:w01234,Avg/Max_Erase_Ct "
-    "-v 235,raw24/raw24:w01z23,Good/Sys_Block_Ct"
-    //  1.....................................40 chars limit for smartmontools <= r3342
+    "-v 234,raw24/raw24:w01234,Avg/Max_Erase_Count "
+    "-v 235,raw24/raw24:w01z23,Good/Sys_Block_Count"
   },
   { "JMicron based SSDs", // JMicron JMF61x
     "ADATA S596 Turbo|"  // tested with ADATA S596 Turbo 256GB SATA SSD (JMicron JMF616)
     "APPLE SSD TS.*|"  // Toshiba?, tested with APPLE SSD TS064C/CJAA0201
     "KINGSTON SNV425S2(64|128)GB|"  // SSDNow V Series (2. Generation, JMF618),
                                     // tested with KINGSTON SNV425S264GB/C091126a
+    "KINGSTON SSDNOW 30GB|" // tested with KINGSTON SSDNOW 30GB/AJXA0202
     "KINGSTON SS100S2(8|16)G|"  // SSDNow S100 Series, tested with KINGSTON SS100S28G/D100309a
     "KINGSTON SVP?100S2B?(64|96|128|256|512)G|"  // SSDNow V100/V+100 Series,
-                                                 // tested with KINGSTON SVP100S296G/CJR10202,
-                                                 // KINGSTON SV100S2256G/D110225a
+      // tested with KINGSTON SVP100S296G/CJR10202, KINGSTON SV100S2256G/D110225a
+    "KINGSTON SV200S3(64|128|256)G|" // SSDNow V200 Series, tested with KINGSTON SV200S3128G/E120506a
     "TOSHIBA THNS128GG4BBAA|"  // Toshiba / Super Talent UltraDrive DX,
                                // tested with Toshiba 128GB 2.5" SSD (built in MacBooks)
     "TOSHIBA THNSNC128GMLJ|" // tested with THNSNC128GMLJ/CJTA0202 (built in Toshiba Protege/Dynabook)
-    "TS(8|16|32|64|128|192|256|512)GSSD25S-(MD?|S)", // Transcend SATA (JMF612), tested with TS256GSSD25S-M/101028
+    "TS(8|16|32|64|128|192|256|512)GSSD25S?-(MD?|S)", // Transcend IDE and SATA (JMF612), tested with
+      // TS256GSSD25S-M/101028, TS32GSSD25-M/20101227
     "", "",
   //"-v 1,raw48,Raw_Read_Error_Rate "
   //"-v 2,raw48,Throughput_Performance "
@@ -545,12 +717,38 @@ const drive_settings builtin_knowndrives[] = {
   //"-v 197,raw48,Current_Pending_Sector "
     "-v 240,raw48,Unknown_Attribute"
   },
+  { "Plextor M3 (Pro) Series SSDs", // Marvell 9174, tested with PLEXTOR PX-128M3/1.01,
+      // PLEXTOR PX-128M3P/1.04, PLEXTOR PX-256M3/1.05
+      // (1.04/5 Firmware self-test log lifetime unit is bogus, possibly 1/256 hours)
+    "PLEXTOR PX-(64|128|256|512)M3P?",
+    "", "",
+  //"-v 1,raw48,Raw_Read_Error_Rate "
+  //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+  //"-v 177,raw48,Wear_Leveling_Count "
+  //"-v 178,raw48,Used_Rsvd_Blk_Cnt_Chip "
+  //"-v 181,raw48,Program_Fail_Cnt_Total "
+  //"-v 182,raw48,Erase_Fail_Count_Total "
+  //"-v 187,raw48,Reported_Uncorrect "
+  //"-v 192,raw48,Power-Off_Retract_Count "
+  //"-v 196,raw16(raw16),Reallocated_Event_Count "
+  //"-v 198,raw48,Offline_Uncorrectable "
+  //"-v 199,raw48,UDMA_CRC_Error_Count "
+  //"-v 232,raw48,Available_Reservd_Space "
+    ""
+  },
   { "Samsung based SSDs",
     "SAMSUNG SSD PM800 .*GB|"  // SAMSUNG PM800 SSDs, tested with SAMSUNG SSD PM800 TH 64GB/VBM25D1Q
     "SAMSUNG SSD PM810 .*GB|"  // SAMSUNG PM810 (470 series) SSDs, tested with SAMSUNG SSD PM810 2.5" 128GB/AXM06D1Q
     "SAMSUNG 470 Series SSD|"  // tested with SAMSUNG 470 Series SSD 64GB/AXM09B1Q
-    "SAMSUNG SSD 830 Series",  // tested with SAMSUNG SSD 830 Series 64GB/CXM03B1Q
+    "SAMSUNG SSD 830 Series|"  // tested with SAMSUNG SSD 830 Series 64GB/CXM03B1Q
+    "Samsung SSD 840 (PRO )?Series|" // tested with Samsung SSD 840 PRO Series 128GB/DXM04B0Q,
+      // Samsung SSD 840 Series/DXT06B0Q
+    "SAMSUNG MZ7WD((120|240)HAFV|480HAGM|960HAGP)-00003", // SM843T Series, tested with
+      // SAMSUNG MZ7WD120HAFV-00003/DXM85W3Q
     "", "",
+  //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
   //"-v 9,raw24(raw8),Power_On_Hours "
   //"-v 12,raw48,Power_Cycle_Count "
   //"-v 175,raw48,Program_Fail_Count_Chip "
@@ -562,16 +760,34 @@ const drive_settings builtin_knowndrives[] = {
   //"-v 181,raw48,Program_Fail_Cnt_Total "
   //"-v 182,raw48,Erase_Fail_Count_Total "
   //"-v 183,raw48,Runtime_Bad_Block "
+  //"-v 184,raw48,End-to-End_Error " // SM843T Series
     "-v 187,raw48,Uncorrectable_Error_Cnt "
   //"-v 190,tempminmax,Airflow_Temperature_Cel "  // seems to be some sort of temperature value for 470 Series?
   //"-v 194,tempminmax,Temperature_Celsius "
-    "-v 195,raw48,ECC_Rate "
+    "-v 195,raw48,ECC_Error_Rate "
   //"-v 198,raw48,Offline_Uncorrectable "
     "-v 199,raw48,CRC_Error_Count "
     "-v 201,raw48,Supercap_Status "
     "-v 202,raw48,Exception_Mode_Status "
-    "-v 240,raw48,Unknown_Attribute"  // 830 Series
-  //"-v 241,raw48,Total_LBAs_Written" // 830 Series
+    "-v 235,raw48,POR_Recovery_Count " // 830/840 Series
+  //"-v 241,raw48,Total_LBAs_Written"
+  },
+  { "Smart Storage Systems Xcel-10 SSDs",  // based on http://www.smartm.com/files/salesLiterature/storage/xcel10.pdf
+    "SMART A25FD-(32|64|128)GI32N", // tested with SMART A25FD-128GI32N/B9F23D4K
+    "",
+    "", // attributes info from http://www.adtron.com/pdf/SMART_Attributes_Xcel-10_810800014_RevB.pdf
+    "-v 1,raw48,Not_Supported "
+    "-v 2,raw48,Not_Supported "
+  //"-v 9,raw24(raw8),Power_On_Hours "
+  //"-v 12,raw48,Power_Cycle_Count "
+    "-v 191,raw48,Not_Supported "
+  //"-v 192,raw48,Power-Off_Retract_Count "
+    "-v 197,raw48,ECC_Error_Count "
+  //"-v 198,raw48,Offline_Uncorrectable "
+  //"-v 199,raw48,UDMA_CRC_Error_Count "
+    "-v 251,raw48,Min_Spares_Remain_Perc " // percentage of the total number of spare blocks available
+    "-v 252,raw48,Added_Bad_Flash_Blk_Ct " // number of bad flash blocks
+    "-v 254,raw48,Total_Erase_Blocks_Ct" // number of times the drive has erased any erase block
   },
   { "Smart Storage Systems XceedSecure2 SSDs",
     "(SMART|Adtron) ([AIS]25FBS|S35FCS).*",
@@ -600,8 +816,7 @@ const drive_settings builtin_knowndrives[] = {
     "-v 126,hex64,Proprietary_SF1st "
     "-v 127,hex64,Proprietary_SF2nd "
     "-v 128,hex64,Proprietary_SF3rd "
-    "-v 194,raw24/raw32:zvzzzw,Fract_Temperature"
-    //  1.....................................40 chars limit for smartmontools <= r3342
+    "-v 194,raw24/raw32:zvzzzw,Fractional_Temperature"
   },
   { "Smart Storage Systems Adtron A25FB 3xN SSDs",
     "(SMART|Adtron) A25FB-.*3.N",
@@ -611,6 +826,19 @@ const drive_settings builtin_knowndrives[] = {
     "-v 130,raw48:54321,Minimum_Spares_All_Zs"
   //"-v 194,tempminmax,Temperature_Celsius"
   },
+  { "STEC Mach2 CompactFlash Cards", // tested with STEC M2P CF 1.0.0/K1385MS
+    "STEC M2P CF 1.0.0",
+    "", "",
+    "-v 100,raw48,Erase_Program_Cycles "
+    "-v 103,raw48,Remaining_Energy_Storg "
+    "-v 170,raw48,Reserved_Block_Count "
+    "-v 171,raw48,Program_Fail_Count "
+    "-v 172,raw48,Erase_Fail_Count "
+    "-v 173,raw48,Wear_Leveling_Count "
+    "-v 174,raw48,Unexpect_Power_Loss_Ct "
+    "-v 211,raw48,Unknown_Attribute " // ] Missing in specification
+    "-v 212,raw48,Unknown_Attribute"  // ] from September 2012
+  },
   { "Transcend CompactFlash Cards", // tested with TRANSCEND/20080820,
       // TS4GCF133/20100709, TS16GCF133/20100709
     "TRANSCEND|TS(4|8|16)GCF133",
@@ -864,6 +1092,10 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HD(083G|16[12]G|25[12]H|32[12]H|50[12]I|642J|75[23]L|10[23]U)J",
     "", "", ""
   },
+  { "SAMSUNG SpinPoint F1 EG", // tested with HD103UI/1AA01113
+    "SAMSUNG HD(252H|322H|502I|642J|753L|103U)I",
+    "", "", ""
+  },
   { "SAMSUNG SpinPoint F1 RE", // tested with HE103UJ/1AA01113
     "SAMSUNG HE(252H|322H|502I|642J|753L|103U)J",
     "", "", ""
@@ -876,11 +1108,19 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HD(502H|754J|103S)J",
     "", "", ""
   },
+  { "Seagate Barracuda SpinPoint F3", // tested with ST1000DM005 HD103SJ/1AJ100E5
+    "ST[0-9DM]* HD(502H|754J|103S)J",
+    "", "", ""
+  },
   { "SAMSUNG SpinPoint F3 EG", // tested with HD503HI/1AJ100E4, HD153WI/1AN10002
     "SAMSUNG HD(253G|(324|503)H|754J|105S|(153|203)W)I",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint F4 EG (AFT)",// tested with HD204UI/1AQ10001(buggy|fixed)
+  { "SAMSUNG SpinPoint F3 RE", // tested with HE103SJ/1AJ30001
+    "SAMSUNG HE(502H|754J|103S)J",
+    "", "", ""
+  },
+  { "SAMSUNG SpinPoint F4 EG (AF)",// tested with HD204UI/1AQ10001(buggy|fixed)
     "SAMSUNG HD(155|204)UI",
     "", // 1AQ10001
     "Using smartmontools or hdparm with this\n"
@@ -933,8 +1173,9 @@ const drive_settings builtin_knowndrives[] = {
     "May need -F samsung3 enabled; see manual for details.",
     ""
   },
-  { "SAMSUNG SpinPoint P80", // firmware *-25...34, tested with SP1614C/SW100-25 and -34
-    "SAMSUNG SP(0451|08[0124]2|12[0145]3|16[0145]4)[CN]",
+  { "SAMSUNG SpinPoint P80", // firmware *-25...34, tested with
+      // SP0401N/TJ100-30, SP1614C/SW100-25 and -34
+    "SAMSUNG SP(04[05]1|08[0124]2|12[0145]3|16[0145]4)[CN]",
     ".*-(2[5-9]|3[0-4])",
     "",
     "-v 9,halfminutes -v 198,increasing"
@@ -954,8 +1195,8 @@ const drive_settings builtin_knowndrives[] = {
     "May need -F samsung2 or -F samsung3 enabled; see manual for details.",
     ""
   },
-  { "SAMSUNG SpinPoint M40/60/80", // tested with HM160JI/AD100-16
-    "SAMSUNG HM(0[468]0H|1[026]0J)[CI]",
+  { "SAMSUNG SpinPoint M40/60/80", // tested with HM120IC/AN100-16, HM160JI/AD100-16
+    "SAMSUNG HM(0[468]0H|120I|1[026]0J)[CI]",
     "",
     "",
     "-v 9,halfminutes"
@@ -972,7 +1213,7 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HM(250H|320I|[45]00J)I",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint M7E (AFT)", // tested with HM321HI/2AJ10001, HM641JI/2AJ10001
+  { "SAMSUNG SpinPoint M7E (AF)", // tested with HM321HI/2AJ10001, HM641JI/2AJ10001
     "SAMSUNG HM(161G|(251|321)H|501I|641J)I",
     "", "", ""
   },
@@ -980,14 +1221,23 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HM(162H|252H|322I|502J)X",
     "", "", ""
   },
-  { "SAMSUNG SpinPoint M8 (AFT)", // tested with HN-M101MBB/2AR10001
-    "SAMSUNG HN-M(250|500|750|101)MBB",
+  { "SAMSUNG SpinPoint M8 (AF)", // tested with HN-M101MBB/2AR10001
+    "SAMSUNG HN-M(250|320|500|640|750|101)MBB",
+    "", "", ""
+  },
+  { "Seagate Momentus SpinPoint M8 (AF)", // tested with
+      // ST750LM022 HN-M750MBB/2AR10001, ST320LM001 HN-M320MBB/2AR10002
+    "ST(250|320|500|640|750|1000)LM0[012][124] HN-M[0-9]*MBB",
     "", "", ""
   },
   { "SAMSUNG SpinPoint M8U (USB)", // tested with HN-M500XBB/2AR10001
     "SAMSUNG HN-M(320|500|750|101)XBB",
     "", "", ""
   },
+  { "Seagate Samsung SpinPoint M8U (USB)", // tested with ST1000LM025 HN-M101ABB/2AR10001
+    "ST(250|320|500|640|750|1000)LM0[012][3459] HN-M[0-9]*ABB",
+    "", "", ""
+  },
   { "SAMSUNG SpinPoint MP5", // tested with HM250HJ/2AK10001
     "SAMSUNG HM(250H|320H|500J|640J)J",
     "", "", ""
@@ -1010,46 +1260,6 @@ const drive_settings builtin_knowndrives[] = {
     "SAMSUNG HS(122H|2[05]YJ)Z",
     "", "", ""
   },
-  { "SMART Xcel-10 2.5 SATA SSD", //  based on http://www.smartm.com/files/salesLiterature/storage/xcel10.pdf
-    "SMART A25FD-(32|64|128)GI32N", // tested with SMART A25FD-128GI32N/B9F23D4K
-    "",
-    "", // attributes info from http://www.adtron.com/pdf/SMART_Attributes_Xcel-10_810800014_RevB.pdf
-    "-v 1,raw48,Not_Supported "
-    "-v 2,raw48,Not_Supported "
-  //"-v 9,raw24(raw8),Power_On_Hours "
-  //"-v 12,raw48,Power_Cycle_Count "
-    "-v 191,raw48,Not_Supported "
-  //"-v 192,raw48,Power-Off_Retract_Count "
-    "-v 197,raw48,ECC_Error_Count "
-  //"-v 198,raw48,Offline_Uncorrectable "
-  //"-v 199,raw48,UDMA_CRC_Error_Count "
-    "-v 251,raw48,Min_Spares_Remain_Perc " // percentage of the total number of spare blocks available
-    "-v 252,raw48,Added_Bad_Flash_Blk_Ct " // number of bad flash blocks
-    "-v 254,raw48,Total_Erase_Blocks_Ct" // number of times the drive has erased any erase block
-  },
-/*
-  // TODO: Make the entries below more specific.
-  // These entries produce misleading results, because newer
-  // Samsung disks reuse the version numbers *-NN.
-  { "", // All Samsung drives with '.*-25' firmware
-    "SAMSUNG.*",
-    ".*-25",
-    "May need -F samsung2 disabled; see manual for details.",
-    "-v 9,halfminutes -F samsung2"
-  },
-  { "", // All Samsung drives with '.*-26 or later (currently to -39)' firmware
-    "SAMSUNG.*",
-    ".*-(2[6789]|3[0-9])",
-    "",
-    "-v 9,halfminutes"
-  },
-  { "", // Samsung ALL OTHER DRIVES
-    "SAMSUNG.*",
-    "",
-    "May need -F samsung or -F samsung2 enabled; see manual for details.",
-    ""
-  },
-*/
   { "Maxtor Fireball 541DX",
     "Maxtor 2B0(0[468]|1[05]|20)H1",
     "",
@@ -1276,9 +1486,19 @@ const drive_settings builtin_knowndrives[] = {
     "http://knowledge.seagate.com/articles/en_US/FAQ/207975en",
     ""
   },
-  { "Seagate Maxtor DiamondMax 23",
+  { "Seagate Maxtor DiamondMax 23", // new firmware
     "STM3((160|250)31|(320|500)41|(750|1000)52)8AS?",
-    "", "", ""
+    "CC3[D-Z]",
+    "", ""
+  },
+  { "Seagate Maxtor DiamondMax 23", // unknown firmware
+    "STM3((160|250)31|(320|500)41|(750|1000)52)8AS?",
+    "",
+    "A firmware update for this drive may be available,\n"
+    "see the following Seagate web pages:\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/207931en\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/213911en",
+    ""
   },
   { "Maxtor MaXLine Plus II",
     "Maxtor 7Y250[PM]0",
@@ -1426,6 +1646,14 @@ const drive_settings builtin_knowndrives[] = {
     "(Hitachi )?HT[ES]5450(12|16|25|32|40|50)B9A30[01]",
     "", "", ""
   },
+  { "Hitachi/HGST Travelstar Z5K500", // tested with HGST HTS545050A7E380/GG2OAC90
+    "HGST HT[ES]5450(25|32|50)A7E38[01]",
+    "", "", ""
+  },
+  { "Hitachi/HGST Travelstar 5K750", // tested with Hitachi HTS547575A9E384/JE4OA60A
+    "Hitachi HT[ES]5475(50|64|75)A9E38[14]",
+    "", "", ""
+  },
   { "Hitachi Travelstar 7K60",
     "(Hitachi )?HTS726060M9AT00",
     "", "", ""
@@ -1456,7 +1684,11 @@ const drive_settings builtin_knowndrives[] = {
     "", "", ""
   },
   { "Hitachi Travelstar 7K500",
-    "(Hitachi )?HT[ES]7250(12|16|25|32|50)A9A36[45]",
+    "(Hitachi )?HT[ES]7250(12|16|25|32|50)A9A36[2-5]",
+    "", "", ""
+  },
+  { "HGST Travelstar 7K1000", // tested with HGST HTS721010A9E630/JB0OA3B0
+    "HGST HTS721010A9E630",
     "", "", ""
   },
   { "IBM Deskstar 14GXP and 16GP",
@@ -1483,6 +1715,10 @@ const drive_settings builtin_knowndrives[] = {
     "(Hitachi )?HDS5C30(15|20|30)ALA63[02].*",
     "", "", ""
   },
+  { "Hitachi Deskstar 5K4000", // tested with HDS5C4040ALE630/MPAOA250
+    "(Hitachi )?HDS5C40(30|40)ALE63[01].*",
+    "", "", ""
+  },
   { "Hitachi Deskstar 7K80",
     "(Hitachi )?HDS7280([48]0PLAT20|(40)?PLA320|80PLA380).*",
     "", "", ""
@@ -1527,8 +1763,8 @@ const drive_settings builtin_knowndrives[] = {
     "(Hitachi )?HDT7210((16|25)SLA380|(32|50|64|75|10)SLA360)",
     "", "", ""
   },
-  { "Hitachi Deskstar 7K1000.C",
-    "(Hitachi )?HDS7210((16|25)CLA382|(32|50)CLA362|(64|75|10)CLA332)",
+  { "Hitachi Deskstar 7K1000.C", // tested with Hitachi HDS721010CLA330/JP4OA3MA
+    "(Hitachi )?HDS7210((16|25)CLA382|(32|50)CLA362|(64|75|10)CLA33[02])",
     "", "", ""
   },
   { "Hitachi Deskstar 7K1000.D", // tested with HDS721010DLE630/MS2OA5Q0
@@ -1547,6 +1783,10 @@ const drive_settings builtin_knowndrives[] = {
     "Hitachi HDS7230((15|20)BLA642|30ALA640)",
     "", "", ""
   },
+  { "Hitachi/HGST Deskstar 7K4000", // tested with Hitachi HDS724040ALE640/MJAOA250
+    "Hitachi HDS724040ALE640",
+    "", "", ""
+  },
   { "Hitachi Ultrastar A7K1000", // tested with
     // HUA721010KLA330      44X2459 42C0424IBM/GKAOAB4A
     "(Hitachi )?HUA7210(50|75|10)KLA330.*",
@@ -1561,6 +1801,10 @@ const drive_settings builtin_knowndrives[] = {
     "Hitachi HUA7230(20|30)ALA640",
     "", "", ""
   },
+  { "Hitachi Ultrastar 7K4000", // tested with Hitachi HUS724040ALE640/MJAOA3B0
+    "Hitachi HUS7240(20|30|40)ALE640",
+    "", "", ""
+  },
   { "Toshiba 2.5\" HDD (10-20 GB)",
     "TOSHIBA MK(101[67]GAP|15[67]GAP|20(1[678]GAP|(18|23)GAS))",
     "", "", ""
@@ -1573,6 +1817,10 @@ const drive_settings builtin_knowndrives[] = {
     "TOSHIBA MK(80(25GAS|26GAX|32GAX|32GSX)|10(31GAS|32GAX)|12(33GAS|34G[AS]X)|2035GSS)",
     "", "", ""
   },
+  { "Toshiba 2.5\" HDD MK..37GSX", // tested with TOSHIBA MK1637GSX/DL032C
+    "TOSHIBA MK(12|16)37GSX",
+    "", "", ""
+  },
   { "Toshiba 2.5\" HDD MK..50GACY", // tested with TOSHIBA MK8050GACY/TF105A
     "TOSHIBA MK8050GACY",
     "", "", ""
@@ -1581,8 +1829,8 @@ const drive_settings builtin_knowndrives[] = {
     "TOSHIBA MK(80|12|16|25|32)52GSX",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..55GSX", // tested with TOSHIBA MK5055GSX/FG001A
-    "TOSHIBA MK(12|16|25|32|40|50)55GSX",
+  { "Toshiba 2.5\" HDD MK..55GSX", // tested with TOSHIBA MK5055GSX/FG001A, MK3255GSXF/FH115B
+    "TOSHIBA MK(12|16|25|32|40|50)55GSXF?",
     "", "", ""
   },
   { "Toshiba 2.5\" HDD MK..56GSY", // tested with TOSHIBA MK2556GSYF/LJ001D
@@ -1591,16 +1839,20 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,minutes"
   },
-  { "Toshiba 2.5\" HDD MK..59GSXP (Adv. Format)",
+  { "Toshiba 2.5\" HDD MK..59GSXP (AF)",
     "TOSHIBA MK(32|50|64|75)59GSXP?",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..59GSM (Adv. Format)",
+  { "Toshiba 2.5\" HDD MK..59GSM (AF)",
     "TOSHIBA MK(75|10)59GSM",
     "", "", ""
   },
-  { "Toshiba 2.5\" HDD MK..65GSX", // tested with TOSHIBA MK5065GSX/GJ003A
-    "TOSHIBA MK(16|25|32|50|64)65GSX",
+  { "Toshiba 2.5\" HDD MK..61GSYN", // tested with TOSHIBA MK5061GSYN/MH000A
+    "TOSHIBA MK(16|25|32|50|64)61GSYN",
+    "", "", ""
+  },
+  { "Toshiba 2.5\" HDD MK..65GSX", // tested with TOSHIBA MK5065GSX/GJ003A, MK3265GSXN/GH012H
+    "TOSHIBA MK(16|25|32|50|64)65GSXN?",
     "", "", ""
   },
   { "Toshiba 2.5\" HDD MK..76GSX", // tested with TOSHIBA MK3276GSX/GS002D
@@ -1609,6 +1861,10 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-v 9,minutes"
   },
+  { "Toshiba 2.5\" HDD MQ01ABD...", // tested with TOSHIBA MQ01ABD100/AX001U
+    "TOSHIBA MQ01ABD(025|032|050|064|075|100)",
+    "", "", ""
+  },
   { "Toshiba 3.5\" HDD MK.002TSKB", // tested with TOSHIBA MK1002TSKB/MT1A
     "TOSHIBA MK(10|20)02TSKB",
     "", "", ""
@@ -1673,7 +1929,7 @@ const drive_settings builtin_knowndrives[] = {
     "ST9(160316|(250|320)310|(500|640)320)AS",
     "", "", ""
   },
-  { "Seagate Momentus 5400.7 (Adv. Format)", // tested with ST9640322AS/0001BSM2
+  { "Seagate Momentus 5400.7 (AF)", // tested with ST9640322AS/0001BSM2
       // (device reports 4KiB LPS with 1 sector offset)
     "ST9(320312|400321|640322|750423)AS",
     "", "", ""
@@ -1702,6 +1958,10 @@ const drive_settings builtin_knowndrives[] = {
     "ST9((160413|25041[12]|320426|50042[12])AS|(16041[489]|2504[16]4|32042[67]|500426)ASG)",
     "", "", ""
   },
+  { "Seagate Momentus 7200.5", // tested with ST9750420AS/0001SDM5, ST9750420AS/0002SDM1
+    "ST9(50042[34]|64042[012]|75042[02])ASG?",
+    "", "", ""
+  },
   { "Seagate Momentus XT", // fixed firmware
     "ST9(2505610|3205620|5005620)AS",
     "SD2[68]", // http://knowledge.seagate.com/articles/en_US/FAQ/215451en
@@ -1728,6 +1988,14 @@ const drive_settings builtin_knowndrives[] = {
     "http://superuser.com/questions/313447/seagate-momentus-xt-corrupting-files-linux-and-mac",
     ""
   },
+  { "Seagate Momentus XT (AF)", // tested with ST750LX003-1AC154/SM12
+    "ST750LX003-.*",
+    "", "", ""
+  },
+  { "Seagate Momentus Thin", // tested with ST320LT007-9ZV142/0004LVM1
+    "ST(160|250|320)LT0(07|09|11|14)-.*",
+    "", "", ""
+  },
   { "Seagate Medalist 1010, 1720, 1721, 2120, 3230 and 4340",  // ATA2, with -t permissive
     "ST3(1010|1720|1721|2120|3230|4340)A",
     "", "", ""
@@ -1792,8 +2060,8 @@ const drive_settings builtin_knowndrives[] = {
     "ST340015A",
     "", "", ""
   },
-  { "Seagate Barracuda 7200.7 and 7200.7 Plus",
-    "ST3(200021A|200822AS?|16002[13]AS?|12002[26]AS?|1[26]082[78]AS|8001[13]AS?|8081[79]AS|60014A|40111AS|40014AS?)",
+  { "Seagate Barracuda 7200.7 and 7200.7 Plus", // tested with "ST380819AS          39M3701 39M0171 IBM"/3.03
+    "ST3(200021A|200822AS?|16002[13]AS?|12002[26]AS?|1[26]082[78]AS|8001[13]AS?|8081[79]AS|60014A|40111AS|40014AS?)( .* IBM)?",
     "", "", ""
   },
   { "Seagate Barracuda 7200.8",
@@ -1844,10 +2112,95 @@ const drive_settings builtin_knowndrives[] = {
     "http://knowledge.seagate.com/articles/en_US/FAQ/207957en",
     ""
   },
-  { "Seagate Barracuda 7200.12", // tested with ST3250312AS/JC45, ST31000524AS/JC45, ST3500413AS/JC4B
-    "ST3(160318|25031[128]|320418|50041[038]|750(518|52[38])|100052[348])AS",
+  { "Seagate Barracuda 7200.12", // new firmware
+    "ST3(160318|250318|320418|50041[08]|750528|1000528)AS",
+    "CC4[9A-Z]",
+    "", ""
+  },
+  { "Seagate Barracuda 7200.12", // unknown firmware
+    "ST3(160318|250318|320418|50041[08]|750528|1000528)AS",
+    "",
+    "A firmware update for this drive may be available,\n"
+    "see the following Seagate web pages:\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/207931en\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/213891en",
+    ""
+  },
+  { "Seagate Barracuda 7200.12", // tested with ST3250312AS/JC45, ST31000524AS/JC45,
+      // ST3500413AS/JC4B, ST3750525AS/JC4B
+    "ST3(160318|25031[128]|320418|50041[038]|750(518|52[358])|100052[348])AS",
     "", "", ""
   },
+  { "Seagate Barracuda XT", // tested with ST32000641AS/CC13,
+      // ST4000DX000-1C5160/CC42
+    "ST(3(2000641|3000651)AS|4000DX000-.*)",
+    "", "", ""
+  },
+  { "Seagate Barracuda 7200.14 (AF)", // new firmware, tested with
+      // ST3000DM001-9YN166/CC4H, ST3000DM001-9YN166/CC9E
+    "ST(1000|1500|2000|2500|3000)DM00[1-3]-.*",
+    "CC(4[H-Z]|[5-9A-Z]..*)", // >= "CC4H"
+    "",
+    "-v 188,raw16 -v 240,msec24hour32" // tested with ST3000DM001-9YN166/CC4H
+  },
+  { "Seagate Barracuda 7200.14 (AF)", // old firmware, tested with
+      // ST1000DM003-9YN162/CC46
+    "ST(1000|1500|2000|2500|3000)DM00[1-3]-.*",
+    "CC4[679CG]",
+    "A firmware update for this drive is available,\n"
+    "see the following Seagate web pages:\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/207931en\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/223651en",
+    "-v 188,raw16 -v 240,msec24hour32"
+  },
+  { "Seagate Barracuda 7200.14 (AF)", // unknown firmware
+    "ST(1000|1500|2000|2500|3000)DM00[1-3]-.*",
+    "",
+    "A firmware update for this drive may be available,\n"
+    "see the following Seagate web pages:\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/207931en\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/223651en",
+    "-v 188,raw16 -v 240,msec24hour32"
+  },
+  { "Seagate Barracuda 7200.14 (AF)", // < 1TB, tested with ST250DM000-1BC141
+    "ST(250|320|500|750)DM00[0-3]-.*",
+    "", "",
+    "-v 188,raw16 -v 240,msec24hour32"
+  },
+  { "Seagate Desktop HDD.15", // tested with ST4000DM000-1CD168/CC43
+    "ST4000DM000-.*",
+    "", "",
+    "-v 188,raw16 -v 240,msec24hour32"
+  },
+  { "Seagate Barracuda LP", // new firmware
+    "ST3(500412|1000520|1500541|2000542)AS",
+    "CC3[5-9A-Z]",
+    "",
+    "" // -F xerrorlba ?
+  },
+  { "Seagate Barracuda LP", // unknown firmware
+    "ST3(500412|1000520|1500541|2000542)AS",
+    "",
+    "A firmware update for this drive may be available,\n"
+    "see the following Seagate web pages:\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/207931en\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/213915en",
+    "-F xerrorlba" // tested with ST31000520AS/CC32
+  },
+  { "Seagate Barracuda Green (AF)", // new firmware
+    "ST((10|15|20)00DL00[123])-.*",
+    "CC3[2-9A-Z]",
+    "", ""
+  },
+  { "Seagate Barracuda Green (AF)", // unknown firmware
+    "ST((10|15|20)00DL00[123])-.*",
+    "",
+    "A firmware update for this drive may be available,\n"
+    "see the following Seagate web pages:\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/207931en\n"
+    "http://knowledge.seagate.com/articles/en_US/FAQ/218171en",
+    ""
+  },
   { "Seagate Barracuda ES",
     "ST3(250[68]2|32062|40062|50063|75064)0NS",
     "", "", ""
@@ -1856,7 +2209,8 @@ const drive_settings builtin_knowndrives[] = {
     "ST3(25031|50032|75033|100034)0NS",
     "SN[01]6|"         // http://knowledge.seagate.com/articles/en_US/FAQ/207963en
     "MA(0[^7]|[^0].)", // http://dellfirmware.seagate.com/dell_firmware/DellFirmwareRequest.jsp
-    "", ""
+    "",
+    "-F xerrorlba" // tested with ST31000340NS/SN06
   },
   { "Seagate Barracuda ES.2", // buggy firmware (Dell)
     "ST3(25031|50032|75033|100034)0NS",
@@ -1876,23 +2230,6 @@ const drive_settings builtin_knowndrives[] = {
     "http://knowledge.seagate.com/articles/en_US/FAQ/207963en",
     ""
   },
-  { "Seagate Barracuda LP",
-    "ST3(500412|1000520|1500541|2000542)AS",
-    "", "", ""
-  },
-  { "Seagate Barracuda Green (Adv. Format)",
-    "ST((10|15|20)00DL00[123])-.*",
-    "", "", ""
-  },
-  { "Seagate Barracuda XT", // tested with ST32000641AS/CC13,
-      // ST4000DX000-1C5160/CC42
-    "ST(3(2000641|3000651)AS|4000DX000-.*)",
-    "", "", ""
-  },
-  { "Seagate Barracuda (SATA 3Gb/s, 4K Sectors)", // tested with ST250DM000-1BC141
-    "ST(3000|2000|1500|750|500|320|250)DM00[012]-.*",
-    "", "", ""
-  },
   { "Seagate Constellation (SATA)", // tested with ST9500530NS/SN03
     "ST9(160511|500530)NS",
     "", "", ""
@@ -1953,6 +2290,10 @@ const drive_settings builtin_knowndrives[] = {
     "ST3(750640SCE|((80|160)215|(250|320|400)820|500830|750840)[AS]CE)",
     "", "", ""
   },
+  { "Seagate LD25.2", // tested with ST940210AS/3.ALC
+    "ST9(40|80)210AS?",
+    "", "", ""
+  },
   { "Seagate ST1.2 CompactFlash", // tested with ST68022CF/3.01
     "ST6[468]022CF",
     "", "", ""
@@ -2074,7 +2415,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD((25|32|50|75)02A|(75|10)02F)BYS-.*",
     "", "", ""
   },
-  { "Western Digital RE4 Serial ATA",
+  { "Western Digital RE4", // tested with WDC WD2003FYYS-18W0B0/01.01D02
     "WDC WD((((25|50)03A|1003F)BYX)|((15|20)03FYYS))-.*",
     "", "", ""
   },
@@ -2082,25 +2423,37 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD2002FYPS-.*",
     "", "", ""
   },
+  { "Western Digital RE4 (SATA 6Gb/s)", // tested with WDC WD2000FYYZ-01UL1B0/01.01K01
+    "WDC WD(20|30|40)00FYYZ-.*",
+    "", "", ""
+  },
   { "Western Digital Caviar Green",
     "WDC WD((50|64|75)00AA(C|V)S|(50|64|75)00AADS|10EA(C|V)S|(10|15|20)EADS)-.*",
-    "", "", ""
+    "",
+    "",
+    "-F xerrorlba" // tested with WDC WD7500AADS-00M2B0/01.00A01
   },
-  { "Western Digital Caviar Green (Adv. Format)",
+  { "Western Digital Caviar Green (AF)",
     "WDC WD(((64|75|80)00AA|(10|15|20)EA|(25|30)EZ)R|20EAC)S-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Green (Adv. Format)", // SATA 6Gb/s variants
-      // tested with WDC WD30EZRX-00MMMB0/80.00A80
-    "WDC WD(7500AA|(10|15|20)EA|(25|30)EZ)RX-.*",
+  { "Western Digital Caviar Green (AF, SATA 6Gb/s)", // tested with
+      // WDC WD10EZRX-00A8LB0/01.01A01, WDC WD20EZRX-00DC0B0/80.00A80,
+      // WDC WD30EZRX-00MMMB0/80.00A80
+    "WDC WD(7500AA|(10|15|20)EA|(10|20|25|30)EZ)RX-.*",
     "", "", ""
   },
   { "Western Digital Caviar Black",
     "WDC WD((500|640|750)1AAL|1001FA[EL]|2001FAS)S-.*",
     "", "", ""
   },
-  { "Western Digital Caviar Black",  // SATA 3.0 variants
-    "WDC WD(5002AAL|(64|75)02AAE|(10|15|20)02FAE)X-.*",
+  { "Western Digital Caviar Black",  // SATA 6 Gb/s variants, tested with
+      //  WDC WD4001FAEX-00MJRA0/01.01L01
+    "WDC WD(5002AAL|(64|75)02AAE|((10|15|20)02|4001)FAE)X-.*",
+    "", "", ""
+  },
+  { "Western Digital Caviar Black (AF)", // tested with WDC WD5003AZEX-00RKKA0/80.00A80
+    "WDC WD(5003AZE)X-.*",
     "", "", ""
   },
   { "Western Digital AV ATA", // tested with WDC WD3200AVJB-63J5A0/01.03E01
@@ -2115,7 +2468,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD((16|25|32|50|64|75)00AV[CDV]S|(10|15|20)EV[CDV]S)-.*",
     "", "", ""
   },
-  { "Western Digital AV-GP (Adv. Format)", // tested with WDC WD10EURS-630AB1/80.00A80, WDC WD10EUCX-63YZ1Y0/51.0AB52
+  { "Western Digital AV-GP (AF)", // tested with WDC WD10EURS-630AB1/80.00A80, WDC WD10EUCX-63YZ1Y0/51.0AB52
     "WDC WD(7500AURS|10EU[CR]X|(10|15|20|25|30)EURS)-.*",
     "", "", ""
   },
@@ -2135,6 +2488,10 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(((800H|(1500|3000)[BH]|1600H|3000G)LFS)|((1500|3000|4500|6000)[BH]LHX))-.*",
     "", "", ""
   },
+  { "Western Digital VelociRaptor (AF)", // tested with WDC WD1000DHTZ-04N21V0/04.06A00
+    "WDC WD(2500H|5000H|1000D)HTZ-.*",
+    "", "", ""
+  },
   { "Western Digital Scorpio EIDE",
     "WDC WD(4|6|8|10|12|16)00(UE|VE)-.*",
     "", "", ""
@@ -2151,7 +2508,7 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD((4|6|8|10|12|16|25)00BEVS|(8|12|16|25|32|40|50|64)00BEVT|7500KEVT|10TEVT)-.*",
     "", "", ""
   },
-  { "Western Digital Scorpio Blue Serial ATA (Adv. Format)", // tested with
+  { "Western Digital Scorpio Blue Serial ATA (AF)", // tested with
       // WDC WD10JPVT-00A1YT0/01.01A01
     "WDC WD((16|25|32|50|64|75)00BPVT|10[JT]PVT)-.*",
     "", "", ""
@@ -2160,22 +2517,22 @@ const drive_settings builtin_knowndrives[] = {
     "WDC WD(8|12|16|25|32|50)00B[EJ]KT-.*",
     "", "", ""
   },
-  { "Western Digital Scorpio Black (Adv. Format)",
+  { "Western Digital Scorpio Black (AF)",
     "WDC WD(50|75)00BPKT-.*",
     "", "", ""
   },
-  { "Western Digital My Passport Essential (USB)",
-    "WDC WD(25|32|40|50)00BMVU-.*",
+  { "Western Digital Red (AF)", // tested with WDC WD10EFRX-68JCSN0/01.01A01
+    "WDC WD(10|20|30)EFRX-.*",
     "", "", ""
   },
-  { "Western Digital My Passport Essential SE (USB, Adv. Format)", // tested with
-      // WDC WD10TMVW-11ZSMS5/01.01A01
-    "WDC WD(7500K|10T)MV[VW]-.*",
+  { "Western Digital My Passport (USB)", // tested with WDC WD5000BMVW-11AMCS0/01.01A01
+    "WDC WD(25|32|40|50)00BMV[UVW]-.*",  // *W-* = USB 3.0
     "", "", ""
   },
-  { "Western Digital My Passport (USB)", // tested with
-      // WDC WD5000BMVW-11AMCS0/01.01A01
-    "WDC WD(3200BMVV|5000BMVW)-.*",
+  { "Western Digital My Passport (USB, AF)", // tested with
+      // WDC WD5000KMVV-11TK7S1/01.01A01, WDC WD10TMVW-11ZSMS5/01.01A01,
+      // WDC WD10JMVW-11S5XS1/01.01A01, WDC WD20NMVW-11W68S0/01.01A01
+    "WDC WD(5000[LK]|7500K|10[JT]|20N)MV[VW]-.*", // *W-* = USB 3.0
     "", "", ""
   },
   { "Quantum Bigfoot", // tested with TS10.0A/A21.0G00, TS12.7A/A21.0F00
@@ -2198,8 +2555,8 @@ const drive_settings builtin_knowndrives[] = {
     "QUANTUM FIREBALL CR(4.3|6.4|8.4|13.0)A",
     "", "", ""
   },
-  { "Quantum Fireball EX",
-    "QUANTUM FIREBALL EX(3.2|6.4)A",
+  { "Quantum Fireball EX", // tested with QUANTUM FIREBALL EX10.2A/A0A.0D00
+    "QUANTUM FIREBALL EX(3\\.2|6\\.4|10\\.2)A",
     "", "", ""
   },
   { "Quantum Fireball ST",
@@ -2280,12 +2637,18 @@ const drive_settings builtin_knowndrives[] = {
     "-d sat"
   },
   // Toshiba
-  { "USB: Toshiba Canvio 500GB; ",
+  { "USB: Toshiba Canvio 500GB; SunPlus",
     "0x0480:0xa004",
     "",
     "",
     "-d usbsunplus"
   },
+  { "USB: Toshiba Canvio Basics; ",
+    "0x0480:0xa006",
+    "", // 0x0001
+    "",
+    "-d sat"
+  },
   // Cypress
   { "USB: ; Cypress CY7C68300A (AT2)",
     "0x04b4:0x6830",
@@ -2299,6 +2662,13 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbcypress"
   },
+  // Fujitsu
+  { "USB: Fujitsu/Zalman ZM-VE300; ", // USB 3.0
+    "0x04c5:0x2028",
+    "", // 0x0001
+    "",
+    "-d sat"
+  },
   // Myson Century
   { "USB: ; Myson Century CS8818",
     "0x04cf:0x8818",
@@ -2349,6 +2719,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: Samsung M3 Portable USB 3.0; ", // 1TB
+    "0x04e8:0x61b6",
+    "", // 0x0e00
+    "",
+    "-d sat"
+  },
   // Sunplus
   { "USB: ; SunPlus",
     "0x04fc:0x0c05",
@@ -2466,6 +2842,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: LaCie Rugged Mini USB 3.0; ",
+    "0x059f:0x1051",
+    "", // 0x0000
+    "",
+    "-d sat"
+  },
   // In-System Design
   { "USB: ; In-System/Cypress ISD-300A1",
     "0x05ab:0x0060",
@@ -2504,7 +2886,14 @@ const drive_settings builtin_knowndrives[] = {
     "0x067b:0x3507",
     "", // 0x0001
     "",
-    "" // unsupported
+    "-d usbjmicron,p"
+  },
+  // Imation
+  { "USB: Imation ; ", // Imation Odyssey external USB dock
+    "0x0718:0x1000",
+    "", // 0x5104
+    "",
+    "-d sat"
   },
   // Freecom
   { "USB: Freecom Mobile Drive XXS; JMicron",
@@ -2537,19 +2926,6 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbjmicron"
   },
-  // Toshiba
-  { "USB: Toshiba PX1270E-1G16; Sunplus",
-    "0x0930:0x0b03",
-    "",
-    "",
-    "-d usbsunplus"
-  },
-  { "USB: Toshiba STOR.E; ",
-    "0x0930:0x0b1b",
-    "", // 0x0001
-    "",
-    "-d sat"
-  },
   // Oxford Semiconductor, Ltd
   { "USB: ; Oxford",
     "0x0928:0x0000",
@@ -2563,7 +2939,19 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "" // unsupported
   },
-  // Toshiba Corp.
+  { "USB: ; Oxford", // Zalman ZM-VE200
+    "0x0928:0x0010",
+    "", // 0x0304
+    "",
+    "-d sat"
+  },
+  // Toshiba
+  { "USB: Toshiba PX1270E-1G16; Sunplus",
+    "0x0930:0x0b03",
+    "",
+    "",
+    "-d usbsunplus"
+  },
   { "USB: Toshiba PX1396E-3T01; Sunplus", // similar to Dura Micro 501
     "0x0930:0x0b09",
     "",
@@ -2576,6 +2964,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbsunplus"
   },
+  { "USB: Toshiba Stor.E; ",
+    "0x0930:0x0b1[9ab]",
+    "", // 0x0001
+    "",
+    "-d sat"
+  },
   // Lumberg, Inc.
   { "USB: Toshiba Stor.E; Sunplus",
     "0x0939:0x0b16",
@@ -2584,6 +2978,12 @@ const drive_settings builtin_knowndrives[] = {
     "-d usbsunplus"
   },
   // Seagate
+  { "USB: Seagate External Drive; Cypress",
+    "0x0bc2:0x0503",
+    "", // 0x0240
+    "",
+    "-d usbcypress"
+  },
   { "USB: Seagate FreeAgent Go; ",
     "0x0bc2:0x2(000|100|101)",
     "",
@@ -2656,6 +3056,18 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: Seagate Backup Plus USB 3.0; ", // 1TB
+    "0x0bc2:0xa013",
+    "", // 0x0100
+    "",
+    "-d sat"
+  },
+  { "USB: Seagate Backup Plus Desktop USB 3.0; ", // 3TB, 8 LBA/1 PBA offset
+    "0x0bc2:0xa0a4",
+    "",
+    "",
+    "-d sat"
+  },
   // Dura Micro
   { "USB: Dura Micro; Cypress",
     "0x0c0b:0xb001",
@@ -2777,7 +3189,7 @@ const drive_settings builtin_knowndrives[] = {
     "-d sat"
   },
   { "USB: WD My Passport USB 3.0; ",
-    "0x1058:0x0748",
+    "0x1058:0x07[4a]8",
     "",
     "",
     "-d sat"
@@ -2848,6 +3260,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: WD My Book Studio II; ", // 2x1TB
+    "0x1058:0x1105",
+    "",
+    "",
+    "-d sat"
+  },
   { "USB: WD My Book Essential; ",
     "0x1058:0x1110",
     "", // 0x1030
@@ -2874,6 +3292,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbcypress"
   },
+  { "USB: A-DATA DashDrive; Cypress",
+    "0x125f:0xa94a",
+    "",
+    "",
+    "-d usbcypress"
+  },
   // Initio
   { "USB: ; Initio 316000",
     "0x13fd:0x0540",
@@ -2887,6 +3311,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d sat"
   },
+  { "USB: ; Initio", // USB->SATA+PATA, Chieftec CEB-25I
+    "0x13fd:0x1040",
+    "", // 0x0106
+    "",
+    "" // unsupported
+  },
   { "USB: ; Initio 6Y120L0", // CoolerMaster XCraft RX-3HU
     "0x13fd:0x1150",
     "",
@@ -2993,20 +3423,22 @@ const drive_settings builtin_knowndrives[] = {
   },
   // ASMedia
   { "USB: ; ASMedia ASM1051",
-    "0x174c:0x5106",
+    "0x174c:0x5106", // 0x174c:0x55aa after firmware update
     "",
     "",
     "-d sat"
   },
-  { "USB: ; ASMedia USB 3.0", // BYTECC T-200U3
+  { "USB: ; ASMedia USB 3.0", // MEDION HDDrive-n-GO, LaCie Rikiki USB 3.0,
+      // Silicon Power Armor A80 (ticket #237)
+      // reported as unsupported: BYTECC T-200U3, Kingwin USB 3.0 docking station
     "0x174c:0x55aa",
+    "", // 0x0100
     "",
-    "",
-    "" // unsupported
+    "-d sat"
   },
   // LucidPort
-  { "USB: RaidSonic ICY BOX IB-110StU3-B; LucidPORT USB300",
-    "0x1759:0x500[02]",
+  { "USB: ; LucidPORT USB300", // RaidSonic ICY BOX IB-110StU3-B, Sharkoon SATA QuickPort H3
+    "0x1759:0x500[02]", // 0x5000: USB 2.0, 0x5002: USB 3.0
     "",
     "",
     "-d sat"
@@ -3042,6 +3474,12 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbjmicron"
   },
+  { "USB: Verbatim Store'n'Go; JMicron", // USB->SATA
+    "0x18a5:0x022b",
+    "", // 0x0100
+    "",
+    "-d usbjmicron"
+  },
   // Silicon Image
   { "USB: Vantec NST-400MX-SR; Silicon Image 5744",
     "0x1a4a:0x1670",
@@ -3056,13 +3494,20 @@ const drive_settings builtin_knowndrives[] = {
     "",
     "-d usbsunplus"
   },
-  // Unknown: 0x1f75
-  { "USB: Sharkoon SATA QuickDeck Pro; ", // USB 2.0/3.0
+  // Innostor
+  { "USB: ; Innostor IS888", // Sharkoon SATA QuickDeck Pro USB 3.0
     "0x1f75:0x0888",
     "", // 0x0034
     "",
     "" // unsupported
   },
+  // Power Quotient International
+  { "USB: PQI H560; ",
+    "0x3538:0x0902",
+    "", // 0x0000
+    "",
+    "-d sat"
+  },
   // Hitachi/SimpleTech
   { "USB: Hitachi Touro Desk; JMicron", // 3TB
     "0x4971:0x1011",
index 0d855addd3711911f0437feffa4d5802cccdfcc9..dfeccfec5bd6ab4a3d962b09d8978ac9f56f5e2e 100644 (file)
@@ -1,6 +1,6 @@
 # Home page: http://smartmontools.sourceforge.net
 #
-# $Id: README,v 1.7 2008/03/04 22:09:47 ballen4705 Exp $
+# $Id: README 3728 2012-12-13 17:57:50Z chrfranke $
 #
 # Copyright (C) 2003-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 # 
@@ -10,8 +10,8 @@
 # version.
 # 
 # You should have received a copy of the GNU General Public License (for
-# example COPYING); if not, write to the Free Software Foundation, Inc., 675
-# Mass Ave, Cambridge, MA 02139, USA.
+# example COPYING); if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, 02110-1301 USA.
 #
 # This code was originally developed as a Senior Thesis by Michael Cornwell
 # at the Concurrent Systems Laboratory (now part of the Storage Systems
index 2aad1f2ec0f4efe63d444ce14e56a8d7d220cf79..b61ab8e014f3b5e6a274b8a0307de4b6aa4eb94e 100644 (file)
@@ -18,9 +18,9 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-\f
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
+
 /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
    Ditto for AIX 3.2 and <stdlib.h>.  */
 #ifndef _NO_PROTO
index 4283c35b168acb3a4a4770cd6f646797478128ab..c4f1ea48db14db668ebc2aa304077c379b87d859 100644 (file)
@@ -14,8 +14,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 #ifndef _GETOPT_H
 
diff --git a/int64.h b/int64.h
index b346bd916d779c24c219f4b2fb5303b87713e8e8..bc328ab850120a8113f3f4191c9d2d929f3a7724 100644 (file)
--- a/int64.h
+++ b/int64.h
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
 #ifndef INT64_H_
 #define INT64_H_
 
-#define INT64_H_CVSID "$Id: int64.h 3475 2011-11-10 21:43:40Z chrfranke $"
+#define INT64_H_CVSID "$Id: int64.h 3727 2012-12-13 17:23:06Z samm2 $"
 
 // 64 bit integer typedefs and format strings
 
index 422b8654eebb499117fc3ab0ded0a840f3c183f9..25d3babcb7d0a321ea1161245ebc50c97bf4ee18 100644 (file)
@@ -5,7 +5,7 @@
  * Address of support mailing list: smartmontools-support@lists.sourceforge.net
  *
  * Copyright (C) 2003-11 Philip Williams, Bruce Allen
- * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-12 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
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
@@ -34,7 +33,7 @@
 
 #include <stdexcept>
 
-const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 3447 2011-10-14 20:32:00Z chrfranke $"
+const char * knowndrives_cpp_cvsid = "$Id: knowndrives.cpp 3719 2012-12-03 21:19:33Z chrfranke $"
                                      KNOWNDRIVES_H_CVSID;
 
 #define MODEL_STRING_LENGTH                         40
@@ -124,14 +123,16 @@ void drive_database::push_back(const drive_settings & src)
 
 const char * drive_database::copy_string(const char * src)
 {
-  char * dest = new char[strlen(src)+1];
+  size_t len = strlen(src);
+  char * dest = new char[len+1];
+  memcpy(dest, src, len+1);
   try {
     m_custom_strings.push_back(dest);
   }
   catch (...) {
     delete [] dest; throw;
   }
-  return strcpy(dest, src);
+  return dest;
 }
 
 
@@ -208,7 +209,7 @@ static const drive_settings * lookup_drive(const char * model, const char * firm
 
 // Parse drive or USB options in preset string, return false on error.
 static bool parse_db_presets(const char * presets, ata_vendor_attr_defs * defs,
-                             unsigned char * fix_firmwarebug, std::string * type)
+                             firmwarebug_defs * firmwarebugs, std::string * type)
 {
   for (int i = 0; ; ) {
     i += strspn(presets+i, " \t");
@@ -222,19 +223,13 @@ static bool parse_db_presets(const char * presets, ata_vendor_attr_defs * defs,
       if (!parse_attribute_def(arg, *defs, PRIOR_DATABASE))
         return false;
     }
-    else if (opt == 'F' && fix_firmwarebug) {
-      unsigned char fix;
-      if (!strcmp(arg, "samsung"))
-        fix = FIX_SAMSUNG;
-      else if (!strcmp(arg, "samsung2"))
-        fix = FIX_SAMSUNG2;
-      else if (!strcmp(arg, "samsung3"))
-        fix = FIX_SAMSUNG3;
-      else
+    else if (opt == 'F' && firmwarebugs) {
+      firmwarebug_defs bug;
+      if (!parse_firmwarebug_def(arg, bug))
         return false;
-      // Set only if not set by user
-      if (*fix_firmwarebug == FIX_NOTSPECIFIED)
-        *fix_firmwarebug = fix;
+      // Don't set if user specified '-F none'.
+      if (!firmwarebugs->is_set(BUG_NONE))
+        firmwarebugs->set(bug);
     }
     else if (opt == 'd' && type) {
         // TODO: Check valid types
@@ -251,9 +246,9 @@ static bool parse_db_presets(const char * presets, ata_vendor_attr_defs * defs,
 // Parse '-v' and '-F' options in preset string, return false on error.
 static inline bool parse_presets(const char * presets,
                                  ata_vendor_attr_defs & defs,
-                                 unsigned char & fix_firmwarebug)
+                                 firmwarebug_defs & firmwarebugs)
 {
-  return parse_db_presets(presets, &defs, &fix_firmwarebug, 0);
+  return parse_db_presets(presets, &defs, &firmwarebugs, 0);
 }
 
 // Parse '-d' option in preset string, return false on error.
@@ -365,11 +360,11 @@ static int showonepreset(const drive_settings * dbentry)
     pout("%-*s %s\n", TABLEPRINTWIDTH, "MODEL FAMILY:", dbentry->modelfamily);
 
     // if there are any presets, then show them
-    unsigned char fix_firmwarebug = 0;
+    firmwarebug_defs firmwarebugs;
     bool first_preset = true;
     if (*dbentry->presets) {
       ata_vendor_attr_defs defs;
-      if (!parse_presets(dbentry->presets, defs, fix_firmwarebug)) {
+      if (!parse_presets(dbentry->presets, defs, firmwarebugs)) {
         pout("Syntax error in preset option string \"%s\"\n", dbentry->presets);
         errcnt++;
       }
@@ -393,18 +388,26 @@ static int showonepreset(const drive_settings * dbentry)
       pout("%-*s %s\n", TABLEPRINTWIDTH, "ATTRIBUTE OPTIONS:", "None preset; no -v options are required.");
 
     // describe firmwarefix
-    if (fix_firmwarebug) {
+    for (int b = BUG_NOLOGDIR; b <= BUG_XERRORLBA; b++) {
+      if (!firmwarebugs.is_set((firmwarebug_t)b))
+        continue;
       const char * fixdesc;
-      switch (fix_firmwarebug) {
-        case FIX_SAMSUNG:
+      switch ((firmwarebug_t)b) {
+        case BUG_NOLOGDIR:
+          fixdesc = "Avoids reading GP/SMART Log Directories (same as -F nologdir)";
+          break;
+        case BUG_SAMSUNG:
           fixdesc = "Fixes byte order in some SMART data (same as -F samsung)";
           break;
-        case FIX_SAMSUNG2:
+        case BUG_SAMSUNG2:
           fixdesc = "Fixes byte order in some SMART data (same as -F samsung2)";
           break;
-        case FIX_SAMSUNG3:
+        case BUG_SAMSUNG3:
           fixdesc = "Fixes completed self-test reported as in progress (same as -F samsung3)";
           break;
+        case BUG_XERRORLBA:
+          fixdesc = "Fixes LBA byte ordering in Ext. Comprehensive SMART error log (same as -F xerrorlba)";
+          break;
         default:
           fixdesc = "UNKNOWN"; errcnt++;
           break;
@@ -525,12 +528,12 @@ void show_presets(const ata_identify_device * drive)
 }
 
 // Searches drive database and sets preset vendor attribute
-// options in defs and fix_firmwarebug.
+// options in defs and firmwarebugs.
 // Values that have already been set will not be changed.
 // Returns pointer to database entry or nullptr if none found
 const drive_settings * lookup_drive_apply_presets(
   const ata_identify_device * drive, ata_vendor_attr_defs & defs,
-  unsigned char & fix_firmwarebug)
+  firmwarebug_defs & firmwarebugs)
 {
   // get the drive's model/firmware strings
   char model[MODEL_STRING_LENGTH+1], firmware[FIRMWARE_STRING_LENGTH+1];
@@ -544,7 +547,7 @@ const drive_settings * lookup_drive_apply_presets(
 
   if (*dbentry->presets) {
     // Apply presets
-    if (!parse_presets(dbentry->presets, defs, fix_firmwarebug))
+    if (!parse_presets(dbentry->presets, defs, firmwarebugs))
       pout("Syntax error in preset option string \"%s\"\n", dbentry->presets);
   }
   return dbentry;
@@ -765,7 +768,7 @@ static bool parse_drive_database(parse_ptr src, drive_database & db, const char
           case 4:
             if (!token.value.empty()) {
               if (!is_usb_modelfamily(values[0].c_str())) {
-                ata_vendor_attr_defs defs; unsigned char fix = 0;
+                ata_vendor_attr_defs defs; firmwarebug_defs fix;
                 if (!parse_presets(token.value.c_str(), defs, fix)) {
                   pout("%s(%d): Syntax error in preset option string\n", path, token.line);
                   ok = false;
index 457884988369c8e7960cc09b93f3b8ac432df308..7d2a8cc18a1ba0f866431293f03989ff58295d34 100644 (file)
@@ -5,7 +5,7 @@
  * Address of support mailing list: smartmontools-support@lists.sourceforge.net
  *
  * Copyright (C) 2003-11 Philip Williams, Bruce Allen
- * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-12 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
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 #ifndef KNOWNDRIVES_H_
 #define KNOWNDRIVES_H_
 
-#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 3288 2011-03-09 18:40:36Z chrfranke $\n"
+#define KNOWNDRIVES_H_CVSID "$Id: knowndrives.h 3597 2012-09-04 21:10:37Z chrfranke $\n"
 
 // Structure to store drive database entries, see drivedb.h for a description.
 struct drive_settings {
@@ -56,12 +55,12 @@ int showallpresets();
 int showmatchingpresets(const char *model, const char *firmware);
 
 // Searches drive database and sets preset vendor attribute
-// options in defs and fix_firmwarebug.
+// options in defs and firmwarebugs.
 // Values that have already been set will not be changed.
 // Returns pointer to database entry or nullptr if none found.
 const drive_settings * lookup_drive_apply_presets(
   const ata_identify_device * drive, ata_vendor_attr_defs & defs,
-  unsigned char & fix_firmwarebug);
+  firmwarebug_defs & firmwarebugs);
 
 // Get path for additional database file
 const char * get_drivedb_path_add();
index b1f398d63acaaf312e5f35bfef0a8450588b4425..9c2bf6e8e5e47d76ddfaf93398da56342ced17ed 100644 (file)
@@ -8,14 +8,14 @@ int megaraid_io_interface(int device, int target, struct scsi_cmnd_io *, int);
 #define u64 uint64_t
 
 /*======================================================
- * PERC2/3/4 Passthrough SCSI Command Interface
- *
- * Contents from:
- *  drivers/scsi/megaraid/megaraid_ioctl.h
- *  drivers/scsi/megaraid/mbox_defs.h
- *======================================================*/
-#define MEGAIOC_MAGIC          'm'
-#define MEGAIOCCMD             _IOWR(MEGAIOC_MAGIC, 0, struct uioctl_t)
+* PERC2/3/4 Passthrough SCSI Command Interface
+*
+* Contents from:
+*  drivers/scsi/megaraid/megaraid_ioctl.h
+*  drivers/scsi/megaraid/mbox_defs.h
+*======================================================*/
+#define MEGAIOC_MAGIC   'm'
+#define MEGAIOCCMD      _IOWR(MEGAIOC_MAGIC, 0, struct uioctl_t)
 
 /* Following subopcode work for opcode == 0x82 */
 #define MKADAP(adapno)   (MEGAIOC_MAGIC << 8 | adapno)
@@ -30,42 +30,42 @@ int megaraid_io_interface(int device, int target, struct scsi_cmnd_io *, int);
 
 typedef struct
 {
-       uint8_t  timeout : 3;
-       uint8_t  ars : 1;
-       uint8_t  reserved : 3;
-       uint8_t  islogical : 1;
-       uint8_t  logdrv;
-       uint8_t  channel;
-       uint8_t  target;
-       uint8_t  queuetag;
-       uint8_t  queueaction;
-       uint8_t  cdb[MAX_CDB_LEN];
-       uint8_t  cdblen;
-       uint8_t  reqsenselen;
-       uint8_t  reqsensearea[MAX_REQ_SENSE_LEN];
-       uint8_t  numsgelements;
-       uint8_t  scsistatus;
-       uint32_t dataxferaddr;
-       uint32_t dataxferlen;
+  uint8_t  timeout : 3;
+  uint8_t  ars : 1;
+  uint8_t  reserved : 3;
+  uint8_t  islogical : 1;
+  uint8_t  logdrv;
+  uint8_t  channel;
+  uint8_t  target;
+  uint8_t  queuetag;
+  uint8_t  queueaction;
+  uint8_t  cdb[MAX_CDB_LEN];
+  uint8_t  cdblen;
+  uint8_t  reqsenselen;
+  uint8_t  reqsensearea[MAX_REQ_SENSE_LEN];
+  uint8_t  numsgelements;
+  uint8_t  scsistatus;
+  uint32_t dataxferaddr;
+  uint32_t dataxferlen;
 } __attribute__((packed)) mega_passthru;
 
 typedef struct
 {
-       uint8_t   cmd;
-       uint8_t   cmdid;
-       uint8_t   opcode;
-       uint8_t   subopcode;
-       uint32_t  lba;
-       uint32_t  xferaddr;
-       uint8_t   logdrv;
-       uint8_t   resvd[3];
-       uint8_t   numstatus;
-       uint8_t   status;
+  uint8_t   cmd;
+  uint8_t   cmdid;
+  uint8_t   opcode;
+  uint8_t   subopcode;
+  uint32_t  lba;
+  uint32_t  xferaddr;
+  uint8_t   logdrv;
+  uint8_t   resvd[3];
+  uint8_t   numstatus;
+  uint8_t   status;
 } __attribute__((packed)) megacmd_t;
 
 typedef union {
-       uint8_t   *pointer;
-       uint8_t    pad[8];
+  uint8_t   *pointer;
+  uint8_t    pad[8];
 } ptr_t;
 
 // The above definition assumes sizeof(void*) <= 8.
@@ -79,151 +79,177 @@ typedef char assert_sizeof_ptr_t[sizeof(ptr_t) == 8 ? 1 : -1];
 
 struct uioctl_t
 {
-       uint32_t       inlen;
-       uint32_t       outlen;
-       union {
-               uint8_t      fca[16];
-               struct {
-                       uint8_t  opcode;
-                       uint8_t  subopcode;
-                       uint16_t adapno;
-                       ptr_t    buffer;
-                       uint32_t length;
-               } __attribute__((packed)) fcs;
-       } __attribute__((packed)) ui;
-
-       megacmd_t     mbox;
-       mega_passthru pthru;
-       ptr_t         data;
+  uint32_t       inlen;
+  uint32_t       outlen;
+  union {
+    uint8_t      fca[16];
+    struct {
+      uint8_t  opcode;
+      uint8_t  subopcode;
+      uint16_t adapno;
+      ptr_t    buffer;
+      uint32_t length;
+    } __attribute__((packed)) fcs;
+  } __attribute__((packed)) ui;
+  
+  megacmd_t     mbox;
+  mega_passthru pthru;
+  ptr_t         data;
 } __attribute__((packed));
 
 /*===================================================
- * PERC5/6 Passthrough SCSI Command Interface
- *
- * Contents from:
- *  drivers/scsi/megaraid/megaraid_sas.h
- *===================================================*/
+* PERC5/6 Passthrough SCSI Command Interface
+*
+* Contents from:
+*  drivers/scsi/megaraid/megaraid_sas.h
+*===================================================*/
 #define MEGASAS_MAGIC          'M'
 #define MEGASAS_IOC_FIRMWARE   _IOWR(MEGASAS_MAGIC, 1, struct megasas_iocpacket)
 
 #define MFI_CMD_PD_SCSI_IO        0x04
+#define MFI_CMD_DCMD              0x05
 #define MFI_FRAME_SGL64           0x02
-#define MFI_FRAME_DIR_READ        0x10 
-
-#define MAX_IOCTL_SGE                  16
+#define MFI_STAT_OK               0x00
+#define MFI_DCMD_PD_GET_LIST      0x02010000
+/*
+* Number of mailbox bytes in DCMD message frame
+*/
+#define MFI_MBOX_SIZE             12
+#define MAX_IOCTL_SGE             16
+#define MFI_FRAME_DIR_NONE        0x0000
+#define MFI_FRAME_DIR_WRITE       0x0008
+#define MFI_FRAME_DIR_READ        0x0010
+#define MFI_FRAME_DIR_BOTH        0x0018
+
+#define MAX_SYS_PDS               240
 
 struct megasas_sge32 {
-
-       u32 phys_addr;
-       u32 length;
-
+  
+  u32 phys_addr;
+  u32 length;
+  
 } __attribute__ ((packed));
 
 struct megasas_sge64 {
-
-       u64 phys_addr;
-       u32 length;
-
+  
+  u64 phys_addr;
+  u32 length;
+  
 } __attribute__ ((packed));
 
 union megasas_sgl {
-
-       struct megasas_sge32 sge32[1];
-       struct megasas_sge64 sge64[1];
-
+  
+  struct megasas_sge32 sge32[1];
+  struct megasas_sge64 sge64[1];
+  
 } __attribute__ ((packed));
 
 struct megasas_header {
-
-       u8 cmd;                 /*00h */
-       u8 sense_len;           /*01h */
-       u8 cmd_status;          /*02h */
-       u8 scsi_status;         /*03h */
-
-       u8 target_id;           /*04h */
-       u8 lun;                 /*05h */
-       u8 cdb_len;             /*06h */
-       u8 sge_count;           /*07h */
-
-       u32 context;            /*08h */
-       u32 pad_0;              /*0Ch */
-
-       u16 flags;              /*10h */
-       u16 timeout;            /*12h */
-       u32 data_xferlen;       /*14h */
-
+  
+  u8 cmd;           /*00h */
+  u8 sense_len;     /*01h */
+  u8 cmd_status;    /*02h */
+  u8 scsi_status;   /*03h */
+  
+  u8 target_id;     /*04h */
+  u8 lun;           /*05h */
+  u8 cdb_len;       /*06h */
+  u8 sge_count;     /*07h */
+  
+  u32 context;      /*08h */
+  u32 pad_0;        /*0Ch */
+  
+  u16 flags;        /*10h */
+  u16 timeout;      /*12h */
+  u32 data_xferlen; /*14h */
+  
 } __attribute__ ((packed));
 
 struct megasas_pthru_frame {
-
-       u8 cmd;                 /*00h */
-       u8 sense_len;           /*01h */
-       u8 cmd_status;          /*02h */
-       u8 scsi_status;         /*03h */
-
-       u8 target_id;           /*04h */
-       u8 lun;                 /*05h */
-       u8 cdb_len;             /*06h */
-       u8 sge_count;           /*07h */
-
-       u32 context;            /*08h */
-       u32 pad_0;              /*0Ch */
-
-       u16 flags;              /*10h */
-       u16 timeout;            /*12h */
-       u32 data_xfer_len;      /*14h */
-
-       u32 sense_buf_phys_addr_lo;     /*18h */
-       u32 sense_buf_phys_addr_hi;     /*1Ch */
-
-       u8 cdb[16];             /*20h */
-       union megasas_sgl sgl;  /*30h */
-
+  
+  u8 cmd;            /*00h */
+  u8 sense_len;      /*01h */
+  u8 cmd_status;     /*02h */
+  u8 scsi_status;    /*03h */
+  
+  u8 target_id;      /*04h */
+  u8 lun;            /*05h */
+  u8 cdb_len;        /*06h */
+  u8 sge_count;      /*07h */
+  
+  u32 context;       /*08h */
+  u32 pad_0;         /*0Ch */
+  
+  u16 flags;         /*10h */
+  u16 timeout;       /*12h */
+  u32 data_xfer_len; /*14h */
+  
+  u32 sense_buf_phys_addr_lo; /*18h */
+  u32 sense_buf_phys_addr_hi; /*1Ch */
+  
+  u8 cdb[16];            /*20h */
+  union megasas_sgl sgl; /*30h */
+  
 } __attribute__ ((packed));
 
 struct megasas_dcmd_frame {
-
-       u8 cmd;                 /*00h */
-       u8 reserved_0;          /*01h */
-       u8 cmd_status;          /*02h */
-       u8 reserved_1[4];       /*03h */
-       u8 sge_count;           /*07h */
-
-       u32 context;            /*08h */
-       u32 pad_0;              /*0Ch */
-
-       u16 flags;              /*10h */
-       u16 timeout;            /*12h */
-
-       u32 data_xfer_len;      /*14h */
-       u32 opcode;             /*18h */
-
-       union {                 /*1Ch */
-               u8 b[12];
-               u16 s[6];
-               u32 w[3];
-       } mbox;
-
-       union megasas_sgl sgl;  /*28h */
-
+  
+  u8 cmd;            /*00h */
+  u8 reserved_0;     /*01h */
+  u8 cmd_status;     /*02h */
+  u8 reserved_1[4];  /*03h */
+  u8 sge_count;      /*07h */
+  
+  u32 context;       /*08h */
+  u32 pad_0;         /*0Ch */
+  
+  u16 flags;         /*10h */
+  u16 timeout;  /*12h */
+  
+  u32 data_xfer_len; /*14h */
+  u32 opcode;  /*18h */
+  
+  union {   /*1Ch */
+    u8 b[12];
+    u16 s[6];
+    u32 w[3];
+  } mbox;
+  
+  union megasas_sgl sgl; /*28h */
+  
 } __attribute__ ((packed));
 
 struct megasas_iocpacket {
+  u16 host_no;
+  u16 __pad1;
+  u32 sgl_off;
+  u32 sge_count;
+  u32 sense_off;
+  u32 sense_len;
+  union {
+    u8 raw[128];
+    struct megasas_header hdr;
+    struct megasas_pthru_frame pthru;
+    struct megasas_dcmd_frame dcmd;
+  } frame;
+  
+  struct iovec sgl[MAX_IOCTL_SGE];
+} __attribute__ ((packed));
 
-       u16 host_no;
-       u16 __pad1;
-       u32 sgl_off;
-       u32 sge_count;
-       u32 sense_off;
-       u32 sense_len;
-       union {
-               u8 raw[128];
-               struct megasas_header hdr;
-               struct megasas_pthru_frame pthru;
-       } frame;
-
-       struct iovec sgl[MAX_IOCTL_SGE];
-
+struct megasas_pd_address {
+  u16 device_id;
+  u16 encl_device_id;
+  u8 encl_index;
+  u8 slot_number;
+  u8 scsi_dev_type; /* 0 = disk */
+  u8 connect_port_bitmap;
+  u64 sas_addr[2];
+}   __attribute__ ((packed));
+
+struct megasas_pd_list {
+  u32 size;
+  u32 count;
+  struct megasas_pd_address addr[MAX_SYS_PDS];
 } __attribute__ ((packed));
 
 #undef u8
index 61c3425c7de3addd8e62b16c8edfa3a54fd30658..eabdee9846eefc3a1b5f946a1d7f2fd1495aea2b 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include <stdbool.h>
@@ -44,7 +44,7 @@
 #include "os_darwin.h"
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_darwin.cpp,v 1.21 2008/06/12 21:46:31 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_darwin.cpp 3805 2013-03-29 19:54:18Z chrfranke $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_DARWIN_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // Print examples for smartctl.
@@ -72,9 +72,8 @@ void print_smartctl_examples(){
 
 // tries to guess device type given the name (a path).  See utility.h
 // for return values.
-int guess_device_type (const char* dev_name) {
+int guess_device_type (const char * /* dev_name */) {
   // Only ATA is supported right now, so that's what it'd better be.
-  dev_name = dev_name;  // suppress unused warning.
   return CONTROLLER_ATA;
 }
 
@@ -420,59 +419,7 @@ ata_command_interface(int fd, smart_command_set command,
   return err == kIOReturnSuccess ? 0 : -1;
 }
 
-// There's no special handling needed for hidden devices, the kernel
-// must deal with them.
-int escalade_command_interface(int fd, int escalade_port, int escalade_type,
-                              smart_command_set command, int select,
-                              char *data)
-{
-  fd = fd;
-  escalade_port = escalade_port;
-  escalade_type = escalade_type;
-  command = command;
-  select = select;
-  data = data;
-  return -1;
-}
-
-int areca_command_interface(int fd, int escalade_port, 
-                              smart_command_set command, int select,
-                              char *data)
-{
-  fd = fd;
-  escalade_port = escalade_port;
-  command = command;
-  select = select;
-  data = data;
-  return -1;
-}
-
-
-
-
-int marvell_command_interface(int fd, smart_command_set command,
-                     int select, char *data)
-{ 
-  fd = fd;
-  command = command;
-  select = select;
-  data = data;
-  return -1;
-}
-
-int highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{
-  fd = fd;
-  command = command;
-  select = select;
-  data = data;
-  return -1;
-}
-
 // Interface to SCSI devices.  See os_linux.c
-int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) {
-  fd = fd;
-  iop = iop;
-  report = report;
+int do_scsi_cmnd_io(int /* fd */, struct scsi_cmnd_io * /* iop */, int /* report */) {
   return -ENOSYS;
 }
index b3a7ec47c108073c346cd5a61710d0479981d71b..59781874470e82990eef018a6809ba84f422e464 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -24,7 +24,7 @@
 #ifndef OS_DARWIN_H_
 #define OS_DARWIN_H_
 
-#define OS_DARWIN_H_CVSID "$Id: os_darwin.h,v 1.7 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_DARWIN_H_CVSID "$Id: os_darwin.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 // Isn't in 10.3.9?
 
index eb6137d90d6aca5fcb4a2caf79ce728f3f8f16eb..df2cb5cb6ae777a1734592d54f138a07bef203ac 100644 (file)
 # version.
 #
 # You should have received a copy of the GNU General Public License (for
-# example COPYING); if not, write to the Free Software Foundation, Inc., 675
-# Mass Ave, Cambridge, MA 02139, USA.
+# example COPYING); if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
-# $Id: SMART.in,v 1.5 2008/03/04 22:09:47 ballen4705 Exp $
+# $Id: SMART.in 3728 2012-12-13 17:57:50Z chrfranke $
 
 ##
 # SMART monitoring
index d9a6add0dddfa0f029c5b399dffe50d4f401cf52..4f00cddcaa5cc06c31dc7574df74b306a94ce667 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
+ *
  */
 
 #include <stdio.h>
@@ -46,6 +46,7 @@
 
 #include "dev_interface.h"
 #include "dev_ata_cmd_set.h"
+#include "dev_areca.h"
 
 #define USBDEV "/dev/usb"
 #if defined(__FreeBSD_version)
@@ -74,7 +75,7 @@
 #define PATHINQ_SETTINGS_SIZE   128
 #endif
 
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3542 2012-05-18 18:18:45Z samm2 $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3771 2013-02-10 15:36:55Z samm2 $" \
 ATACMDS_H_CVSID CCISS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_FREEBSD_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 #define NO_RETURN 0
@@ -121,6 +122,7 @@ void printwarning(int msgNo, const char* extra) {
 
 // global variable holding byte count of allocated memory
 long long bytes;
+extern unsigned char failuretest_permissive;
 
 /////////////////////////////////////////////////////////////////////////////
 
@@ -189,6 +191,7 @@ static const char  smartctl_examples[] =
          "                                      (Prints Self-Test & Attribute errors)\n\n"
          "  smartctl -a --device=3ware,2 /dev/twa0\n"
          "  smartctl -a --device=3ware,2 /dev/twe0\n"
+         "  smartctl -a --device=3ware,2 /dev/tws0\n"
          "                              (Prints all SMART information for ATA disk on\n"
          "                                 third port of first 3ware RAID controller)\n"
   "  smartctl -a --device=cciss,0 /dev/ciss0\n"
@@ -252,9 +255,11 @@ freebsd_ata_device::freebsd_ata_device(smart_interface * intf, const char * dev_
 
 int freebsd_ata_device::do_cmd( struct ata_ioc_request* request, bool is_48bit_cmd)
 {
-  int fd = get_fd();
+  int fd = get_fd(), ret;
   ARGUSED(is_48bit_cmd); // no support for 48 bit commands in the IOCATAREQUEST
-  return ioctl(fd, IOCATAREQUEST, request);
+  ret = ioctl(fd, IOCATAREQUEST, request);
+  if (ret) set_err(errno);
+  return ret;
 }
 
 
@@ -269,8 +274,10 @@ bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o
     true,  // data_out_support
     true,  // multi_sector_support
     ata_48bit) 
-    ) 
-    return false;
+    ) {
+      set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
+      return false;
+    }
 
   struct ata_ioc_request request;
   bzero(&request,sizeof(struct ata_ioc_request));
@@ -303,7 +310,7 @@ bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o
   clear_err();
   errno = 0;
   if (do_cmd(&request, in.in_regs.is_48bit_cmd()))
-      return set_err(errno);
+      return false;
   if (request.error)
       return set_err(EIO, "request failed, error code 0x%02x", request.error);
 
@@ -328,7 +335,8 @@ bool freebsd_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & o
     {
       // We haven't gotten output that makes sense; print out some debugging info
       char buf[512];
-      sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
+      snprintf(buf, sizeof(buf),
+        "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
         (int)request.u.ata.command,
         (int)request.u.ata.feature,
         (int)request.u.ata.count,
@@ -385,6 +393,16 @@ int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bi
   union ccb ccb;
   int camflags;
 
+  // FIXME:
+  // 48bit commands are broken in ATACAM before r242422/HEAD
+  // and may cause system hang
+  // Waiting for MFC to make sure that bug is fixed,
+  // later version check needs to be added
+  if(!strcmp("ata",m_camdev->sim_name) && is_48bit_cmd) {
+    set_err(ENOSYS, "48-bit ATA commands not implemented for legacy controllers");
+    return -1;
+  }
+
   memset(&ccb, 0, sizeof(ccb));
 
   if (request->count == 0)
@@ -393,8 +411,6 @@ int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bi
     camflags = CAM_DIR_IN;
   else
     camflags = CAM_DIR_OUT;
-  if(is_48bit_cmd)
-    camflags |= CAM_ATAIO_48BIT;
 
   cam_fill_ataio(&ccb.ataio,
                  0,
@@ -405,7 +421,8 @@ int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bi
                  request->count,
                  request->timeout * 1000); // timeout in seconds
 
-  ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT;
+  ccb.ataio.cmd.flags = CAM_ATAIO_NEEDRESULT |
+    (is_48bit_cmd ? CAM_ATAIO_48BIT : 0);
   // ata_28bit_cmd
   ccb.ataio.cmd.command = request->u.ata.command;
   ccb.ataio.cmd.features = request->u.ata.feature;
@@ -423,12 +440,13 @@ int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bi
   ccb.ccb_h.flags |= CAM_DEV_QFRZDIS;
 
   if (cam_send_ccb(m_camdev, &ccb) < 0) {
-    err(1, "cam_send_ccb");
+    set_err(EIO, "cam_send_ccb failed");
     return -1;
   }
 
   if ((ccb.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
     cam_error_print(m_camdev, &ccb, CAM_ESF_ALL, CAM_EPF_ALL, stderr);
+    set_err(EIO);
     return -1;
   }
 
@@ -449,10 +467,10 @@ int freebsd_atacam_device::do_cmd( struct ata_ioc_request* request, bool is_48bi
 #endif
 
 /////////////////////////////////////////////////////////////////////////////
-/// Implement AMCC/3ware RAID support with old functions
+/// Implement AMCC/3ware RAID support
 
 class freebsd_escalade_device
-: public /*implements*/ ata_device_with_command_set,
+: public /*implements*/ ata_device,
   public /*extends*/ freebsd_smart_device
 {
 public:
@@ -460,7 +478,7 @@ public:
     int escalade_type, int disknum);
 
 protected:
-  virtual int ata_command_interface(smart_command_set command, int select, char * data);
+  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
   virtual bool open();
 
 private:
@@ -493,13 +511,18 @@ bool freebsd_escalade_device::open()
   return true;
 }
 
-int freebsd_escalade_device::ata_command_interface(smart_command_set command, int select, char * data)
+bool freebsd_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
   // to hold true file descriptor
   int fd = get_fd();
 
-  // return value and buffer for ioctl()
-  int  ioctlreturn, readdata=0;
+  if (!ata_cmd_is_ok(in,
+    true, // data_out_support
+    false, // TODO: multi_sector_support
+    true) // ata_48bit_support
+  )
+  return false;
+
   struct twe_usercommand* cmd_twe = NULL;
   TW_OSLI_IOCTL_NO_DATA_BUF* cmd_twa = NULL;
   TWE_Command_ATA* ata = NULL;
@@ -517,16 +540,16 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
   if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
     cmd_twa = (TW_OSLI_IOCTL_NO_DATA_BUF*)ioctl_buffer;
     cmd_twa->pdata = ((TW_OSLI_IOCTL_WITH_PAYLOAD*)cmd_twa)->payload.data_buf;
-    cmd_twa->driver_pkt.buffer_length = 512;
+    cmd_twa->driver_pkt.buffer_length = in.size;
+    // using "old" packet format to speak with SATA devices
     ata = (TWE_Command_ATA*)&cmd_twa->cmd_pkt.command.cmd_pkt_7k;
   } else if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
     cmd_twe = (struct twe_usercommand*)ioctl_buffer;
     ata = &cmd_twe->tu_command.ata;
   } else {
-    pout("Unrecognized escalade_type %d in freebsd_3ware_command_interface(disk %d)\n"
-      "Please contact " PACKAGE_BUGREPORT "\n", m_escalade_type, m_disknum);
-    errno=ENOSYS;
-    return -1;
+    return set_err(ENOSYS,
+      "Unrecognized escalade_type %d in linux_3ware_command_interface(disk %d)\n"
+      "Please contact " PACKAGE_BUGREPORT "\n", (int)m_escalade_type, m_disknum);
   }
 
   ata->opcode = TWE_OP_ATA_PASSTHROUGH;
@@ -534,18 +557,20 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
   // Same for (almost) all commands - but some reset below
   ata->request_id    = 0xFF;
   ata->unit          = m_disknum;
-  ata->status        = 0;           
+  ata->status        = 0;
   ata->flags         = 0x1;
-  ata->drive_head    = 0x0;
-  ata->sector_num    = 0;
-
-  // All SMART commands use this CL/CH signature.  These are magic
-  // values from the ATA specifications.
-  ata->cylinder_lo   = 0x4F;
-  ata->cylinder_hi   = 0xC2;
-
-  // SMART ATA COMMAND REGISTER value
-  ata->command       = ATA_SMART_CMD;
+  ata->size         = 0x5; // TODO: multisector support
+  // Set registers
+  {
+    const ata_in_regs_48bit & r = in.in_regs;
+    ata->features     = r.features_16;
+    ata->sector_count = r.sector_count_16;
+    ata->sector_num   = r.lba_low_16;
+    ata->cylinder_lo  = r.lba_mid_16;
+    ata->cylinder_hi  = r.lba_high_16;
+    ata->drive_head   = r.device;
+    ata->command      = r.command;
+  }
 
   // Is this a command that reads or returns 512 bytes?
   // passthru->param values are:
@@ -554,113 +579,51 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
   // 0xD - data command that returns data to host from device
   // 0xF - data command that writes data from host to device
   // passthru->size values are 0x5 for non-data and 0x07 for data
-  if (command == READ_VALUES     ||
-      command == READ_THRESHOLDS ||
-      command == READ_LOG        ||
-      command == IDENTIFY        ||
-      command == WRITE_LOG ) 
-  {
-    readdata=1;
+  bool readdata = false;
+  if (in.direction == ata_cmd_in::data_in) {
     if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
-      cmd_twe->tu_data = data;
+      cmd_twe->tu_data = in.buffer;
       cmd_twe->tu_size = 512;
     }
-    ata->sgl_offset = 0x5;
-    ata->size         = 0x5;
+
+    readdata=true;
+    ata->sgl_offset   = 0x5;
     ata->param        = 0xD;
-    ata->sector_count = 0x1;
     // For 64-bit to work correctly, up the size of the command packet
     // in dwords by 1 to account for the 64-bit single sgl 'address'
     // field. Note that this doesn't agree with the typedefs but it's
     // right (agree with kernel driver behavior/typedefs).
-    //if (sizeof(long)==8)
+    // if (sizeof(long)==8)
     //  ata->size++;
   }
-  else {
+  else if (in.direction == ata_cmd_in::no_data) {
     // Non data command -- but doesn't use large sector 
-    // count register values.  
-    ata->sgl_offset = 0x0;
-    ata->size         = 0x5;
+    // count register values.
+    ata->sgl_offset   = 0x0;
     ata->param        = 0x8;
     ata->sector_count = 0x0;
   }
+  else if (in.direction == ata_cmd_in::data_out) {
+    ata->sgl_offset   = 0x5;
+    ata->param        = 0xF; // PIO data write
+    if (m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
+      cmd_twe->tu_data = in.buffer;
+      cmd_twe->tu_size = 512;
+    }
+    else if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
+       memcpy(cmd_twa->pdata, in.buffer, in.size);
+    }
+  }
+  else
+    return set_err(EINVAL);
 
-  // Now set ATA registers depending upon command
-  switch (command){
-  case CHECK_POWER_MODE:
-    ata->command     = ATA_CHECK_POWER_MODE;
-    ata->features    = 0;
-    ata->cylinder_lo = 0;
-    ata->cylinder_hi = 0;
-    break;
-  case READ_VALUES:
-    ata->features = ATA_SMART_READ_VALUES;
-    break;
-  case READ_THRESHOLDS:
-    ata->features = ATA_SMART_READ_THRESHOLDS;
-    break;
-  case READ_LOG:
-    ata->features = ATA_SMART_READ_LOG_SECTOR;
-    // log number to return
-    ata->sector_num  = select;
-    break;
-  case WRITE_LOG:
-    readdata=0;
-    ata->features     = ATA_SMART_WRITE_LOG_SECTOR;
-    ata->sector_count = 1;
-    ata->sector_num   = select;
-    ata->param        = 0xF;  // PIO data write
-    break;
-  case IDENTIFY:
-    // ATA IDENTIFY DEVICE
-    ata->command     = ATA_IDENTIFY_DEVICE;
-    ata->features    = 0;
-    ata->cylinder_lo = 0;
-    ata->cylinder_hi = 0;
-    break;
-  case PIDENTIFY:
-    // 3WARE controller can NOT have packet device internally
-    pout("WARNING - NO DEVICE FOUND ON 3WARE CONTROLLER (disk %d)\n", m_disknum);
-    errno=ENODEV;
-    return -1;
-  case ENABLE:
-    ata->features = ATA_SMART_ENABLE;
-    break;
-  case DISABLE:
-    ata->features = ATA_SMART_DISABLE;
-    break;
-  case AUTO_OFFLINE:
-    ata->features     = ATA_SMART_AUTO_OFFLINE;
-    // Enable or disable?
-    ata->sector_count = select;
-    break;
-  case AUTOSAVE:
-    ata->features     = ATA_SMART_AUTOSAVE;
-    // Enable or disable?
-    ata->sector_count = select;
-    break;
-  case IMMEDIATE_OFFLINE:
-    ata->features    = ATA_SMART_IMMEDIATE_OFFLINE;
-    // What test type to run?
-    ata->sector_num  = select;
-    break;
-  case STATUS_CHECK:
-    ata->features = ATA_SMART_STATUS;
-    break;
-  case STATUS:
-    // This is JUST to see if SMART is enabled, by giving SMART status
-    // command. But it doesn't say if status was good, or failing.
-    // See below for the difference.
-    ata->features = ATA_SMART_STATUS;
-    break;
-  default:
-    pout("Unrecognized command %d in freebsd_3ware_command_interface(disk %d)\n"
-         "Please contact " PACKAGE_BUGREPORT "\n", command, m_disknum);
-    errno=ENOSYS;
-    return -1;
+  // 3WARE controller can NOT have packet device internally
+  if (in.in_regs.command == ATA_IDENTIFY_PACKET_DEVICE) {
+    return set_err(ENODEV, "No drive on port %d", m_disknum);
   }
 
   // Now send the command down through an ioctl()
+  int ioctlreturn;
   if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR) {
     ioctlreturn=ioctl(fd,TW_OSL_IOCTL_FIRMWARE_PASS_THROUGH,cmd_twa);
   } else {
@@ -669,9 +632,7 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
 
   // Deal with the different error cases
   if (ioctlreturn) {
-    if (!errno)
-      errno=EIO;
-    return -1;
+    return set_err(EIO);
   }
 
   // See if the ATA command failed.  Now that we have returned from
@@ -687,50 +648,36 @@ int freebsd_escalade_device::ata_command_interface(smart_command_set command, in
   // happened.
 
   if (ata->status || (ata->command & 0x21)) {
-    pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags);
-    errno=EIO;
-    return -1;
+    if (scsi_debugmode)
+      pout("Command failed, ata.status=(0x%2.2x), ata.command=(0x%2.2x), ata.flags=(0x%2.2x)\n",ata->status,ata->command,ata->flags);
+    return set_err(EIO);
   }
 
   // If this is a read data command, copy data to output buffer
   if (readdata) {
     if (m_escalade_type==CONTROLLER_3WARE_9000_CHAR)
-      memcpy(data, cmd_twa->pdata, 512);
+      memcpy(in.buffer, cmd_twa->pdata, in.size);
+    else if(m_escalade_type==CONTROLLER_3WARE_678K_CHAR) {
+      memcpy(in.buffer, cmd_twe->tu_data, in.size); // untested
+    }
   }
-
-  // For STATUS_CHECK, we need to check register values
-  if (command==STATUS_CHECK) {
-
-    // To find out if the SMART RETURN STATUS is good or failing, we
-    // need to examine the values of the Cylinder Low and Cylinder
-    // High Registers.
-
-    unsigned short cyl_lo=ata->cylinder_lo;
-    unsigned short cyl_hi=ata->cylinder_hi;
-
-    // If values in Cyl-LO and Cyl-HI are unchanged, SMART status is good.
-    if (cyl_lo==0x4F && cyl_hi==0xC2)
-      return 0;
-
-    // If values in Cyl-LO and Cyl-HI are as follows, SMART status is FAIL
-    if (cyl_lo==0xF4 && cyl_hi==0x2C)
-      return 1;
-
-      errno=EIO;
-      return -1;
+  // Return register values
+  if (ata) {
+    ata_out_regs_48bit & r = out.out_regs;
+    r.error           = ata->features;
+    r.sector_count_16 = ata->sector_count;
+    r.lba_low_16      = ata->sector_num;
+    r.lba_mid_16      = ata->cylinder_lo;
+    r.lba_high_16     = ata->cylinder_hi;
+    r.device          = ata->drive_head;
+    r.status          = ata->command;
   }
-
-  // copy sector count register (one byte!) to return data
-  if (command==CHECK_POWER_MODE)
-    *data=*(char *)&(ata->sector_count);
-
   // look for nonexistent devices/ports
-  if (command==IDENTIFY && !nonempty(data, 512)) {
-    errno=ENODEV;
-    return -1;
+  if (in.in_regs.command == ATA_IDENTIFY_DEVICE
+  && !nonempty((unsigned char *)in.buffer, in.size)) {
+    return set_err(ENODEV, "No drive on port %d", m_disknum);
   }
-
-  return 0;
+  return true;
 }
 
 
@@ -911,7 +858,8 @@ int freebsd_highpoint_device::ata_command_interface(smart_command_set command, i
 
     // We haven't gotten output that makes sense; print out some debugging info
     char buf[512];
-    sprintf(buf,"CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
+    snprintf(buf, sizeof(buf),
+            "CMD=0x%02x\nFR =0x%02x\nNS =0x%02x\nSC =0x%02x\nCL =0x%02x\nCH =0x%02x\nRETURN =0x%04x\n",
             (int)pide_pt_hdr_out->command,
             (int)pide_pt_hdr_out->feature,
             (int)pide_pt_hdr_out->sectorcount,
@@ -1021,13 +969,16 @@ bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
         return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
     }
     // SMART WRITE LOG SECTOR causing media errors
-    if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 && iop->cmnd[14] == ATA_SMART_CMD 
-        && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || 
-        (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 && iop->cmnd[9] == ATA_SMART_CMD &&
-        iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) 
-      return set_err(ENOSYS, "SMART WRITE LOG SECTOR command is not supported by controller firmware"); 
+    if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16
+        && iop->cmnd[14] == ATA_SMART_CMD  && iop->cmnd[3]==0 &&
+        iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
+        (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12
+        && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR))
+    {
+      if(!failuretest_permissive)
+        return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force"); 
+    }
   }
-
   // clear out structure, except for header that was filled in for us
   bzero(&(&ccb->ccb_h)[1],
     sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
@@ -1077,6 +1028,16 @@ bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
     dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
   }
 
+  // mfip replacing PDT of the device so response does not make a sense
+  // this sets PDT to 00h - direct-access block device
+  if((!strcmp("mfi", m_camdev->sim_name) || !strcmp("mpt", m_camdev->sim_name))
+   && iop->cmnd[0] == INQUIRY) {
+     if (report > 0) {
+        pout("device on %s controller, patching PDT\n", m_camdev->sim_name);
+     }
+     iop->dxferp[0] = iop->dxferp[0] & 0xe0;
+  }
+
   return true;
 }
 
@@ -1084,433 +1045,148 @@ bool freebsd_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
 /////////////////////////////////////////////////////////////////////////////
 /// Areca RAID support
 
-class freebsd_areca_device
-: public /*implements*/ ata_device,
+///////////////////////////////////////////////////////////////////
+// SATA(ATA) device behind Areca RAID Controller
+class freebsd_areca_ata_device
+: public /*implements*/ areca_ata_device,
   public /*extends*/ freebsd_smart_device
 {
 public:
-  freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
-
-protected:
-  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); 
+  freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  virtual smart_device * autodetect_open();
+  virtual bool arcmsr_lock();
+  virtual bool arcmsr_unlock();
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
+};
 
-private:
-  int m_disknum; ///< Disk number.
+///////////////////////////////////////////////////////////////////
+// SAS(SCSI) device behind Areca RAID Controller
+class freebsd_areca_scsi_device
+: public /*implements*/ areca_scsi_device,
+  public /*extends*/ freebsd_smart_device
+{
+public:
+  freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  virtual smart_device * autodetect_open();
+  virtual bool arcmsr_lock();
+  virtual bool arcmsr_unlock();
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
 };
 
 
-// PURPOSE
-//   This is an interface routine meant to isolate the OS dependent
-//   parts of the code, and to provide a debugging interface.  Each
-//   different port and OS needs to provide it's own interface.  This
-//   is the linux interface to the Areca "arcmsr" driver.  It allows ATA
-//   commands to be passed through the SCSI driver.
-// DETAILED DESCRIPTION OF ARGUMENTS
-//   fd: is the file descriptor provided by open()
-//   disknum is the disk number (0 to 15) in the RAID array
-//   command: defines the different operations.
-//   select: additional input data if needed (which log, which type of
-//           self-test).
-//   data:   location to write output data, if needed (512 bytes).
-//   Note: not all commands use all arguments.
-// RETURN VALUES
-//  -1 if the command failed
-//   0 if the command succeeded,
-//   STATUS_CHECK routine: 
-//  -1 if the command failed
-//   0 if the command succeeded and disk SMART status is "OK"
-//   1 if the command succeeded and disk SMART status is "FAILING"
-
-
-/*FunctionCode*/
-#define FUNCTION_READ_RQBUFFER                 0x0801
-#define FUNCTION_WRITE_WQBUFFER                0x0802
-#define FUNCTION_CLEAR_RQBUFFER                0x0803
-#define FUNCTION_CLEAR_WQBUFFER                0x0804
-
-/* ARECA IO CONTROL CODE*/
-#define ARCMSR_IOCTL_READ_RQBUFFER           _IOWR('F', FUNCTION_READ_RQBUFFER, sSRB_BUFFER)
-#define ARCMSR_IOCTL_WRITE_WQBUFFER          _IOWR('F', FUNCTION_WRITE_WQBUFFER, sSRB_BUFFER)
-#define ARCMSR_IOCTL_CLEAR_RQBUFFER          _IOWR('F', FUNCTION_CLEAR_RQBUFFER, sSRB_BUFFER)
-#define ARCMSR_IOCTL_CLEAR_WQBUFFER          _IOWR('F', FUNCTION_CLEAR_WQBUFFER, sSRB_BUFFER)
-#define ARECA_SIG_STR                                                  "ARCMSR"
-
-
-
-// The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
-typedef struct _SRB_IO_CONTROL
+// Areca RAID Controller(SATA Disk)
+freebsd_areca_ata_device::freebsd_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca"),
+  freebsd_smart_device("ATA")
+{
+  set_disknum(disknum);
+  set_encnum(encnum);
+  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
+}
+
+
+smart_device * freebsd_areca_ata_device::autodetect_open()
 {
-       unsigned int HeaderLength;
-       unsigned char Signature[8];
-       unsigned int Timeout;
-       unsigned int ControlCode;
-       unsigned int ReturnCode;
-       unsigned int Length;
-} sSRB_IO_CONTROL;
-
-typedef struct _SRB_BUFFER
+  int is_ata = 1;
+
+  // autodetect device type
+  is_ata = arcmsr_get_dev_type();
+  if(is_ata < 0)
+  {
+    set_err(EIO);
+    return this;
+  }
+
+  if(is_ata == 1)
+  {
+    // SATA device
+    return this;
+  }
+
+  // SAS device
+  smart_device_auto_ptr newdev(new freebsd_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
+  close();
+  delete this;
+  newdev->open();      // TODO: Can possibly pass open fd
+
+  return newdev.release();
+}
+
+int freebsd_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
 {
-       sSRB_IO_CONTROL srbioctl;
-       unsigned char   ioctldatabuffer[1032]; // the buffer to put the command data to/from firmware
-} sSRB_BUFFER;
+  int ioctlreturn = 0;
+
+  if(!is_open()) {
+      if(!open()){
+      }
+  }
 
+  ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
+  if (ioctlreturn)
+  {
+    // errors found
+    return -1;
+  }
 
-// For debugging areca code
+  return ioctlreturn;
+}
 
-static void areca_dumpdata(unsigned char *block, int len)
+bool freebsd_areca_ata_device::arcmsr_lock()
 {
-       int ln = (len / 16) + 1;         // total line#
-       unsigned char c;
-       int pos = 0;
-
-       printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
-       printf("      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F      ASCII      \n");
-       printf("=====================================================================\n");
-
-       for ( int l = 0; l < ln && len; l++ )
-       {
-               // printf the line# and the HEX data
-               // if a line data length < 16 then append the space to the tail of line to reach 16 chars
-               printf("%02X | ", l);
-               for ( pos = 0; pos < 16 && len; pos++, len-- )
-               {
-                       c = block[l*16+pos];    
-                       printf("%02X ", c);
-               }
-
-               if ( pos < 16 )
-               {
-                       for ( int loop = pos; loop < 16; loop++ )
-                       {
-                               printf("   ");
-                       }
-               }
-
-               // print ASCII char
-               for ( int loop = 0; loop < pos; loop++ )
-               {
-                       c = block[l*16+loop];
-                       if ( c >= 0x20 && c <= 0x7F )
-                       {
-                               printf("%c", c);
-                       }
-                       else
-                       {
-                               printf(".");
-                       }
-               }
-               printf("\n");
-       }   
-       printf("=====================================================================\n");
+  return true;
 }
 
 
-static int arcmsr_command_handler(int fd, unsigned long arcmsr_cmd, unsigned char *data, int data_len, void *ext_data /* reserved for further use */)
+bool freebsd_areca_ata_device::arcmsr_unlock()
 {
-       ARGUSED(ext_data);
-
-       int ioctlreturn = 0;
-       sSRB_BUFFER sBuf;
-
-       unsigned char *areca_return_packet;
-       int total = 0;
-       int expected = -1;
-       unsigned char return_buff[2048];
-       unsigned char *ptr = &return_buff[0];
-       memset(return_buff, 0, sizeof(return_buff));
-
-       memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
-
-
-       sBuf.srbioctl.HeaderLength = sizeof(sSRB_IO_CONTROL);   
-       memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
-       sBuf.srbioctl.Timeout = 10000;      
-       sBuf.srbioctl.ControlCode = ARCMSR_IOCTL_READ_RQBUFFER;
-
-       switch ( arcmsr_cmd )
-       {
-       // command for writing data to driver
-       case ARCMSR_IOCTL_WRITE_WQBUFFER:   
-               if ( data && data_len )
-               {
-                       sBuf.srbioctl.Length = data_len;    
-                       memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
-               }
-               // commands for clearing related buffer of driver
-       case ARCMSR_IOCTL_CLEAR_RQBUFFER:
-       case ARCMSR_IOCTL_CLEAR_WQBUFFER:
-               break;
-               // command for reading data from driver
-       case ARCMSR_IOCTL_READ_RQBUFFER:    
-               break;
-       default:
-               // unknown arcmsr commands
-               return -1;
-       }
-
-
-       while ( 1 )
-       {
-               ioctlreturn = ioctl(fd,arcmsr_cmd,&sBuf);
-               if ( ioctlreturn  )
-               {
-                       // errors found
-                       break;
-               }
-
-               if ( arcmsr_cmd != ARCMSR_IOCTL_READ_RQBUFFER )
-               {
-                       // if succeeded, just returns the length of outgoing data
-                       return data_len;
-               }
-
-               if ( sBuf.srbioctl.Length )
-               {
-                       if(ata_debugmode)
-                           areca_dumpdata(&sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
-                       memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
-                       ptr += sBuf.srbioctl.Length;
-                       total += sBuf.srbioctl.Length;
-                       // the returned bytes enough to compute payload length ?
-                       if ( expected < 0 && total >= 5 )
-                       {
-                               areca_return_packet = (unsigned char *)&return_buff[0];
-                               if ( areca_return_packet[0] == 0x5E && 
-                                        areca_return_packet[1] == 0x01 && 
-                                        areca_return_packet[2] == 0x61 )
-                               {
-                                       // valid header, let's compute the returned payload length,
-                                       // we expected the total length is 
-                                       // payload + 3 bytes header + 2 bytes length + 1 byte checksum
-                                       expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
-                               }
-                       }
-
-                       if ( total >= 7 && total >= expected )
-                       {
-                               //printf("total bytes received = %d, expected length = %d\n", total, expected);
-
-                               // ------ Okay! we received enough --------
-                               break;
-                       }
-               }
-       }
-
-       // Deal with the different error cases
-       if ( ioctlreturn )
-       {
-               pout("ioctl write buffer failed code = %x\n", ioctlreturn);
-               return -2;
-       }
-
-
-       if ( data )
-       {
-               memcpy(data, return_buff, total);
-       }
-
-       return total;
+  return true;
 }
 
 
-freebsd_areca_device::freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+// Areca RAID Controller(SAS Device)
+freebsd_areca_scsi_device::freebsd_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
 : smart_device(intf, dev_name, "areca", "areca"),
-  freebsd_smart_device("ATA"),
-  m_disknum(disknum),
-  m_encnum(encnum)
+  freebsd_smart_device("SCSI")
 {
+  set_disknum(disknum);
+  set_encnum(encnum);
   set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
 }
 
-// Areca RAID Controller
-// int freebsd_areca_device::ata_command_interface(smart_command_set command, int select, char * data)
-bool freebsd_areca_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) 
+smart_device * freebsd_areca_scsi_device::autodetect_open()
+{
+  return this;
+}
+
+int freebsd_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
+{
+  int ioctlreturn = 0;
+
+  if(!is_open()) {
+      if(!open()){
+      }
+  }
+  ioctlreturn = ioctl(get_fd(), ((sSRB_BUFFER *)(iop->dxferp))->srbioctl.ControlCode, iop->dxferp);
+  if (ioctlreturn)
+  {
+    // errors found
+    return -1;
+  }
+
+  return ioctlreturn;
+}
+
+bool freebsd_areca_scsi_device::arcmsr_lock()
 {
-if (!ata_cmd_is_ok(in, 
-    true, // data_out_support 
-    false, // TODO: multi_sector_support 
-    true) // ata_48bit_support 
-    )
-    return false; 
-
-       // ATA input registers
-       typedef struct _ATA_INPUT_REGISTERS
-       {
-               unsigned char features;
-               unsigned char sector_count;
-               unsigned char sector_number;
-               unsigned char cylinder_low; 
-               unsigned char cylinder_high;    
-               unsigned char device_head;  
-               unsigned char command;      
-               unsigned char reserved[8];
-               unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
-       } sATA_INPUT_REGISTERS;
-
-       // ATA output registers
-       // Note: The output registers is re-sorted for areca internal use only
-       typedef struct _ATA_OUTPUT_REGISTERS
-       {
-               unsigned char error;
-               unsigned char status;
-               unsigned char sector_count;
-               unsigned char sector_number;
-               unsigned char cylinder_low; 
-               unsigned char cylinder_high;
-       }sATA_OUTPUT_REGISTERS;
-
-       // Areca packet format for outgoing:
-       // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
-       // B[3~4] : 2 bytes command length + variant data length, little endian
-       // B[5]   : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
-       // B[6~last-1] : variant bytes payload data
-       // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
-       // 
-       // 
-       //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte 
-       // +--------------------------------------------------------------------------------+
-       // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
-       // +--------------------------------------------------------------------------------+
-       // 
-
-       //Areca packet format for incoming:
-       // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
-       // B[3~4] : 2 bytes payload length, little endian
-       // B[5~last-1] : variant bytes returned payload data
-       // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
-       // 
-       // 
-       //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte 
-       // +-------------------------------------------------------------------+
-       // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
-       // +-------------------------------------------------------------------+
-       unsigned char    areca_packet[640];
-       int areca_packet_len = sizeof(areca_packet);
-       unsigned char cs = 0;   
-
-       sATA_INPUT_REGISTERS *ata_cmd;
-
-       // For debugging
-       memset(areca_packet, 0, areca_packet_len);
-
-       // ----- BEGIN TO SETUP HEADERS -------
-       areca_packet[0] = 0x5E;
-       areca_packet[1] = 0x01;
-       areca_packet[2] = 0x61;
-       areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
-       areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
-       areca_packet[5] = 0x1c; // areca defined code for ATA passthrough command
-
-       // ----- BEGIN TO SETUP PAYLOAD DATA -----
-       memcpy(&areca_packet[7], "SmrT", 4);    // areca defined password
-       ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
-
-       // Set registers
-        {
-           const ata_in_regs_48bit & r = in.in_regs;
-           ata_cmd->features     = r.features_16;
-           ata_cmd->sector_count  = r.sector_count_16;
-           ata_cmd->sector_number = r.lba_low_16;
-           ata_cmd->cylinder_low  = r.lba_mid_16;
-           ata_cmd->cylinder_high = r.lba_high_16;
-           ata_cmd->device_head   = r.device;
-           ata_cmd->command      = r.command;
-       }
-       bool readdata = false; 
-       if (in.direction == ata_cmd_in::data_in) { 
-           readdata = true;
-           // the command will read data
-           areca_packet[6] = 0x13;
-       }
-       else if ( in.direction == ata_cmd_in::no_data )
-       {
-               // the commands will return no data
-               areca_packet[6] = 0x15;
-       }
-       else if (in.direction == ata_cmd_in::data_out) 
-       {
-               // the commands will write data
-               memcpy(ata_cmd->data, in.buffer, in.size);
-               areca_packet[6] = 0x14;
-       }
-       else {
-           // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
-           return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type");
-       }
-
-       areca_packet[11] = m_disknum - 1;               // disk #
-       areca_packet[19] = m_encnum - 1;                // enc#
-
-       // ----- BEGIN TO SETUP CHECKSUM -----
-       for ( int loop = 3; loop < areca_packet_len - 1; loop++ )
-       {
-               cs += areca_packet[loop]; 
-       }
-       areca_packet[areca_packet_len-1] = cs;
-
-       // ----- BEGIN TO SEND TO ARECA DRIVER ------
-       int expected = 0;       
-       unsigned char return_buff[2048];
-       memset(return_buff, 0, sizeof(return_buff));
-
-       expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_RQBUFFER, NULL, 0, NULL);
-        if (expected==-3) {
-           return set_err(EIO);
-       }
-
-       expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_WQBUFFER, NULL, 0, NULL);
-       expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_WRITE_WQBUFFER, areca_packet, areca_packet_len, NULL);
-       if ( expected > 0 )
-       {
-               expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_READ_RQBUFFER, return_buff, sizeof(return_buff), NULL);
-       }
-       if ( expected < 0 )
-       {
-               return -1;
-       }
-
-       // ----- VERIFY THE CHECKSUM -----
-       cs = 0;
-       for ( int loop = 3; loop < expected - 1; loop++ )
-       {
-               cs += return_buff[loop]; 
-       }
-
-       if ( return_buff[expected - 1] != cs )
-       {
-               return set_err(EIO);
-       }
-
-       sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
-       if ( ata_out->status )
-       {
-               if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
-                && !nonempty((unsigned char *)in.buffer, in.size)) 
-                {
-                   return set_err(ENODEV, "No drive on port %d", m_disknum);
-                } 
-       }
-
-       // returns with data
-       if (readdata)
-       {
-               memcpy(in.buffer, &return_buff[7], in.size); 
-       }
-
-       // Return register values
-       {
-           ata_out_regs_48bit & r = out.out_regs;
-           r.error           = ata_out->error;
-           r.sector_count_16 = ata_out->sector_count;
-           r.lba_low_16      = ata_out->sector_number;
-           r.lba_mid_16      = ata_out->cylinder_low;
-           r.lba_high_16     = ata_out->cylinder_high;
-           r.status          = ata_out->status;
-       }
-       return true;
+  return true;
 }
 
 
+bool freebsd_areca_scsi_device::arcmsr_unlock()
+{
+  return true;
+}
+
 
 /////////////////////////////////////////////////////////////////////////////
 /// Implement CCISS RAID support with old functions
@@ -1599,10 +1275,11 @@ smart_device * freebsd_scsi_device::autodetect_open()
   // Use INQUIRY to detect type
 
   // 3ware ?
-  if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4)) {
+  if (!memcmp(req_buff + 8, "3ware", 5) || !memcmp(req_buff + 8, "AMCC", 4) ||
+      !strcmp("tws",m_camdev->sim_name) || !strcmp("twa",m_camdev->sim_name)) {
     close();
-    set_err(EINVAL, "AMCC/3ware controller, please try adding '-d 3ware,N',\n"
-                    "you may need to replace %s with /dev/twaN or /dev/tweN", get_dev_name());
+    set_err(EINVAL, "3ware/LSI controller, please try adding '-d 3ware,N',\n"
+                    "you may need to replace %s with /dev/twaN, /dev/tweN or /dev/twsN", get_dev_name());
     return this;
   }
 
@@ -1791,10 +1468,13 @@ bool get_dev_names_cam(std::vector<std::string> & names, bool show_all)
       } else if (ccb.cdm.matches[i].type == DEV_MATCH_PERIPH && 
           (skip_device == 0 || show_all)) { 
         /* One device may be populated as many peripherals (pass0 & da0 for example). 
-        * We are searching for latest name
+        * We are searching for best name
         */
         periph_result =  &ccb.cdm.matches[i].result.periph_result;
-        devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
+        /* Prefer non-"pass" names */
+        if (devname.empty() || strncmp(periph_result->periph_name, "pass", 4) != 0) {
+          devname = strprintf("%s%s%d", _PATH_DEV, periph_result->periph_name, periph_result->unit_number);
+           }
         changed = 0;
       };
       if ((changed == 1 || show_all) && !devname.empty()) {
@@ -2200,6 +1880,7 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
   // 3Ware ?
   static const char * fbsd_dev_twe_ctrl = "/dev/twe";
   static const char * fbsd_dev_twa_ctrl = "/dev/twa";
+  static const char * fbsd_dev_tws_ctrl = "/dev/tws";
   int disknum = -1, n1 = -1, n2 = -1, contr = -1;
 
   if (sscanf(type, "3ware,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
@@ -2213,7 +1894,8 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
     }
 
     // guess 3ware device type based on device name
-    if (!strncmp(fbsd_dev_twa_ctrl, name, strlen(fbsd_dev_twa_ctrl))){
+    if (str_starts_with(name, fbsd_dev_twa_ctrl) ||
+        str_starts_with(name, fbsd_dev_tws_ctrl)   ) {
       contr=CONTROLLER_3WARE_9000_CHAR;
     }
     if (!strncmp(fbsd_dev_twe_ctrl, name, strlen(fbsd_dev_twe_ctrl))){
@@ -2221,12 +1903,12 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
     }
 
     if(contr == -1){
-      set_err(EINVAL, "3ware controller type unknown, use %sX or %sX devices", 
-        fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl);
+      set_err(EINVAL, "3ware controller type unknown, use %sX, %sX or %sX devices", 
+        fbsd_dev_twe_ctrl, fbsd_dev_twa_ctrl, fbsd_dev_tws_ctrl);
       return 0;
     }
     return new freebsd_escalade_device(this, name, contr, disknum);
-  } 
+  }
 
   // Highpoint ?
   int controller = -1, channel = -1; disknum = 1;
@@ -2263,7 +1945,7 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
       set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
       return 0;
     }
-    return new freebsd_cciss_device(this, name, disknum);
+    return get_sat_device("sat,auto", new freebsd_cciss_device(this, name, disknum));
   }
 #if FREEBSDVER > 800100
   // adaX devices ?
@@ -2282,7 +1964,7 @@ smart_device * freebsd_smart_interface::get_custom_smart_device(const char * nam
       set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
       return 0;
     }
-    return new freebsd_areca_device(this, name, disknum);
+    return new freebsd_areca_ata_device(this, name, disknum, encnum);
   }
 
   return 0;
index d00e9f657ef21c9beeded2d3eaf3b163b93f15f6..a22442f49f56f7fb8f588e1c1883aa5cf3e3d6bd 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -82,7 +82,7 @@
 #ifndef OS_FREEBSD_H_
 #define OS_FREEBSD_H_
 
-#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 3266 2011-02-21 16:33:04Z chrfranke $"
+#define OS_FREEBSD_H_CVSID "$Id: os_freebsd.h 3727 2012-12-13 17:23:06Z samm2 $"
 
 #define MAX_NUM_DEV 26
 
index e4b79995fba5d57f6c257cdf7ca2be6751615a09..09998335c75aca7f83f4b7d5fcbbbd6800c33269 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * os_generic.c
+ * os_generic.cpp
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
@@ -13,8 +13,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
+ *
  */
 
 
@@ -71,6 +71,7 @@
 
 // These are needed to define prototypes and structures for the
 // functions defined below
+#include "int64.h"
 #include "atacmds.h"
 #include "utility.h"
 
@@ -82,8 +83,8 @@
 // should have one *_H_CVSID macro appearing below for each file
 // appearing with #include "*.h" above.  Please list these (below) in
 // alphabetic/dictionary order.
-const char *os_XXXX_c_cvsid="$Id: os_generic.cpp 3191 2010-10-27 19:55:33Z chrfranke $" \
-ATACMDS_H_CVSID CONFIG_H_CVSID OS_GENERIC_H_CVSID UTILITY_H_CVSID;
+const char * os_XXXX_cpp_cvsid="$Id: os_generic.cpp 3579 2012-07-20 17:50:12Z chrfranke $"
+  ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_GENERIC_H_CVSID UTILITY_H_CVSID;
 
 // This is here to prevent compiler warnings for unused arguments of
 // functions.
index fcc6b1217fafdefbd86e1432a66e0f51b1a97979..4c0ba6682231b974643e104562dc05f0c675aa63 100644 (file)
@@ -12,8 +12,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -25,7 +25,7 @@
 // In the three following lines, change 'GENERIC' to your OS name
 #ifndef OS_GENERIC_H_
 #define OS_GENERIC_H_
-#define OS_GENERIC_H_CVSID "$Id: os_generic.h,v 1.7 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_GENERIC_H_CVSID "$Id: os_generic.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 // Additional material should start here.  Note: to keep the '-V' CVS
 // reporting option working as intended, you should only #include
index b68575a12e348a995accad3021b1808b025b0a06..164e8f794efdf98532cacaf6018c11b891b94cea 100644 (file)
@@ -65,6 +65,7 @@
 #include <stddef.h>  // for offsetof()
 #include <sys/uio.h>
 #include <sys/types.h>
+#include <dirent.h>
 #ifndef makedev // old versions of types.h do not include sysmacros.h
 #include <sys/sysmacros.h>
 #endif
@@ -82,6 +83,7 @@
 
 #include "dev_interface.h"
 #include "dev_ata_cmd_set.h"
+#include "dev_areca.h"
 
 #ifndef ENOTSUP
 #define ENOTSUP ENOSYS
@@ -89,9 +91,9 @@
 
 #define ARGUSED(x) ((void)(x))
 
-const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3558 2012-06-05 16:42:05Z chrfranke $"
+const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3738 2012-12-17 12:01:35Z samm2 $"
   OS_LINUX_H_CVSID;
-
+extern unsigned char failuretest_permissive;
 
 namespace os_linux { // No need to publish anything, name provided for Doxygen
 
@@ -121,13 +123,15 @@ protected:
   int get_fd() const
     { return m_fd; }
 
+  void set_fd(int fd)
+    { m_fd = fd; }
+
 private:
   int m_fd; ///< filedesc, -1 if not open.
   int m_flags; ///< Flags for ::open()
   int m_retry_flags; ///< Flags to retry ::open(), -1 if no retry
 };
 
-
 linux_smart_device::~linux_smart_device() throw()
 {
   if (m_fd >= 0)
@@ -201,7 +205,6 @@ static const char  smartctl_examples[] =
                  "           on Areca RAID controller)\n"
   ;
 
-
 /////////////////////////////////////////////////////////////////////////////
 /// Linux ATA support
 
@@ -242,7 +245,6 @@ linux_ata_device::linux_ata_device(smart_interface * intf, const char * dev_name
 //   0 if the command succeeded and disk SMART status is "OK"
 //   1 if the command succeeded and disk SMART status is "FAILING"
 
-
 #define BUFFER_LENGTH (4+512)
 
 int linux_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
@@ -849,7 +851,6 @@ linux_scsi_device::linux_scsi_device(smart_interface * intf,
 {
 }
 
-
 bool linux_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
 {
   int status = do_normal_scsi_cmnd_io(get_fd(), iop, scsi_debugmode);
@@ -875,7 +876,7 @@ public:
 
   virtual bool open();
   virtual bool close();
+
   virtual bool scsi_pass_through(scsi_cmnd_io *iop);
 
 private:
@@ -885,11 +886,11 @@ private:
   int m_fd;
 
   bool (linux_megaraid_device::*pt_cmd)(int cdblen, void *cdb, int dataLen, void *data,
-    int senseLen, void *sense, int report);
+    int senseLen, void *sense, int report, int direction);
   bool megasas_cmd(int cdbLen, void *cdb, int dataLen, void *data,
-    int senseLen, void *sense, int report);
+    int senseLen, void *sense, int report, int direction);
   bool megadev_cmd(int cdbLen, void *cdb, int dataLen, void *data,
-    int senseLen, void *sense, int report);
+    int senseLen, void *sense, int report, int direction);
 };
 
 linux_megaraid_device::linux_megaraid_device(smart_interface *intf,
@@ -900,6 +901,7 @@ linux_megaraid_device::linux_megaraid_device(smart_interface *intf,
    m_fd(-1), pt_cmd(0)
 {
   set_info().info_name = strprintf("%s [megaraid_disk_%02d]", dev_name, m_disknum);
+  set_info().dev_type = strprintf("megaraid,%d", tgt);
 }
 
 linux_megaraid_device::~linux_megaraid_device() throw()
@@ -939,61 +941,55 @@ smart_device * linux_megaraid_device::autodetect_open()
 
   // Use INQUIRY to detect type
   {
-    // SAT or USB ?
+    // SAT?
     ata_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
-    if (newdev) {
-      // NOTE: 'this' is now owned by '*newdev'
-      newdev->close();
-      newdev->set_err(ENOSYS, "SATA device detected,\n"
-        "MegaRAID SAT layer is reportedly buggy, use '-d sat+megaraid,N' to try anyhow");
+    if (newdev) // NOTE: 'this' is now owned by '*newdev'
       return newdev;
-    }
   }
 
   // Nothing special found
   return this;
 }
 
-
 bool linux_megaraid_device::open()
 {
   char line[128];
-  int   mjr, n1;
-  FILE *fp;
+  int   mjr;
   int report = scsi_debugmode;
 
-  if (!linux_smart_device::open())
-    return false;
-
-  /* Get device HBA */
-  struct sg_scsi_id sgid;
-  if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) {
-    m_hba = sgid.host_no;
-  }
-  else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) {
-    int err = errno;
+  if(sscanf(get_dev_name(),"/dev/bus/%d", &m_hba) == 0) {
+    if (!linux_smart_device::open())
+      return false;
+    /* Get device HBA */
+    struct sg_scsi_id sgid;
+    if (ioctl(get_fd(), SG_GET_SCSI_ID, &sgid) == 0) {
+      m_hba = sgid.host_no;
+    }
+    else if (ioctl(get_fd(), SCSI_IOCTL_GET_BUS_NUMBER, &m_hba) != 0) {
+      int err = errno;
+      linux_smart_device::close();
+      return set_err(err, "can't get bus number");
+    } // we dont need this device anymore
     linux_smart_device::close();
-    return set_err(err, "can't get bus number");
   }
-
   /* Perform mknod of device ioctl node */
-  fp = fopen("/proc/devices", "r");
+  FILE * fp = fopen("/proc/devices", "r");
   while (fgets(line, sizeof(line), fp) != NULL) {
-       n1=0;
-       if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
-          n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
-          if(report > 0)
-            pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
-          if (n1 >= 0 || errno == EEXIST)
-             break;
-       }
-       else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {
-          n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0));
-          if(report > 0)
-            pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
-          if (n1 >= 0 || errno == EEXIST)
-             break;
-       }
+    int n1 = 0;
+    if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
+      n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
+      if(report > 0)
+        pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
+      if (n1 >= 0 || errno == EEXIST)
+        break;
+    }
+    else if (sscanf(line, "%d megadev%n", &mjr, &n1) == 1 && n1 == 11) {
+      n1=mknod("/dev/megadev0", S_IFCHR, makedev(mjr, 0));
+      if(report > 0)
+        pout("Creating /dev/megadev0 = %d\n", n1 >= 0 ? 0 : errno);
+      if (n1 >= 0 || errno == EEXIST)
+        break;
+    }
   }
   fclose(fp);
 
@@ -1009,7 +1005,7 @@ bool linux_megaraid_device::open()
     linux_smart_device::close();
     return set_err(err, "cannot open /dev/megaraid_sas_ioctl_node or /dev/megadev0");
   }
-
+  set_fd(m_fd);
   return true;
 }
 
@@ -1018,7 +1014,8 @@ bool linux_megaraid_device::close()
   if (m_fd >= 0)
     ::close(m_fd);
   m_fd = -1; m_hba = 0; pt_cmd = 0;
-  return linux_smart_device::close();
+  set_fd(m_fd);
+  return true;
 }
 
 bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
@@ -1061,23 +1058,25 @@ bool linux_megaraid_device::scsi_pass_through(scsi_cmnd_io *iop)
       return set_err(ENOSYS, "ATA return descriptor not supported by controller firmware");
   }
   // SMART WRITE LOG SECTOR causing media errors
-  if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 && iop->cmnd[14] == ATA_SMART_CMD 
-       && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) || 
-      (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 && iop->cmnd[9] == ATA_SMART_CMD &&
-        iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) 
-    return set_err(ENOSYS, "SMART WRITE LOG SECTOR command is not supported by controller firmware"); 
-
+  if ((iop->cmnd[0] == SAT_ATA_PASSTHROUGH_16 // SAT16 WRITE LOG
+      && iop->cmnd[14] == ATA_SMART_CMD && iop->cmnd[3]==0 && iop->cmnd[4] == ATA_SMART_WRITE_LOG_SECTOR) ||
+      (iop->cmnd[0] == SAT_ATA_PASSTHROUGH_12 // SAT12 WRITE LOG
+       && iop->cmnd[9] == ATA_SMART_CMD && iop->cmnd[3] == ATA_SMART_WRITE_LOG_SECTOR)) 
+  {
+    if(!failuretest_permissive)
+       return set_err(ENOSYS, "SMART WRITE LOG SECTOR may cause problems, try with -T permissive to force"); 
+  }
   if (pt_cmd == NULL)
     return false;
-  return (this->*pt_cmd)(iop->cmnd_len, iop->cmnd, 
+  return (this->*pt_cmd)(iop->cmnd_len, iop->cmnd,
     iop->dxfer_len, iop->dxferp,
-    iop->max_sense_len, iop->sensep, report);
+    iop->max_sense_len, iop->sensep, report, iop->dxfer_dir);
 }
 
 /* Issue passthrough scsi command to PERC5/6 controllers */
 bool linux_megaraid_device::megasas_cmd(int cdbLen, void *cdb, 
   int dataLen, void *data,
-  int /*senseLen*/, void * /*sense*/, int /*report*/)
+  int /*senseLen*/, void * /*sense*/, int /*report*/, int dxfer_dir)
 {
   struct megasas_pthru_frame   *pthru;
   struct megasas_iocpacket     uio;
@@ -1092,7 +1091,21 @@ bool linux_megaraid_device::megasas_cmd(int cdbLen, void *cdb,
   pthru->lun = 0;
   pthru->cdb_len = cdbLen;
   pthru->timeout = 0;
-  pthru->flags = MFI_FRAME_DIR_READ;
+  switch (dxfer_dir) {
+    case DXFER_NONE:
+      pthru->flags = MFI_FRAME_DIR_NONE;
+      break;
+    case DXFER_FROM_DEVICE:
+      pthru->flags = MFI_FRAME_DIR_READ;
+      break;
+    case DXFER_TO_DEVICE:
+      pthru->flags = MFI_FRAME_DIR_WRITE;
+      break;
+    default:
+      pout("megasas_cmd: bad dxfer_dir\n");
+      return set_err(EINVAL, "megasas_cmd: bad dxfer_dir\n");
+  }
+
   if (dataLen > 0) {
     pthru->sge_count = 1;
     pthru->data_xfer_len = dataLen;
@@ -1126,7 +1139,7 @@ bool linux_megaraid_device::megasas_cmd(int cdbLen, void *cdb,
 /* Issue passthrough scsi commands to PERC2/3/4 controllers */
 bool linux_megaraid_device::megadev_cmd(int cdbLen, void *cdb, 
   int dataLen, void *data,
-  int /*senseLen*/, void * /*sense*/, int /*report*/)
+  int /*senseLen*/, void * /*sense*/, int /*report*/, int /* dir */)
 {
   struct uioctl_t uio;
   int rc;
@@ -1261,7 +1274,6 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
   int                selinux_enforced = security_getenforce();
 #endif
 
-
   /* First try to open up /proc/devices */
   if (!(file = fopen("/proc/devices", "r"))) {
     pout("Error opening /proc/devices to check/create 3ware device nodes\n");
@@ -1301,7 +1313,7 @@ static int setup_3ware_nodes(const char *nodename, const char *driver_name)
 #endif
   /* Now check if nodes are correct */
   for (index=0; index<16; index++) {
-    sprintf(nodestring, "/dev/%s%d", nodename, index);
+    snprintf(nodestring, sizeof(nodestring), "/dev/%s%d", nodename, index);
 #ifdef WITH_SELINUX
     /* Get context of the node and set it as the default */
     if (selinux_enabled) {
@@ -1434,7 +1446,6 @@ bool linux_escalade_device::open()
 //   0 if the command succeeded and disk SMART status is "OK"
 //   1 if the command succeeded and disk SMART status is "FAILING"
 
-
 /* 512 is the max payload size: increase if needed */
 #define BUFFER_LEN_678K      ( sizeof(TW_Ioctl)                  ) // 1044 unpacked, 1041 packed
 #define BUFFER_LEN_678K_CHAR ( sizeof(TW_New_Ioctl)+512-1        ) // 1539 unpacked, 1536 packed
@@ -1644,84 +1655,39 @@ bool linux_escalade_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out
   return true;
 }
 
-
 /////////////////////////////////////////////////////////////////////////////
 /// Areca RAID support
 
-class linux_areca_device
-: public /*implements*/ ata_device,
+///////////////////////////////////////////////////////////////////
+// SATA(ATA) device behind Areca RAID Controller
+class linux_areca_ata_device
+: public /*implements*/ areca_ata_device,
   public /*extends*/ linux_smart_device
 {
 public:
-  linux_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
-
-protected:
-  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); 
-
-private:
-  int m_disknum; ///< Disk number.
-  int m_encnum;  ///< Enclosure number.
+  linux_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  virtual smart_device * autodetect_open();
+  virtual bool arcmsr_lock();
+  virtual bool arcmsr_unlock();
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
 };
 
-
-// PURPOSE
-//   This is an interface routine meant to isolate the OS dependent
-//   parts of the code, and to provide a debugging interface.  Each
-//   different port and OS needs to provide it's own interface.  This
-//   is the linux interface to the Areca "arcmsr" driver.  It allows ATA
-//   commands to be passed through the SCSI driver.
-// DETAILED DESCRIPTION OF ARGUMENTS
-//   fd: is the file descriptor provided by open()
-//   disknum is the disk number (0 to 15) in the RAID array
-//   command: defines the different operations.
-//   select: additional input data if needed (which log, which type of
-//           self-test).
-//   data:   location to write output data, if needed (512 bytes).
-//   Note: not all commands use all arguments.
-// RETURN VALUES
-//  -1 if the command failed
-//   0 if the command succeeded,
-//   STATUS_CHECK routine: 
-//  -1 if the command failed
-//   0 if the command succeeded and disk SMART status is "OK"
-//   1 if the command succeeded and disk SMART status is "FAILING"
-
-
-/*DeviceType*/
-#define ARECA_SATA_RAID                        0x90000000
-/*FunctionCode*/
-#define FUNCTION_READ_RQBUFFER                 0x0801
-#define FUNCTION_WRITE_WQBUFFER                0x0802
-#define FUNCTION_CLEAR_RQBUFFER                0x0803
-#define FUNCTION_CLEAR_WQBUFFER                0x0804
-
-/* ARECA IO CONTROL CODE*/
-#define ARCMSR_IOCTL_READ_RQBUFFER             (ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER)
-#define ARCMSR_IOCTL_WRITE_WQBUFFER            (ARECA_SATA_RAID | FUNCTION_WRITE_WQBUFFER)
-#define ARCMSR_IOCTL_CLEAR_RQBUFFER            (ARECA_SATA_RAID | FUNCTION_CLEAR_RQBUFFER)
-#define ARCMSR_IOCTL_CLEAR_WQBUFFER            (ARECA_SATA_RAID | FUNCTION_CLEAR_WQBUFFER)
-#define ARECA_SIG_STR                                                  "ARCMSR"
-
-// The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
-typedef struct _SRB_IO_CONTROL
-{
-       unsigned int HeaderLength;
-       unsigned char Signature[8];
-       unsigned int Timeout;
-       unsigned int ControlCode;
-       unsigned int ReturnCode;
-       unsigned int Length;
-} sSRB_IO_CONTROL;
-
-typedef struct _SRB_BUFFER
+///////////////////////////////////////////////////////////////////
+// SAS(SCSI) device behind Areca RAID Controller
+class linux_areca_scsi_device
+: public /*implements*/ areca_scsi_device,
+  public /*extends*/ linux_smart_device
 {
-       sSRB_IO_CONTROL srbioctl;
-       unsigned char   ioctldatabuffer[1032]; // the buffer to put the command data to/from firmware
-} sSRB_BUFFER;
+public:
+  linux_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  virtual smart_device * autodetect_open();
+  virtual bool arcmsr_lock();
+  virtual bool arcmsr_unlock();
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
+};
 
 // Looks in /proc/scsi to suggest correct areca devices
-// If hint not NULL, return device path guess
-static int find_areca_in_proc(char *hint)
+static int find_areca_in_proc()
 {
     const char* proc_format_string="host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n";
 
@@ -1760,9 +1726,6 @@ static int find_areca_in_proc(char *hint)
         dev++;
        if (id == 16 && type == 3) {
           // devices with id=16 and type=3 might be Areca controllers
-          if (!found && hint) {
-              sprintf(hint, "/dev/sg%d", dev);
-          }
           pout("Device /dev/sg%d appears to be an Areca controller.\n", dev);
            found++;
         }
@@ -1771,404 +1734,117 @@ static int find_areca_in_proc(char *hint)
     return 0;
 }
 
-
-#if 0 // For debugging areca code
-
-static void dumpdata(unsigned char *block, int len)
-{
-       int ln = (len / 16) + 1;         // total line#
-       unsigned char c;
-       int pos = 0;
-
-       printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
-       printf("      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F      ASCII      \n");
-       printf("=====================================================================\n");
-
-       for ( int l = 0; l < ln && len; l++ )
-       {
-               // printf the line# and the HEX data
-               // if a line data length < 16 then append the space to the tail of line to reach 16 chars
-               printf("%02X | ", l);
-               for ( pos = 0; pos < 16 && len; pos++, len-- )
-               {
-                       c = block[l*16+pos];    
-                       printf("%02X ", c);
-               }
-
-               if ( pos < 16 )
-               {
-                       for ( int loop = pos; loop < 16; loop++ )
-                       {
-                               printf("   ");
-                       }
-               }
-
-               // print ASCII char
-               for ( int loop = 0; loop < pos; loop++ )
-               {
-                       c = block[l*16+loop];
-                       if ( c >= 0x20 && c <= 0x7F )
-                       {
-                               printf("%c", c);
-                       }
-                       else
-                       {
-                               printf(".");
-                       }
-               }
-               printf("\n");
-       }   
-       printf("=====================================================================\n");
+// Areca RAID Controller(SATA Disk)
+linux_areca_ata_device::linux_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca"),
+  linux_smart_device(O_RDWR | O_EXCL | O_NONBLOCK)
+{
+  set_disknum(disknum);
+  set_encnum(encnum);
+  set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
 }
 
-#endif
+smart_device * linux_areca_ata_device::autodetect_open()
+{
+  int is_ata = 1;
 
-static int arcmsr_command_handler(int fd, unsigned long arcmsr_cmd, unsigned char *data, int data_len, void *ext_data /* reserved for further use */)
-{
-       ARGUSED(ext_data);
-
-       int ioctlreturn = 0;
-       sSRB_BUFFER sBuf;
-       struct scsi_cmnd_io io_hdr;  
-       int dir = DXFER_TO_DEVICE;
-
-       UINT8 cdb[10];
-       UINT8 sense[32];
-
-       unsigned char *areca_return_packet;
-       int total = 0;
-       int expected = -1;
-       unsigned char return_buff[2048];
-       unsigned char *ptr = &return_buff[0];
-       memset(return_buff, 0, sizeof(return_buff));
-
-       memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
-       memset(&io_hdr, 0, sizeof(io_hdr));
-       memset(cdb, 0, sizeof(cdb));
-       memset(sense, 0, sizeof(sense));
-
-
-       sBuf.srbioctl.HeaderLength = sizeof(sSRB_IO_CONTROL);   
-       memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
-       sBuf.srbioctl.Timeout = 10000;      
-       sBuf.srbioctl.ControlCode = ARCMSR_IOCTL_READ_RQBUFFER;
-
-       switch ( arcmsr_cmd )
-       {
-       // command for writing data to driver
-       case ARCMSR_IOCTL_WRITE_WQBUFFER:   
-               if ( data && data_len )
-               {
-                       sBuf.srbioctl.Length = data_len;    
-                       memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
-               }
-               // commands for clearing related buffer of driver
-       case ARCMSR_IOCTL_CLEAR_RQBUFFER:
-       case ARCMSR_IOCTL_CLEAR_WQBUFFER:
-               cdb[0] = 0x3B; //SCSI_WRITE_BUF command;
-               break;
-               // command for reading data from driver
-       case ARCMSR_IOCTL_READ_RQBUFFER:    
-               cdb[0] = 0x3C; //SCSI_READ_BUF command;
-               dir = DXFER_FROM_DEVICE;
-               break;
-       default:
-               // unknown arcmsr commands
-               return -1;
-       }
+  // autodetect device type
+  is_ata = arcmsr_get_dev_type();
+  if(is_ata < 0)
+  {
+    set_err(EIO);
+    return this;
+  }
 
-       cdb[1] = 0x01;
-       cdb[2] = 0xf0;    
-       //
-       // cdb[5][6][7][8] areca defined command code( to/from driver )
-       //    
-       cdb[5] = (char)( arcmsr_cmd >> 24);
-       cdb[6] = (char)( arcmsr_cmd >> 16);
-       cdb[7] = (char)( arcmsr_cmd >> 8);
-       cdb[8] = (char)( arcmsr_cmd & 0x0F );
-
-       io_hdr.dxfer_dir = dir;
-       io_hdr.dxfer_len = sizeof(sBuf);
-       io_hdr.dxferp = (unsigned char *)&sBuf;  
-       io_hdr.cmnd = cdb;
-       io_hdr.cmnd_len = sizeof(cdb);
-       io_hdr.sensep = sense;  
-       io_hdr.max_sense_len = sizeof(sense);
-       io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
-
-       while ( 1 )
-       {
-               ioctlreturn = do_normal_scsi_cmnd_io(fd, &io_hdr, 0);
-               if ( ioctlreturn || io_hdr.scsi_status )
-               {
-                       // errors found
-                       break;
-               }
-
-               if ( arcmsr_cmd != ARCMSR_IOCTL_READ_RQBUFFER )
-               {
-                       // if succeeded, just returns the length of outgoing data
-                       return data_len;
-               }
-
-               if ( sBuf.srbioctl.Length )
-               {
-                       //dumpdata(&sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
-                       memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
-                       ptr += sBuf.srbioctl.Length;
-                       total += sBuf.srbioctl.Length;
-                       // the returned bytes enough to compute payload length ?
-                       if ( expected < 0 && total >= 5 )
-                       {
-                               areca_return_packet = (unsigned char *)&return_buff[0];
-                               if ( areca_return_packet[0] == 0x5E && 
-                                        areca_return_packet[1] == 0x01 && 
-                                        areca_return_packet[2] == 0x61 )
-                               {
-                                       // valid header, let's compute the returned payload length,
-                                       // we expected the total length is 
-                                       // payload + 3 bytes header + 2 bytes length + 1 byte checksum
-                                       expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
-                               }
-                       }
-
-                       if ( total >= 7 && total >= expected )
-                       {
-                               //printf("total bytes received = %d, expected length = %d\n", total, expected);
-
-                               // ------ Okay! we received enough --------
-                               break;
-                       }
-               }
-       }
+  if(is_ata == 1)
+  {
+    // SATA device
+    return this;
+  }
 
-       // Deal with the different error cases
-       if ( ioctlreturn )
-       {
-               pout("do_scsi_cmnd_io with write buffer failed code = %x\n", ioctlreturn);
-               return -2;
-       }
+  // SAS device
+  smart_device_auto_ptr newdev(new linux_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
+  close();
+  delete this;
+  newdev->open();      // TODO: Can possibly pass open fd
 
+  return newdev.release();
+}
 
-       if ( io_hdr.scsi_status )
-       {
-               pout("io_hdr.scsi_status with write buffer failed code = %x\n", io_hdr.scsi_status);
-               return -3;
-       }
+int linux_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
+{
+  int ioctlreturn = 0;
 
+  if(!is_open()) {
+      if(!open()){
+          find_areca_in_proc();
+      }
+  }
 
-       if ( data )
-       {
-               memcpy(data, return_buff, total);
-       }
+  ioctlreturn = do_normal_scsi_cmnd_io(get_fd(), iop, scsi_debugmode);
+  if ( ioctlreturn || iop->scsi_status )
+  {
+    // errors found
+    return -1;
+  }
 
-       return total;
+  return ioctlreturn;
 }
 
+bool linux_areca_ata_device::arcmsr_lock()
+{
+  return true;
+}
 
-linux_areca_device::linux_areca_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+bool linux_areca_ata_device::arcmsr_unlock()
+{
+  return true;
+}
+
+// Areca RAID Controller(SAS Device)
+linux_areca_scsi_device::linux_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
 : smart_device(intf, dev_name, "areca", "areca"),
-  linux_smart_device(O_RDWR | O_EXCL | O_NONBLOCK),
-  m_disknum(disknum),
-  m_encnum(encnum)
+  linux_smart_device(O_RDWR | O_EXCL | O_NONBLOCK)
 {
+  set_disknum(disknum);
+  set_encnum(encnum);
   set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
 }
 
-// Areca RAID Controller
-// int linux_areca_device::ata_command_interface(smart_command_set command, int select, char * data)
-bool linux_areca_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) 
-{
-if (!ata_cmd_is_ok(in, 
-    true, // data_out_support 
-    false, // TODO: multi_sector_support 
-    true) // ata_48bit_support 
-    )
-    return false; 
-
-       // ATA input registers
-       typedef struct _ATA_INPUT_REGISTERS
-       {
-               unsigned char features;
-               unsigned char sector_count;
-               unsigned char sector_number;
-               unsigned char cylinder_low; 
-               unsigned char cylinder_high;    
-               unsigned char device_head;  
-               unsigned char command;      
-               unsigned char reserved[8];
-               unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
-       } sATA_INPUT_REGISTERS;
-
-       // ATA output registers
-       // Note: The output registers is re-sorted for areca internal use only
-       typedef struct _ATA_OUTPUT_REGISTERS
-       {
-               unsigned char error;
-               unsigned char status;
-               unsigned char sector_count;
-               unsigned char sector_number;
-               unsigned char cylinder_low; 
-               unsigned char cylinder_high;
-       }sATA_OUTPUT_REGISTERS;
-
-       // Areca packet format for outgoing:
-       // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
-       // B[3~4] : 2 bytes command length + variant data length, little endian
-       // B[5]   : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
-       // B[6~last-1] : variant bytes payload data
-       // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
-       // 
-       // 
-       //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte 
-       // +--------------------------------------------------------------------------------+
-       // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
-       // +--------------------------------------------------------------------------------+
-       // 
-
-       //Areca packet format for incoming:
-       // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
-       // B[3~4] : 2 bytes payload length, little endian
-       // B[5~last-1] : variant bytes returned payload data
-       // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
-       // 
-       // 
-       //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte 
-       // +-------------------------------------------------------------------+
-       // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
-       // +-------------------------------------------------------------------+
-       unsigned char    areca_packet[640];
-       int areca_packet_len = sizeof(areca_packet);
-       unsigned char cs = 0;   
-
-       sATA_INPUT_REGISTERS *ata_cmd;
-
-       // For debugging
-#if 0
-       memset(sInq, 0, sizeof(sInq));
-       scsiStdInquiry(fd, (unsigned char *)sInq, (int)sizeof(sInq));
-       dumpdata((unsigned char *)sInq, sizeof(sInq));
-#endif
-       memset(areca_packet, 0, areca_packet_len);
-
-       // ----- BEGIN TO SETUP HEADERS -------
-       areca_packet[0] = 0x5E;
-       areca_packet[1] = 0x01;
-       areca_packet[2] = 0x61;
-       areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
-       areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
-       areca_packet[5] = 0x1c; // areca defined code for ATA passthrough command
-
-       // ----- BEGIN TO SETUP PAYLOAD DATA -----
-       memcpy(&areca_packet[7], "SmrT", 4);    // areca defined password
-       ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
-
-       // Set registers
-        {
-           const ata_in_regs_48bit & r = in.in_regs;
-           ata_cmd->features     = r.features_16;
-           ata_cmd->sector_count  = r.sector_count_16;
-           ata_cmd->sector_number = r.lba_low_16;
-           ata_cmd->cylinder_low  = r.lba_mid_16;
-           ata_cmd->cylinder_high = r.lba_high_16;
-           ata_cmd->device_head   = r.device;
-           ata_cmd->command      = r.command;
-       }
-       bool readdata = false; 
-       if (in.direction == ata_cmd_in::data_in) { 
-           readdata = true;
-           // the command will read data
-           areca_packet[6] = 0x13;
-       }
-       else if ( in.direction == ata_cmd_in::no_data )
-       {
-               // the commands will return no data
-               areca_packet[6] = 0x15;
-       }
-       else if (in.direction == ata_cmd_in::data_out) 
-       {
-               // the commands will write data
-               memcpy(ata_cmd->data, in.buffer, in.size);
-               areca_packet[6] = 0x14;
-       }
-       else {
-           // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
-           return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type");
-       }
-
-       areca_packet[11] = m_disknum - 1;  // disk#
-       areca_packet[19] = m_encnum - 1;   // enc#
-
-       // ----- BEGIN TO SETUP CHECKSUM -----
-       for ( int loop = 3; loop < areca_packet_len - 1; loop++ )
-       {
-               cs += areca_packet[loop]; 
-       }
-       areca_packet[areca_packet_len-1] = cs;
-
-       // ----- BEGIN TO SEND TO ARECA DRIVER ------
-       int expected = 0;       
-       unsigned char return_buff[2048];
-       memset(return_buff, 0, sizeof(return_buff));
-
-       expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_RQBUFFER, NULL, 0, NULL);
-        if (expected==-3) {
-           find_areca_in_proc(NULL);
-           return set_err(EIO);
-       }
-
-       expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_CLEAR_WQBUFFER, NULL, 0, NULL);
-       expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_WRITE_WQBUFFER, areca_packet, areca_packet_len, NULL);
-       if ( expected > 0 )
-       {
-               expected = arcmsr_command_handler(get_fd(), ARCMSR_IOCTL_READ_RQBUFFER, return_buff, sizeof(return_buff), NULL);
-       }
-       if ( expected < 0 )
-       {
-               return -1;
-       }
+smart_device * linux_areca_scsi_device::autodetect_open()
+{
+  return this;
+}
 
-       // ----- VERIFY THE CHECKSUM -----
-       cs = 0;
-       for ( int loop = 3; loop < expected - 1; loop++ )
-       {
-               cs += return_buff[loop]; 
-       }
+int linux_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
+{
+  int ioctlreturn = 0;
 
-       if ( return_buff[expected - 1] != cs )
-       {
-               return set_err(EIO);
-       }
+  if(!is_open()) {
+      if(!open()){
+          find_areca_in_proc();
+      }
+  }
 
-       sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
-       if ( ata_out->status )
-       {
-               if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
-                && !nonempty((unsigned char *)in.buffer, in.size)) 
-                {
-                   return set_err(ENODEV, "No drive on port %d", m_disknum);
-                } 
-       }
+  ioctlreturn = do_normal_scsi_cmnd_io(get_fd(), iop, scsi_debugmode);
+  if ( ioctlreturn || iop->scsi_status )
+  {
+    // errors found
+    return -1;
+  }
 
-       // returns with data
-       if (readdata)
-       {
-               memcpy(in.buffer, &return_buff[7], in.size); 
-       }
+  return ioctlreturn;
+}
 
-       // Return register values
-       {
-           ata_out_regs_48bit & r = out.out_regs;
-           r.error           = ata_out->error;
-           r.sector_count_16 = ata_out->sector_count;
-           r.lba_low_16      = ata_out->sector_number;
-           r.lba_mid_16      = ata_out->cylinder_low;
-           r.lba_high_16     = ata_out->cylinder_high;
-           r.status          = ata_out->status;
-       }
-       return true;
+bool linux_areca_scsi_device::arcmsr_lock()
+{
+  return true;
 }
 
+bool linux_areca_scsi_device::arcmsr_unlock()
+{
+  return true;
+}
 
 /////////////////////////////////////////////////////////////////////////////
 /// Marvell support
@@ -2317,7 +1993,6 @@ int linux_marvell_device::ata_command_interface(smart_command_set command, int s
   return 0;
 }
 
-
 /////////////////////////////////////////////////////////////////////////////
 /// Highpoint RAID support
 
@@ -2550,7 +2225,6 @@ int linux_highpoint_device::ata_command_interface(smart_command_set command, int
   return 0;
 }
 
-
 #if 0 // TODO: Migrate from 'smart_command_set' to 'ata_in_regs' OR remove the function
 // Utility function for printing warnings
 void printwarning(smart_command_set command){
@@ -2582,7 +2256,6 @@ void printwarning(smart_command_set command){
 }
 #endif
 
-
 /////////////////////////////////////////////////////////////////////////////
 /// SCSI open with autodetection support
 
@@ -2640,7 +2313,9 @@ smart_device * linux_scsi_device::autodetect_open()
     }
 
     // DELL?
-    if (!memcmp(req_buff + 8, "DELL    PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)) {
+    if (!memcmp(req_buff + 8, "DELL    PERC", 12) || !memcmp(req_buff + 8, "MegaRAID", 8)
+        || !memcmp(req_buff + 16, "PERC H700", 9) || !memcmp(req_buff + 8, "LSI\0",4)
+    ) {
       close();
       set_err(EINVAL, "DELL or MegaRaid controller, please try adding '-d megaraid,N'");
       return this;
@@ -2676,7 +2351,6 @@ smart_device * linux_scsi_device::autodetect_open()
   return this;
 }
 
-
 //////////////////////////////////////////////////////////////////////
 // USB bridge ID detection
 
@@ -2730,7 +2404,6 @@ static bool get_usb_id(const char * name, unsigned short & vendor_id,
   return true;
 }
 
-
 //////////////////////////////////////////////////////////////////////
 /// Linux interface
 
@@ -2759,8 +2432,11 @@ protected:
 private:
   bool get_dev_list(smart_device_list & devlist, const char * pattern,
     bool scan_ata, bool scan_scsi, const char * req_type, bool autodetect);
-
+  bool get_dev_megasas(smart_device_list & devlist);
   smart_device * missing_option(const char * opt);
+  int megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf,
+    size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp);
+  int megasas_pd_add_list(int bus_no, smart_device_list & devlist);
 };
 
 std::string linux_smart_interface::get_os_version_str()
@@ -2779,7 +2455,6 @@ std::string linux_smart_interface::get_app_examples(const char * appname)
   return "";
 }
 
-
 // we are going to take advantage of the fact that Linux's devfs will only
 // have device entries for devices that exist.  So if we get the equivalent of
 // ls /dev/hd[a-t], we have all the ATA devices on the system
@@ -2876,7 +2551,61 @@ bool linux_smart_interface::get_dev_list(smart_device_list & devlist,
 
   // free memory
   globfree(&globbuf);
+  return true;
+}
 
+// getting devices from LSI SAS MegaRaid, if available
+bool linux_smart_interface::get_dev_megasas(smart_device_list & devlist)
+{
+  /* Scanning of disks on MegaRaid device */
+  /* Perform mknod of device ioctl node */
+  int   mjr, n1;
+  char line[128];
+  bool scan_megasas = false;
+  FILE * fp = fopen("/proc/devices", "r");
+  while (fgets(line, sizeof(line), fp) != NULL) {
+    n1=0;
+    if (sscanf(line, "%d megaraid_sas_ioctl%n", &mjr, &n1) == 1 && n1 == 22) {
+      scan_megasas = true;
+      n1=mknod("/dev/megaraid_sas_ioctl_node", S_IFCHR, makedev(mjr, 0));
+      if(scsi_debugmode > 0)
+        pout("Creating /dev/megaraid_sas_ioctl_node = %d\n", n1 >= 0 ? 0 : errno);
+      if (n1 >= 0 || errno == EEXIST)
+        break;
+    }
+  }
+  fclose(fp);
+
+  if(!scan_megasas)
+    return false;
+
+  // getting bus numbers with megasas devices
+  struct dirent *ep;
+  unsigned int host_no = 0;
+  char sysfsdir[256];
+
+  /* we are using sysfs to get list of all scsi hosts */
+  DIR * dp = opendir ("/sys/class/scsi_host/");
+  if (dp != NULL)
+  {
+    while ((ep = readdir (dp)) != NULL) {
+      if (!sscanf(ep->d_name, "host%d", &host_no)) 
+        continue;
+      /* proc_name should be megaraid_sas */
+      snprintf(sysfsdir, sizeof(sysfsdir) - 1,
+        "/sys/class/scsi_host/host%d/proc_name", host_no);
+      if((fp = fopen(sysfsdir, "r")) == NULL)
+        continue;
+      if(fgets(line, sizeof(line), fp) != NULL && !strncmp(line,"megaraid_sas",12)) {
+        megasas_pd_add_list(host_no, devlist);
+      }
+      fclose(fp);
+    }
+    (void) closedir (dp);
+  } else { /* sysfs not mounted ? */
+    for(unsigned i = 0; i <=16; i++) // trying to add devices on first 16 buses
+      megasas_pd_add_list(i, devlist);
+  }
   return true;
 }
 
@@ -2904,6 +2633,8 @@ bool linux_smart_interface::scan_smart_devices(smart_device_list & devlist,
     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);
+    // get device list from the megaraid device
+    get_dev_megasas(devlist);
   }
 
   // if we found traditional links, we are done
@@ -2931,6 +2662,99 @@ smart_device * linux_smart_interface::missing_option(const char * opt)
   return 0;
 }
 
+int
+linux_smart_interface::megasas_dcmd_cmd(int bus_no, uint32_t opcode, void *buf,
+  size_t bufsize, uint8_t *mbox, size_t mboxlen, uint8_t *statusp)
+{
+  struct megasas_iocpacket ioc;
+
+  if ((mbox != NULL && (mboxlen == 0 || mboxlen > MFI_MBOX_SIZE)) ||
+    (mbox == NULL && mboxlen != 0)) 
+  {
+    errno = EINVAL;
+    return (-1);
+  }
+
+  bzero(&ioc, sizeof(ioc));
+  struct megasas_dcmd_frame * dcmd = &ioc.frame.dcmd;
+  ioc.host_no = bus_no;
+  if (mbox)
+    bcopy(mbox, dcmd->mbox.w, mboxlen);
+  dcmd->cmd = MFI_CMD_DCMD;
+  dcmd->timeout = 0;
+  dcmd->flags = 0;
+  dcmd->data_xfer_len = bufsize;
+  dcmd->opcode = opcode;
+
+  if (bufsize > 0) {
+    dcmd->sge_count = 1;
+    dcmd->data_xfer_len = bufsize;
+    dcmd->sgl.sge32[0].phys_addr = (intptr_t)buf;
+    dcmd->sgl.sge32[0].length = (uint32_t)bufsize;
+    ioc.sge_count = 1;
+    ioc.sgl_off = offsetof(struct megasas_dcmd_frame, sgl);
+    ioc.sgl[0].iov_base = buf;
+    ioc.sgl[0].iov_len = bufsize;
+  }
+
+  int fd;
+  if ((fd = ::open("/dev/megaraid_sas_ioctl_node", O_RDWR)) <= 0) {
+    return (errno);
+  }
+
+  int r = ioctl(fd, MEGASAS_IOC_FIRMWARE, &ioc);
+  if (r < 0) {
+    return (r);
+  }
+
+  if (statusp != NULL)
+    *statusp = dcmd->cmd_status;
+  else if (dcmd->cmd_status != MFI_STAT_OK) {
+    fprintf(stderr, "command %x returned error status %x\n",
+      opcode, dcmd->cmd_status);
+    errno = EIO;
+    return (-1);
+  }
+  return (0);
+}
+
+int
+linux_smart_interface::megasas_pd_add_list(int bus_no, smart_device_list & devlist)
+{
+  /*
+  * Keep fetching the list in a loop until we have a large enough
+  * buffer to hold the entire list.
+  */
+  megasas_pd_list * list = 0;
+  for (unsigned list_size = 1024; ; ) {
+    list = (megasas_pd_list *)realloc(list, list_size);
+    if (!list)
+      throw std::bad_alloc();
+    bzero(list, list_size);
+    if (megasas_dcmd_cmd(bus_no, MFI_DCMD_PD_GET_LIST, list, list_size, NULL, 0,
+      NULL) < 0) 
+    {
+      free(list);
+      return (-1);
+    }
+    if (list->size <= list_size)
+      break;
+    list_size = list->size;
+  }
+
+  // adding all SCSI devices
+  for (unsigned i = 0; i < list->count; i++) {
+    if(list->addr[i].scsi_dev_type)
+      continue; /* non disk device found */
+    char line[128];
+    snprintf(line, sizeof(line) - 1, "/dev/bus/%d", bus_no);
+    smart_device * dev = new linux_megaraid_device(this, line, 0, list->addr[i].device_id);
+    devlist.push_back(dev);
+  }
+  free(list);
+  return (0);
+}
+
 // Return kernel release as integer ("2.6.31" -> 206031)
 static unsigned get_kernel_release()
 {
@@ -3068,7 +2892,7 @@ smart_device * linux_smart_interface::get_custom_smart_device(const char * name,
       set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
       return 0;
     }
-    return new linux_areca_device(this, name, disknum, encnum);
+    return new linux_areca_ata_device(this, name, disknum, encnum);
   }
 
   // Highpoint ?
@@ -3107,7 +2931,7 @@ smart_device * linux_smart_interface::get_custom_smart_device(const char * name,
       set_err(EINVAL, "Option -d cciss,N (N=%d) must have 0 <= N <= 127", disknum);
       return 0;
     }
-    return new linux_cciss_device(this, name, disknum);
+    return get_sat_device("sat,auto", new linux_cciss_device(this, name, disknum));
   }
 #endif // HAVE_LINUX_CCISS_IOCTL_H
 
@@ -3129,7 +2953,6 @@ std::string linux_smart_interface::get_valid_custom_dev_types_str()
 
 } // namespace
 
-
 /////////////////////////////////////////////////////////////////////////////
 /// Initialize platform interface and register with smi()
 
index 5fabc0475dcebced9f37a45344871f05283b99cf..3cb2f3362e7bed80a64f35cd963faa3a0361b834 100644 (file)
@@ -24,8 +24,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -38,7 +38,7 @@
 #ifndef OS_LINUX_H_
 #define OS_LINUX_H_
 
-#define OS_LINUX_H_CVSID "$Id: os_linux.h,v 1.27 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_LINUX_H_CVSID "$Id: os_linux.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 /* 
    The following definitions/macros/prototypes are used for three
index 09d4a7ef88d7a787d0c8252cbcb2c64424331cc3..dce2d9d5a6a6a69f70ed478e9abbc74da4feb2e4 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
@@ -26,7 +26,7 @@
 #include <errno.h>
 #include <unistd.h>
 
-const char * os_netbsd_cpp_cvsid = "$Id: os_netbsd.cpp 3265 2011-02-21 16:21:14Z chrfranke $"
+const char * os_netbsd_cpp_cvsid = "$Id: os_netbsd.cpp 3806 2013-03-29 20:17:03Z chrfranke $"
   OS_NETBSD_H_CVSID;
 
 /* global variable holding byte count of allocated memory */
@@ -169,14 +169,6 @@ deviceclose(int fd)
   return close(fd);
 }
 
-int
-marvell_command_interface(int fd, smart_command_set command, int select, char *data)
-{ return -1; }
-
-int
-highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{ return -1; }
-
 int
 ata_command_interface(int fd, smart_command_set command, int select, char *data)
 {
@@ -345,20 +337,6 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data)
   return 0;
 }
 
-int
-escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data)
-{
-  printwarning(NO_3WARE, NULL);
-  return -1;
-}
-
-int
-areca_command_interface(int fd, int disknum, smart_command_set command, int select, char *data)
-{
-  printwarning(NO_ARECA, NULL);
-  return -1;
-}
-
 int
 do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
 {
index 772181503edd6548093a6343cf1595131478cb93..6b8c758a231f2021a3607a53ff2756b012d75e3b 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -24,7 +24,7 @@
 #ifndef OS_NETBSD_H_
 #define OS_NETBSD_H_
 
-#define OS_NETBSD_H_CVSID "$Id: os_netbsd.h,v 1.10 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_NETBSD_H_CVSID "$Id: os_netbsd.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 #include <sys/device.h>
 #include <sys/param.h>
index 7acf85aa81a27a498a46b28d8cc43a2ca0e1ec4a..896b88d11be42afde167dbe1c3f795ad113e415e 100644 (file)
@@ -13,8 +13,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
@@ -27,7 +27,7 @@
 
 #include <errno.h>
 
-const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 3265 2011-02-21 16:21:14Z chrfranke $"
+const char * os_openbsd_cpp_cvsid = "$Id: os_openbsd.cpp 3727 2012-12-13 17:23:06Z samm2 $"
   OS_OPENBSD_H_CVSID;
 
 /* global variable holding byte count of allocated memory */
@@ -173,14 +173,6 @@ deviceclose(int fd)
   return close(fd);
 }
 
-int
-marvell_command_interface(int fd, smart_command_set command, int select, char *data)
-{ return -1; }
-
-int
-highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{ return -1; }
-
 int
 ata_command_interface(int fd, smart_command_set command, int select, char *data)
 {
@@ -359,20 +351,6 @@ ata_command_interface(int fd, smart_command_set command, int select, char *data)
   return 0;
 }
 
-int
-escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data)
-{
-  printwarning(NO_3WARE, NULL);
-  return -1;
-}
-
-int
-areca_command_interface(int fd, int disknum, smart_command_set command, int select, char *data)
-{
-  printwarning(NO_ARECA, NULL);
-  return -1;
-}
-
 int
 do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report)
 {
index be1553d24cdfbb7c04721c0a1ae6123dceed4b01..b686c781188f3a7a1faf360df6fc3e351723ee05 100644 (file)
@@ -13,8 +13,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -26,7 +26,7 @@
 #ifndef OS_OPENBSD_H_
 #define OS_OPENBSD_H_
 
-#define OS_OPENBSD_H_CVSID "$Id: os_openbsd.h,v 1.6 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_OPENBSD_H_CVSID "$Id: os_openbsd.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 /* from NetBSD: atareg.h,v 1.17, by Manuel Bouyer */
 /* Actually fits _perfectly_ into OBSDs wdcreg.h, but... */
index 16f4e2e6b262c31a732943be34d26e6da993ab57..7ad7f190e086cc942177ce19ea0f16329b494b18 100644 (file)
@@ -11,8 +11,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 /*
@@ -31,7 +31,7 @@
 #include "os_os2.h"
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl
-const char *os_XXXX_c_cvsid="$Id: os_os2.cpp 3191 2010-10-27 19:55:33Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_os2.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \
 ATACMDS_H_CVSID OS_XXXX_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // global handle to device driver
@@ -522,31 +522,6 @@ int ata_command_interface(int device, smart_command_set command, int select, cha
   return 0;
 }
 
-int marvell_command_interface(int fd, smart_command_set command, int select, char *data){
-  unsupported(1);
-  return -1;
-}
-
-int highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{
-  unsupported(1);
-  return -1;
-}
-
-// Interface to ATA devices behind 3ware escalade RAID controller
-// cards.  Same description as ata_command_interface() above except
-// that 0 <= disknum <= 15 specifies the ATA disk attached to the
-// controller.
-int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data){
-  unsupported(2);
-  return -1;
-}
-
-int areca_command_interface(int fd, int disknum, smart_command_set command, int select, char *data){
-  unsupported(2);
-  return -1;
-}
-
 // Interface to SCSI devices.  See os_linux.c
 int do_scsi_cmnd_io(int fd, struct scsi_cmnd_io * iop, int report) {
   unsupported(3);
index 57d3ad39cd3760077c2ae5627628299d5dda2488..3d8cb860c82db66b44f7e2f09b3fd524d5daf2d3 100644 (file)
--- a/os_os2.h
+++ b/os_os2.h
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifndef OS_OS2_H_
 #define OS_OS2_H_
 
-#define OS_XXXX_H_CVSID "$Id: os_os2.h,v 1.5 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_XXXX_H_CVSID "$Id: os_os2.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 // Additional material should start here.  Note: to keep the '-V' CVS
 // reporting option working as intended, you should only #include
index 7dbcafee96f4960b24fb1169ca9b5c7a4968159a..0f039f4a758d8b3d9a8fac9f8d33f4f0e24a6624 100644 (file)
 // This is to include whatever structures and prototypes you define in
 // os_generic.h
 #include "os_qnxnto.h"
+#include <errno.h>
 
 // Needed by '-V' option (CVS versioning) of smartd/smartctl.  You
 // should have one *_H_CVSID macro appearing below for each file
 // appearing with #include "*.h" above.  Please list these (below) in
 // alphabetic/dictionary order.
-const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3191 2010-10-27 19:55:33Z chrfranke $" \
+const char *os_XXXX_c_cvsid="$Id: os_qnxnto.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_QNXNTO_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 
@@ -370,57 +371,6 @@ int                  status,rc;
   return(rc);
 }
 //----------------------------------------------------------------------------------------------
-int marvell_command_interface(int fd, smart_command_set command, int select, char *data)
-{
-  ARGUSED(fd);
-  ARGUSED(command);
-  ARGUSED(select);
-  ARGUSED(data);
-  unsupported();
-  return -1;
-}
-//----------------------------------------------------------------------------------------------
-int highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{
-  ARGUSED(fd);
-  ARGUSED(command);
-  ARGUSED(select);
-  ARGUSED(data);
-  unsupported();
-  return -1;
-}
-//----------------------------------------------------------------------------------------------
-// Interface to ATA devices behind 3ware escalade/apache RAID
-// controller cards.  Same description as ata_command_interface()
-// above except that 0 <= disknum <= 15 specifies the ATA disk
-// attached to the controller, and controller_type specifies the
-// precise type of 3ware controller.  See os_linux.c
-int escalade_command_interface(int fd,int disknum,int controller_type,smart_command_set command,int select,char *data)
-{
-  ARGUSED(fd);
-  ARGUSED(disknum);
-  ARGUSED(controller_type);
-  ARGUSED(command);
-  ARGUSED(select);
-  ARGUSED(data);
-
-  unsupported();
-  return -1;
-}
-
-int areca_command_interface(int fd,int disknum,smart_command_set command,int select,char *data)
-{
-  ARGUSED(fd);
-  ARGUSED(disknum);
-  ARGUSED(command);
-  ARGUSED(select);
-  ARGUSED(data);
-
-  unsupported();
-  return -1;
-}
-//----------------------------------------------------------------------------------------------
-#include <errno.h>
 // Interface to SCSI devices.  See os_linux.c
 int do_scsi_cmnd_io(int fd,struct scsi_cmnd_io * iop,int report)
 {
index 2feb2359772cd64b3d0ca1cd15cb1aadd6dbad03..3b12cd42a5b4b0524e553dd0664a6a8bad427f5a 100644 (file)
@@ -12,8 +12,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -23,7 +23,7 @@
  */
 #ifndef OS_QNXNTO_H_
 #define OS_QNXNTO_H_
-#define OS_QNXNTO_H_CVSID "$Id: os_qnxnto.h,v 1.2 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_QNXNTO_H_CVSID "$Id: os_qnxnto.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 // Additional material should start here.  Note: to keep the '-V' CVS
 // reporting option working as intended, you should only #include
index b36f700902d893f9a3f00510c678323b6f838b70..793aec7fe52f7706e34880f97d49259030e6de75 100644 (file)
@@ -12,8 +12,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
@@ -39,9 +39,9 @@
 
 extern long long bytes;
 
-static const char *filenameandversion="$Id: os_solaris.cpp,v 1.32 2008/06/12 21:46:31 ballen4705 Exp $";
+static const char *filenameandversion="$Id: os_solaris.cpp 3806 2013-03-29 20:17:03Z chrfranke $";
 
-const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp,v 1.32 2008/06/12 21:46:31 ballen4705 Exp $" \
+const char *os_XXXX_c_cvsid="$Id: os_solaris.cpp 3806 2013-03-29 20:17:03Z chrfranke $" \
 ATACMDS_H_CVSID CONFIG_H_CVSID INT64_H_CVSID OS_SOLARIS_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID;
 
 // The printwarning() function warns about unimplemented functions
@@ -285,17 +285,6 @@ static void swap_sector(void *p)
 #endif
 
 // Interface to ATA devices.  See os_linux.c
-int marvell_command_interface(int fd, smart_command_set command, int select, char *data){
-    ARGUSED(fd); ARGUSED(command); ARGUSED(select); ARGUSED(data);
-    return -1;
-}
-
-int highpoint_command_interface(int fd, smart_command_set command, int select, char *data)
-{
-    ARGUSED(fd); ARGUSED(command); ARGUSED(select); ARGUSED(data);
-    return -1;
-}
-
 int ata_command_interface(int fd, smart_command_set command, int select, char *data){
 #if defined(__sparc)
     int err;
@@ -352,25 +341,6 @@ int ata_command_interface(int fd, smart_command_set command, int select, char *d
     return -1;
 }
 
-// Interface to ATA devices behind 3ware escalade RAID controller cards.  See os_linux.c
-int escalade_command_interface(int fd, int disknum, int escalade_type, smart_command_set command, int select, char *data){
-  ARGUSED(fd);  ARGUSED(disknum);  ARGUSED(escalade_type);
-  ARGUSED(command);  ARGUSED(select);  ARGUSED(data); 
-
-  if (printwarning(1))
-    return -1;
-  return -1;
-}
-
-int areca_command_interface(int fd, int disknum, smart_command_set command, int select, char *data){
-  ARGUSED(fd);  ARGUSED(disknum);
-  ARGUSED(command);  ARGUSED(select);  ARGUSED(data); 
-
-  if (printwarning(1))
-    return -1;
-  return -1;
-}
-
 #include <errno.h>
 #include <sys/scsi/generic/commands.h>
 #include <sys/scsi/generic/status.h>
index 4813a92a4a27a0624f56de56c137729116126e79..70dc3ee87471a10ab6054452c780b45e2bd0dbb3 100644 (file)
@@ -12,8 +12,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -25,7 +25,7 @@
 #ifndef OS_SOLARIS_H_
 #define OS_SOLARIS_H_
 
-#define OS_SOLARIS_H_CVSID "$Id: os_solaris.h,v 1.14 2008/03/04 22:09:47 ballen4705 Exp $\n"
+#define OS_SOLARIS_H_CVSID "$Id: os_solaris.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 // Additional material should start here.  Note: to keep the '-V' CVS
 // reporting option working as intended, you should only #include
index 8f016948be0f3c8c88bfe0e64f4c121459db63a1..fc502b93703f623d2b2adfdbe851eca93e75f9b4 100644 (file)
@@ -16,8 +16,8 @@
 !   General Public License for more details.
 ! 
 !   You should have received a copy of the GNU General Public License
-!   along with this program; if not, write to the Free Software
-!   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+!   along with this program; if not, write to the Free Software Foundation,
+!   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 ! 
 ! 
 !        --------------------------------------------------------
@@ -97,7 +97,7 @@
        .section        ".rodata"
        .align 8
 .LLC0:
-       .asciz  "$Id: os_solaris_ata.s,v 1.6 2008/03/04 22:09:47 ballen4705 Exp $"
+       .asciz  "$Id: os_solaris_ata.s 3728 2012-12-13 17:57:50Z chrfranke $"
        .global os_solaris_ata_s_cvsid
        .section        ".data"
        .align 4
index ace6d32efeb08ff0cfa43b7b50969e8a18ab5c30..6c5fc5178d795eb36b9d62b43db198f7898ca3b6 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2004-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2004-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
  * Copyright (C) 2012    Hank Wu <hank@areca.com.tw>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -28,6 +28,7 @@
 
 #include "dev_interface.h"
 #include "dev_ata_cmd_set.h"
+#include "dev_areca.h"
 
 #include "os_win32/wmiquery.h"
 
 #include <windows.h>
 
 #if HAVE_NTDDDISK_H
-// i686-w64-mingw32, x86_64-w64-mingw32
+// i686-pc-cygwin, i686-w64-mingw32, x86_64-w64-mingw32
 // (Missing: FILE_DEVICE_SCSI)
 #include <devioctl.h>
 #include <ntdddisk.h>
 #include <ntddscsi.h>
 #include <ntddstor.h>
 #elif HAVE_DDK_NTDDDISK_H
-// i686-pc-cygwin, i686-pc-mingw32, i586-mingw32msvc
+// older i686-pc-cygwin, i686-pc-mingw32, i586-mingw32msvc
 // (Missing: IOCTL_IDE_PASS_THROUGH, IOCTL_ATA_PASS_THROUGH, FILE_DEVICE_SCSI)
 #include <ddk/ntdddisk.h>
 #include <ddk/ntddscsi.h>
 #include <winioctl.h>
 #endif
 
+#ifndef _WIN32
+// csmisas.h requires _WIN32 but w32api-headers no longer define it on Cygwin
+#define _WIN32
+#endif
+
 // CSMI support
 #include "csmisas.h"
 
-#ifdef __CYGWIN__
-#include <cygwin/version.h> // CYGWIN_VERSION_DLL_MAJOR
+// Silence -Wunused-local-typedefs warning from g++ >= 4.8
+#if __GNUC__ >= 4
+#define ATTR_UNUSED __attribute__((unused))
+#else
+#define ATTR_UNUSED /**/
 #endif
 
 // Macro to check constants at compile time using a dummy typedef
 #define ASSERT_CONST(c, n) \
-  typedef char assert_const_##c[((c) == (n)) ? 1 : -1]
+  typedef char assert_const_##c[((c) == (n)) ? 1 : -1] ATTR_UNUSED
 #define ASSERT_SIZEOF(t, n) \
-  typedef char assert_sizeof_##t[(sizeof(t) == (n)) ? 1 : -1]
+  typedef char assert_sizeof_##t[(sizeof(t) == (n)) ? 1 : -1] ATTR_UNUSED
 
 #ifndef _WIN64
 #define SELECT_WIN_32_64(x32, x64) (x32)
 #define SELECT_WIN_32_64(x32, x64) (x64)
 #endif
 
-const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3558 2012-06-05 16:42:05Z chrfranke $";
-
-// Disable Win9x/ME specific code if no longer supported by compiler.
-#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)
-    // Win9x/ME support was dropped in MSVC9 (cl.exe 15.0)
-  #else
-    #define WIN9X_SUPPORT 1
-  #endif
-#endif
+const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3804 2013-03-27 20:39:41Z chrfranke $";
 
 /////////////////////////////////////////////////////////////////////////////
 // Windows I/O-controls, some declarations are missing in the include files
@@ -320,16 +316,6 @@ namespace os_win32 { // no need to publish anything, name provided for Doxygen
 #pragma warning(disable:4250)
 #endif
 
-// Running on Win9x/ME ?
-#if WIN9X_SUPPORT
-// Set true in win9x_smart_interface ctor.
-static bool win9x = false;
-#else
-// Never true (const allows compiler to remove dead code).
-const  bool win9x = false;
-#endif
-
-
 class win_smart_device
 : virtual public /*implements*/ smart_device
 {
@@ -382,9 +368,10 @@ private:
   std::string m_options;
   bool m_usr_options; // options set by user?
   bool m_admin; // open with admin access?
+  int m_phydrive; // PhysicalDriveN or -1
   bool m_id_is_cached; // ata_identify_is_cached() return value.
-  bool m_is_3ware; // AMCC/3ware controller detected?
-  int m_drive, m_port;
+  bool m_is_3ware; // LSI/3ware controller detected?
+  int m_port; // LSI/3ware port
   int m_smartver_state;
 };
 
@@ -409,32 +396,6 @@ private:
 
 /////////////////////////////////////////////////////////////////////////////
 
-#if WIN9X_SUPPORT
-
-class win_aspi_device
-: public /*implements*/ scsi_device
-{
-public:
-  win_aspi_device(smart_interface * intf, const char * dev_name, const char * req_type);
-
-  virtual bool is_open() const;
-
-  virtual bool open();
-
-  virtual bool close();
-
-  virtual bool scsi_pass_through(scsi_cmnd_io * iop);
-
-private:
-  int m_adapter;
-  unsigned char m_id;
-};
-
-#endif // WIN9X_SUPPORT
-
-
-//////////////////////////////////////////////////////////////////////
-
 class csmi_device
 : virtual public /*extends*/ smart_device
 {
@@ -535,58 +496,46 @@ private:
 /////////////////////////////////////////////////////////////////////////////
 /// Areca RAID support
 
-/* ARECA IO CONTROL CODE*/
-#define ARCMSR_IOCTL_READ_RQBUFFER           0x90002004
-#define ARCMSR_IOCTL_WRITE_WQBUFFER          0x90002008
-#define ARCMSR_IOCTL_CLEAR_RQBUFFER          0x9000200C
-#define ARCMSR_IOCTL_CLEAR_WQBUFFER          0x90002010
-#define ARCMSR_IOCTL_RETURN_CODE_3F          0x90002018
-#define ARECA_SIG_STR              "ARCMSR"
-
-
-// The SRB_IO_CONTROL & SRB_BUFFER structures are used to communicate(to/from) to areca driver
-typedef struct _SRB_IO_CONTROL
-{
-  unsigned int HeaderLength;
-  unsigned char Signature[8];
-  unsigned int Timeout;
-  unsigned int ControlCode;
-  unsigned int ReturnCode;
-  unsigned int Length;
-} sSRB_IO_CONTROL;
-
-typedef struct _SRB_BUFFER
-{
-  sSRB_IO_CONTROL srbioctl;
-  unsigned char   ioctldatabuffer[1032]; // the buffer to put the command data to/from firmware
-} sSRB_BUFFER;
-
-class win_areca_device
-: public /*implements*/ ata_device,
+///////////////////////////////////////////////////////////////////
+// SATA(ATA) device behind Areca RAID Controller
+class win_areca_ata_device
+: public /*implements*/ areca_ata_device,
   public /*extends*/ win_smart_device
 {
 public:
-  win_areca_device(smart_interface * intf, const char * dev_name, HANDLE fh, int disknum, int encnum = 1);
-
-  static int arcmsr_command_handler(HANDLE fh, unsigned long arcmsr_cmd, unsigned char *data, int data_len);
-
-protected:
+  win_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
   virtual bool open();
+  virtual smart_device * autodetect_open();
+  virtual bool arcmsr_lock();
+  virtual bool arcmsr_unlock();
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
 
-  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
+private:
+  HANDLE m_mutex;
+};
 
-  bool arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
+///////////////////////////////////////////////////////////////////
+// SAS(SCSI) device behind Areca RAID Controller
+class win_areca_scsi_device
+: public /*implements*/ areca_scsi_device,
+  public /*extends*/ win_smart_device
+{
+public:
+  win_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum = 1);
+  virtual bool open();
+  virtual smart_device * autodetect_open();
+  virtual bool arcmsr_lock();
+  virtual bool arcmsr_unlock();
+  virtual int arcmsr_do_scsi_io(struct scsi_cmnd_io * iop);
 
 private:
-  int m_disknum; ///< Disk number.
-  int m_encnum;  ///< Enclosure number.
+  HANDLE m_mutex;
 };
 
 
 //////////////////////////////////////////////////////////////////////
-// Platform specific interfaces
+// Platform specific interface
 
-// Common to all windows flavors
 class win_smart_interface
 : public /*implements part of*/ smart_interface
 {
@@ -599,52 +548,14 @@ public:
   virtual int64_t get_timer_usec();
 #endif
 
-//virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
-//  const char * pattern = 0);
-
-protected:
-  virtual ata_device * get_ata_device(const char * name, const char * type);
-
-//virtual scsi_device * get_scsi_device(const char * name, const char * type);
-
-  virtual smart_device * autodetect_smart_device(const char * name);
-};
-
-#if WIN9X_SUPPORT
-
-// Win9x/ME reduced functionality
-class win9x_smart_interface
-: public /*extends*/ win_smart_interface
-{
-public:
-  win9x_smart_interface()
-    { win9x = true; }
-
-  virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
-    const char * pattern = 0);
-
-protected:
-  virtual scsi_device * get_scsi_device(const char * name, const char * type);
-
-private:
-  bool ata_scan(smart_device_list & devlist);
-
-  bool scsi_scan(smart_device_list & devlist);
-};
-
-#endif // WIN9X_SUPPORT
-
-// WinNT,2000,XP,...
-class winnt_smart_interface
-: public /*extends*/ win_smart_interface
-{
-public:
   virtual bool disable_system_auto_standby(bool disable);
 
   virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
     const char * pattern = 0);
 
 protected:
+  virtual ata_device * get_ata_device(const char * name, const char * type);
+
   virtual scsi_device * get_scsi_device(const char * name, const char * type);
 
   virtual smart_device * autodetect_smart_device(const char * name);
@@ -721,7 +632,7 @@ std::string win_smart_interface::get_os_version_str()
                                                    :   "2008r2"); break;
     case VER_PLATFORM_WIN32_NT     <<16|0x0600| 2:
       w = (vi.wProductType == VER_NT_WORKSTATION   ?   "win8"
-                                                   :   "win8s"); break;
+                                                   :   "2012"); break;
     default: w = 0; break;
   }
 
@@ -732,9 +643,9 @@ std::string win_smart_interface::get_os_version_str()
 #endif
 
   if (!w)
-    snprintf(vptr, vlen, "-%s%lu.%lu%s",
+    snprintf(vptr, vlen, "-%s%u.%u%s",
       (vi.dwPlatformId==VER_PLATFORM_WIN32_NT ? "nt" : "9x"),
-      vi.dwMajorVersion, vi.dwMinorVersion, w64);
+      (unsigned)vi.dwMajorVersion, (unsigned)vi.dwMinorVersion, w64);
   else if (vi.wServicePackMinor)
     snprintf(vptr, vlen, "-%s%s-sp%u.%u", w, w64, vi.wServicePackMajor, vi.wServicePackMinor);
   else if (vi.wServicePackMajor)
@@ -819,25 +730,17 @@ ata_device * win_smart_interface::get_ata_device(const char * name, const char *
   return new win_ata_device(this, name, type);
 }
 
-#ifdef WIN9X_SUPPORT
-
-scsi_device * win9x_smart_interface::get_scsi_device(const char * name, const char * type)
+scsi_device * win_smart_interface::get_scsi_device(const char * name, const char * type)
 {
-  return new win_aspi_device(this, name, type);
+  return new win_scsi_device(this, name, type);
 }
 
-#endif
-
-scsi_device * winnt_smart_interface::get_scsi_device(const char * name, const char * type)
+static int sdxy_to_phydrive(const char (& xy)[2+1])
 {
-  const char * testname = skipdev(name);
-  if (!strncmp(testname, "scsi", 4))
-#if WIN9X_SUPPORT
-    return new win_aspi_device(this, name, type);
-#else
-    return (set_err(EINVAL, "ASPI interface not supported"), (scsi_device *)0);
-#endif
-  return new win_scsi_device(this, name, type);
+  int phydrive = xy[0] - 'a';
+  if (xy[1])
+    phydrive = (phydrive + 1) * ('z' - 'a' + 1) + (xy[1] - 'a');
+  return phydrive;
 }
 
 static win_dev_type get_dev_type(const char * name, int & phydrive)
@@ -857,9 +760,9 @@ static win_dev_type get_dev_type(const char * name, int & phydrive)
     return (type != DEV_UNKNOWN ? type : DEV_SCSI);
   }
 
-  char drive[1+1] = "";
-  if (sscanf(name, "sd%1[a-z]", drive) == 1) {
-    phydrive = drive[0] - 'a';
+  char drive[2+1] = "";
+  if (sscanf(name, "sd%2[a-z]", drive) == 1) {
+    phydrive = sdxy_to_phydrive(drive);
     return get_phy_drive_type(phydrive);
   }
 
@@ -869,27 +772,11 @@ static win_dev_type get_dev_type(const char * name, int & phydrive)
   return DEV_UNKNOWN;
 }
 
-smart_device * win_smart_interface::autodetect_smart_device(const char * name)
-{
-  const char * testname = skipdev(name);
-  if (!strncmp(testname, "hd", 2))
-    return new win_ata_device(this, name, "");
-#if WIN9X_SUPPORT
-  if (!strncmp(testname, "scsi", 4))
-    return new win_aspi_device(this, name, "");
-#endif
-  if (!strncmp(testname, "tw_cli", 6))
-    return new win_tw_cli_device(this, name, "");
-  return 0;
-}
-
-
-smart_device * winnt_smart_interface::get_custom_smart_device(const char * name, const char * type)
+smart_device * win_smart_interface::get_custom_smart_device(const char * name, const char * type)
 {
   // Areca?
   int disknum = -1, n1 = -1, n2 = -1;
   int encnum = 1;
-  HANDLE fh = INVALID_HANDLE_VALUE;
   char devpath[32];
 
   if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
@@ -911,18 +798,16 @@ smart_device * winnt_smart_interface::get_custom_smart_device(const char * name,
        1. scan from "\\\\.\\scsi[0]:" up to "\\\\.\\scsi[ARECA_MAX_CTLR_NUM]:" and
        2. map arcmsrX into "\\\\.\\scsiX"
       */
-      for (int idx = 0; idx < ARECA_MAX_CTLR_NUM; idx++) {
+     for (int idx = 0; idx < ARECA_MAX_CTLR_NUM; idx++) {
         memset(devpath, 0, sizeof(devpath));
-        sprintf(devpath, "\\\\.\\scsi%d:", idx);
-        if ( (fh = CreateFile( devpath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
-                               NULL, OPEN_EXISTING, 0, NULL )) != INVALID_HANDLE_VALUE ) {
-          if (win_areca_device::arcmsr_command_handler(fh, ARCMSR_IOCTL_RETURN_CODE_3F, NULL, 0) == 0) {
-            if (ctlrindex-- == 0) {
-              return new win_areca_device(this, devpath, fh, disknum, encnum);
-            }
+        snprintf(devpath, sizeof(devpath), "\\\\.\\scsi%d:", idx);
+        win_areca_ata_device *arcdev = new win_areca_ata_device(this, devpath, disknum, encnum);
+        if(arcdev->arcmsr_probe()) {
+          if(ctlrindex-- == 0) {
+            return arcdev;
           }
-          CloseHandle(fh);
         }
+        delete arcdev;
       }
       set_err(ENOENT, "No Areca controller found");
     }
@@ -933,19 +818,22 @@ smart_device * winnt_smart_interface::get_custom_smart_device(const char * name,
   return 0;
 }
 
-std::string winnt_smart_interface::get_valid_custom_dev_types_str()
+std::string win_smart_interface::get_valid_custom_dev_types_str()
 {
   return "areca,N[/E]";
 }
 
 
-smart_device * winnt_smart_interface::autodetect_smart_device(const char * name)
+smart_device * win_smart_interface::autodetect_smart_device(const char * name)
 {
-  smart_device * dev = win_smart_interface::autodetect_smart_device(name);
-  if (dev)
-    return dev;
+  const char * testname = skipdev(name);
+  if (str_starts_with(testname, "hd"))
+    return new win_ata_device(this, name, "");
+
+  if (str_starts_with(testname, "tw_cli"))
+    return new win_tw_cli_device(this, name, "");
 
-  if (!strncmp(skipdev(name), "csmi", 4))
+  if (str_starts_with(testname, "csmi"))
     return new win_csmi_device(this, name, "");
 
   int phydrive = -1;
@@ -975,11 +863,9 @@ smart_device * winnt_smart_interface::autodetect_smart_device(const char * name)
 }
 
 
-#if WIN9X_SUPPORT
-
-// Scan for devices on Win9x/ME
+// Scan for devices
 
-bool win9x_smart_interface::scan_smart_devices(smart_device_list & devlist,
+bool win_smart_interface::scan_smart_devices(smart_device_list & devlist,
   const char * type, const char * pattern /* = 0*/)
 {
   if (pattern) {
@@ -987,29 +873,20 @@ bool win9x_smart_interface::scan_smart_devices(smart_device_list & devlist,
     return false;
   }
 
-  if (!type || !strcmp(type, "ata")) {
-    if (!ata_scan(devlist))
-      return false;
-  }
-
-  if (!type || !strcmp(type, "scsi")) {
-    if (!scsi_scan(devlist))
-      return false;
-  }
-  return true;
-}
-
-#endif  // WIN9X_SUPPORT
-
-
-// Scan for devices
-
-bool winnt_smart_interface::scan_smart_devices(smart_device_list & devlist,
-  const char * type, const char * pattern /* = 0*/)
-{
-  if (pattern) {
-    set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
-    return false;
+  // Check for "[*,]pd" type
+  bool pd = false;
+  char type2[16+1] = "";
+  if (type) {
+    int nc = -1;
+    if (!strcmp(type, "pd")) {
+      pd = true;
+      type = 0;
+    }
+    else if (sscanf(type, "%16[^,],pd%n", type2, &nc) == 1 &&
+             nc == (int)strlen(type)) {
+      pd = true;
+      type = type2;
+    }
   }
 
   // Set valid types
@@ -1028,78 +905,89 @@ bool winnt_smart_interface::scan_smart_devices(smart_device_list & devlist,
     else if (!strcmp(type, "csmi"))
       csmi = true;
     else {
-      set_err(EINVAL, "Invalid type '%s', valid arguments are: ata, scsi, usb, csmi", type);
+      set_err(EINVAL, "Invalid type '%s', valid arguments are: ata[,pd], scsi[,pd], usb[,pd], csmi, pd", type);
       return false;
     }
   }
 
-  // Scan up to 10 drives and 2 3ware controllers
-  const int max_raid = 2;
-  bool raid_seen[max_raid] = {false, false};
-
   char name[20];
-  for (int i = 0; i <= 9; i++) {
-    sprintf(name, "/dev/sd%c", 'a'+i);
-    GETVERSIONINPARAMS_EX vers_ex;
-
-    switch (get_phy_drive_type(i, (ata ? &vers_ex : 0))) {
-      case DEV_ATA:
-        // Driver supports SMART_GET_VERSION or STORAGE_QUERY_PROPERTY returned ATA/SATA
-        if (!ata)
-          continue;
 
-        // Interpret RAID drive map if present
-        if (vers_ex.wIdentifier == SMART_VENDOR_3WARE) {
-          // Skip if too many controllers or logical drive from this controller already seen
-          if (!(vers_ex.wControllerId < max_raid && !raid_seen[vers_ex.wControllerId]))
+  if (ata || scsi || usb) {
+    // Scan up to 128 drives and 2 3ware controllers
+    const int max_raid = 2;
+    bool raid_seen[max_raid] = {false, false};
+
+    for (int i = 0; i < 128; i++) {
+      if (pd)
+        snprintf(name, sizeof(name), "/dev/pd%d", i);
+      else if (i + 'a' <= 'z')
+        snprintf(name, sizeof(name), "/dev/sd%c", i + 'a');
+      else
+        snprintf(name, sizeof(name), "/dev/sd%c%c",
+                 i / ('z'-'a'+1) - 1 + 'a',
+                 i % ('z'-'a'+1)     + 'a');
+
+      GETVERSIONINPARAMS_EX vers_ex;
+
+      switch (get_phy_drive_type(i, (ata ? &vers_ex : 0))) {
+        case DEV_ATA:
+          // Driver supports SMART_GET_VERSION or STORAGE_QUERY_PROPERTY returned ATA/SATA
+          if (!ata)
             continue;
-          raid_seen[vers_ex.wControllerId] = true;
-          // Add physical drives
-          int len = strlen(name);
-          for (int pi = 0; pi < 32; pi++) {
-            if (vers_ex.dwDeviceMapEx & (1L << pi)) {
-              sprintf(name+len, ",%u", pi);
-              devlist.push_back( new win_ata_device(this, name, "ata") );
+
+          // Interpret RAID drive map if present
+          if (vers_ex.wIdentifier == SMART_VENDOR_3WARE) {
+            // Skip if too many controllers or logical drive from this controller already seen
+            if (!(vers_ex.wControllerId < max_raid && !raid_seen[vers_ex.wControllerId]))
+              continue;
+            raid_seen[vers_ex.wControllerId] = true;
+            // Add physical drives
+            int len = strlen(name);
+            for (int pi = 0; pi < 32; pi++) {
+              if (vers_ex.dwDeviceMapEx & (1L << pi)) {
+                snprintf(name+len, sizeof(name)-1-len, ",%u", pi);
+                devlist.push_back( new win_ata_device(this, name, "ata") );
+              }
             }
           }
-        }
-        else {
-          devlist.push_back( new win_ata_device(this, name, "ata") );
-        }
-        break;
-
-      case DEV_SCSI:
-        // STORAGE_QUERY_PROPERTY returned SCSI/SAS/...
-        if (!scsi)
-          continue;
-        devlist.push_back( new win_scsi_device(this, name, "scsi") );
-        break;
+          else {
+            devlist.push_back( new win_ata_device(this, name, "ata") );
+          }
+          break;
 
-      case DEV_USB:
-        // STORAGE_QUERY_PROPERTY returned USB
-        if (!usb)
-          continue;
-        {
-          // TODO: Use common function for this and autodetect_smart_device()
-          // Get USB bridge ID
-          unsigned short vendor_id = 0, product_id = 0;
-          if (!get_usb_id(i, vendor_id, product_id))
-            continue;
-          // Get type name for this ID
-          const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id);
-          if (!usbtype)
+        case DEV_SCSI:
+          // STORAGE_QUERY_PROPERTY returned SCSI/SAS/...
+          if (!scsi)
             continue;
-          // Return SAT/USB device for this type
-          ata_device * dev = get_sat_device(usbtype, new win_scsi_device(this, name, ""));
-          if (!dev)
+          devlist.push_back( new win_scsi_device(this, name, "scsi") );
+          break;
+
+        case DEV_USB:
+          // STORAGE_QUERY_PROPERTY returned USB
+          if (!usb)
             continue;
-          devlist.push_back(dev);
-        }
-        break;
+          {
+            // TODO: Use common function for this and autodetect_smart_device()
+            // Get USB bridge ID
+            unsigned short vendor_id = 0, product_id = 0;
+            if (!get_usb_id(i, vendor_id, product_id))
+              continue;
+            // Get type name for this ID
+            const char * usbtype = get_usb_dev_type_by_id(vendor_id, product_id);
+            if (!usbtype)
+              continue;
+            // Return SAT/USB device for this type
+            ata_device * dev = get_sat_device(usbtype, new win_scsi_device(this, name, ""));
+            if (!dev)
+              continue;
+            devlist.push_back(dev);
+          }
+          break;
 
-      default:
-        // Unknown type
-        break;
+        default:
+          // Unknown type
+          break;
+      }
     }
   }
 
@@ -1132,20 +1020,16 @@ std::string win_smart_interface::get_app_examples(const char * appname)
   if (strcmp(appname, "smartctl"))
     return "";
   return "=================================================== SMARTCTL EXAMPLES =====\n\n"
-         "  smartctl -a /dev/hda                       (Prints all SMART information)\n\n"
-         "  smartctl --smart=on --offlineauto=on --saveauto=on /dev/hda\n"
+         "  smartctl -a /dev/sda                       (Prints all SMART information)\n\n"
+         "  smartctl --smart=on --offlineauto=on --saveauto=on /dev/sda\n"
          "                                              (Enables SMART on first disk)\n\n"
-         "  smartctl -t long /dev/hda              (Executes extended disk self-test)\n\n"
-         "  smartctl --attributes --log=selftest --quietmode=errorsonly /dev/hda\n"
+         "  smartctl -t long /dev/sda              (Executes extended disk self-test)\n\n"
+         "  smartctl --attributes --log=selftest --quietmode=errorsonly /dev/sda\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"
+         "             (Prints all information for disk on PhysicalDrive 0)\n"
          "  smartctl -a /dev/pd3\n"
-         "             (Prints all information for SCSI disk on PhysicalDrive 3)\n"
+         "             (Prints all information for disk on PhysicalDrive 3)\n"
          "  smartctl -a /dev/tape1\n"
          "             (Prints all information for SCSI tape on Tape 1)\n"
          "  smartctl -A /dev/hdb,3\n"
@@ -1159,15 +1043,15 @@ std::string win_smart_interface::get_app_examples(const char * appname)
          "  ATA SMART access methods and ordering may be specified by modifiers\n"
          "  following the device name: /dev/hdX:[saicm], where\n"
          "  's': SMART_* IOCTLs,         'a': IOCTL_ATA_PASS_THROUGH,\n"
-         "  'i': IOCTL_IDE_PASS_THROUGH, 'c': ATA via IOCTL_SCSI_PASS_THROUGH,\n"
-         "  'f': IOCTL_STORAGE_*,        'm': IOCTL_SCSI_MINIPORT_*.\n"
+         "  'i': IOCTL_IDE_PASS_THROUGH, 'f': IOCTL_STORAGE_*,\n"
+         "  'm': IOCTL_SCSI_MINIPORT_*.\n"
       + strprintf(
          "  The default on this system is /dev/sdX:%s\n", ata_get_def_options()
         );
 }
 
 
-bool winnt_smart_interface::disable_system_auto_standby(bool disable)
+bool win_smart_interface::disable_system_auto_standby(bool disable)
 {
   if (disable) {
     SYSTEM_POWER_STATUS ps;
@@ -1199,8 +1083,8 @@ bool winnt_smart_interface::disable_system_auto_standby(bool disable)
 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",
-  (out?"STS":"CMD"), r->bCommandReg, (out?"ERR":" FR"), r->bFeaturesReg,
-  r->bSectorCountReg, r->bSectorNumberReg, r->bCylLowReg, r->bCylHighReg, r->bDriveHeadReg);
+    (out?"STS":"CMD"), r->bCommandReg, (out?"ERR":" FR"), r->bFeaturesReg,
+    r->bSectorCountReg, r->bSectorNumberReg, r->bCylLowReg, r->bCylHighReg, r->bDriveHeadReg);
 }
 
 static void print_ide_regs_io(const IDEREGS * ri, const IDEREGS * ro)
@@ -1224,20 +1108,20 @@ static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX * ata_version
   if (!DeviceIoControl(hdevice, SMART_GET_VERSION,
     NULL, 0, &vers, sizeof(vers), &num_out, NULL)) {
     if (ata_debugmode)
-      pout("  SMART_GET_VERSION failed, Error=%ld\n", GetLastError());
+      pout("  SMART_GET_VERSION failed, Error=%u\n", (unsigned)GetLastError());
     errno = ENOSYS;
     return -1;
   }
   assert(num_out == sizeof(GETVERSIONINPARAMS));
 
   if (ata_debugmode > 1) {
-    pout("  SMART_GET_VERSION suceeded, bytes returned: %lu\n"
-         "    Vers = %d.%d, Caps = 0x%lx, DeviceMap = 0x%02x\n",
-      num_out, vers.bVersion, vers.bRevision,
-      vers.fCapabilities, vers.bIDEDeviceMap);
+    pout("  SMART_GET_VERSION suceeded, bytes returned: %u\n"
+         "    Vers = %d.%d, Caps = 0x%x, DeviceMap = 0x%02x\n",
+      (unsigned)num_out, vers.bVersion, vers.bRevision,
+      (unsigned)vers.fCapabilities, vers.bIDEDeviceMap);
     if (vers_ex.wIdentifier == SMART_VENDOR_3WARE)
-      pout("    Identifier = %04x(3WARE), ControllerId=%u, DeviceMapEx = 0x%08lx\n",
-      vers_ex.wIdentifier, vers_ex.wControllerId, vers_ex.dwDeviceMapEx);
+      pout("    Identifier = %04x(3WARE), ControllerId=%u, DeviceMapEx = 0x%08x\n",
+      vers_ex.wIdentifier, vers_ex.wControllerId, (unsigned)vers_ex.dwDeviceMapEx);
   }
 
   if (ata_version_ex)
@@ -1250,7 +1134,7 @@ static int smart_get_version(HANDLE hdevice, GETVERSIONINPARAMS_EX * ata_version
 
 // call SMART_* ioctl
 
-static int smart_ioctl(HANDLE hdevice, int drive, IDEREGS * regs, char * data, unsigned datasize, int port)
+static int smart_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize, int port)
 {
   SENDCMDINPARAMS inpar;
   SENDCMDINPARAMS_EX & inpar_ex = (SENDCMDINPARAMS_EX &)inpar;
@@ -1263,9 +1147,14 @@ static int smart_ioctl(HANDLE hdevice, int drive, IDEREGS * regs, char * data, u
 
   memset(&inpar, 0, sizeof(inpar));
   inpar.irDriveRegs = *regs;
-  // drive is set to 0-3 on Win9x only
-  inpar.irDriveRegs.bDriveHeadReg = 0xA0 | ((drive & 1) << 4);
-  inpar.bDriveNumber = drive;
+
+  // Older drivers may require bits 5 and 7 set
+  // ATA-3: bits shall be set, ATA-4 and later: bits are obsolete
+  inpar.irDriveRegs.bDriveHeadReg |= 0xa0;
+
+  // Drive number 0-3 was required on Win9x/ME only
+  //inpar.irDriveRegs.bDriveHeadReg |= (drive & 1) << 4;
+  //inpar.bDriveNumber = drive;
 
   if (port >= 0) {
     // Set RAID port
@@ -1294,7 +1183,7 @@ static int smart_ioctl(HANDLE hdevice, int drive, IDEREGS * regs, char * data, u
 
   if (!DeviceIoControl(hdevice, code, &inpar, sizeof(SENDCMDINPARAMS)-1,
     outbuf, sizeof(SENDCMDOUTPARAMS)-1 + size_out, &num_out, NULL)) {
-    // CAUTION: DO NOT change "regs" Parameter in this case, see ata_command_interface()
+    // CAUTION: DO NOT change "regs" Parameter in this case, see win_ata_device::ata_pass_through()
     long err = GetLastError();
     if (ata_debugmode && (err != ERROR_INVALID_PARAMETER || ata_debugmode > 1)) {
       pout("  %s failed, Error=%ld\n", name, err);
@@ -1320,8 +1209,8 @@ static int smart_ioctl(HANDLE hdevice, int drive, IDEREGS * regs, char * data, u
   }
 
   if (ata_debugmode > 1) {
-    pout("  %s suceeded, bytes returned: %lu (buffer %lu)\n", name,
-      num_out, outpar->cBufferSize);
+    pout("  %s suceeded, bytes returned: %u (buffer %u)\n", name,
+      (unsigned)num_out, (unsigned)outpar->cBufferSize);
     print_ide_regs_io(regs, (regs->bFeaturesReg == ATA_SMART_STATUS ?
       (const IDEREGS *)(outpar->bBuffer) : NULL));
   }
@@ -1397,8 +1286,8 @@ static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, u
     if (   num_out != size
         || (buf->DataBuffer[0] == magic && !nonempty(buf->DataBuffer+1, datasize-1))) {
       if (ata_debugmode) {
-        pout("  IOCTL_IDE_PASS_THROUGH output data missing (%lu, %lu)\n",
-          num_out, buf->DataBufferSize);
+        pout("  IOCTL_IDE_PASS_THROUGH output data missing (%u, %u)\n",
+          (unsigned)num_out, (unsigned)buf->DataBufferSize);
         print_ide_regs_io(regs, &buf->IdeReg);
       }
       VirtualFree(buf, 0, MEM_RELEASE);
@@ -1409,8 +1298,8 @@ static int ide_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, u
   }
 
   if (ata_debugmode > 1) {
-    pout("  IOCTL_IDE_PASS_THROUGH suceeded, bytes returned: %lu (buffer %lu)\n",
-      num_out, buf->DataBufferSize);
+    pout("  IOCTL_IDE_PASS_THROUGH suceeded, bytes returned: %u (buffer %u)\n",
+      (unsigned)num_out, (unsigned)buf->DataBufferSize);
     print_ide_regs_io(regs, &buf->IdeReg);
   }
   *regs = buf->IdeReg;
@@ -1516,7 +1405,7 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev
     if (   num_out != size
         || (ab.ucDataBuf[0] == magic && !nonempty(ab.ucDataBuf+1, datasize-1))) {
       if (ata_debugmode) {
-        pout("  IOCTL_ATA_PASS_THROUGH output data missing (%lu)\n", num_out);
+        pout("  IOCTL_ATA_PASS_THROUGH output data missing (%u)\n", (unsigned)num_out);
         print_ide_regs_io(regs, ctfregs);
       }
       errno = EIO;
@@ -1526,7 +1415,7 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev
   }
 
   if (ata_debugmode > 1) {
-    pout("  IOCTL_ATA_PASS_THROUGH suceeded, bytes returned: %lu\n", num_out);
+    pout("  IOCTL_ATA_PASS_THROUGH suceeded, bytes returned: %u\n", (unsigned)num_out);
     print_ide_regs_io(regs, ctfregs);
   }
   *regs = *ctfregs;
@@ -1537,91 +1426,6 @@ static int ata_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, IDEREGS * prev
 }
 
 
-/////////////////////////////////////////////////////////////////////////////
-// ATA PASS THROUGH via SCSI PASS THROUGH (WinNT4 only)
-
-// undocumented SCSI opcode to for ATA passthrough
-#define SCSIOP_ATA_PASSTHROUGH    0xCC
-
-static int ata_via_scsi_pass_through_ioctl(HANDLE hdevice, IDEREGS * regs, char * data, unsigned datasize)
-{
-  typedef struct {
-    SCSI_PASS_THROUGH spt;
-    ULONG Filler;
-    UCHAR ucSenseBuf[32];
-    UCHAR ucDataBuf[512];
-  } SCSI_PASS_THROUGH_WITH_BUFFERS;
-
-  SCSI_PASS_THROUGH_WITH_BUFFERS sb;
-  IDEREGS * cdbregs;
-  unsigned int size;
-  DWORD num_out;
-  const unsigned char magic = 0xcf;
-
-  memset(&sb, 0, sizeof(sb));
-  sb.spt.Length = sizeof(SCSI_PASS_THROUGH);
-  //sb.spt.PathId = 0;
-  sb.spt.TargetId = 1;
-  //sb.spt.Lun = 0;
-  sb.spt.CdbLength = 10; sb.spt.SenseInfoLength = 24;
-  sb.spt.TimeOutValue = 10;
-  sb.spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
-  size = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucDataBuf);
-  sb.spt.DataBufferOffset = size;
-
-  if (datasize) {
-    if (datasize > sizeof(sb.ucDataBuf)) {
-      errno = EINVAL;
-      return -1;
-    }
-    sb.spt.DataIn = SCSI_IOCTL_DATA_IN;
-    sb.spt.DataTransferLength = datasize;
-    size += datasize;
-    sb.ucDataBuf[0] = magic;
-  }
-  else {
-    sb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
-    //sb.spt.DataTransferLength = 0;
-  }
-
-  // Use pseudo SCSI command followed by registers
-  sb.spt.Cdb[0] = SCSIOP_ATA_PASSTHROUGH;
-  cdbregs = (IDEREGS *)(sb.spt.Cdb+2);
-  *cdbregs = *regs;
-
-  if (!DeviceIoControl(hdevice, IOCTL_SCSI_PASS_THROUGH,
-    &sb, size, &sb, size, &num_out, NULL)) {
-    long err = GetLastError();
-    if (ata_debugmode)
-      pout("  ATA via IOCTL_SCSI_PASS_THROUGH failed, Error=%ld\n", err);
-    errno = (err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED ? ENOSYS : EIO);
-    return -1;
-  }
-
-  // Cannot check ATA status, because command does not return IDEREGS
-
-  // Check and copy data
-  if (datasize) {
-    if (   num_out != size
-        || (sb.ucDataBuf[0] == magic && !nonempty(sb.ucDataBuf+1, datasize-1))) {
-      if (ata_debugmode) {
-        pout("  ATA via IOCTL_SCSI_PASS_THROUGH output data missing (%lu)\n", num_out);
-        print_ide_regs_io(regs, NULL);
-      }
-      errno = EIO;
-      return -1;
-    }
-    memcpy(data, sb.ucDataBuf, datasize);
-  }
-
-  if (ata_debugmode > 1) {
-    pout("  ATA via IOCTL_SCSI_PASS_THROUGH suceeded, bytes returned: %lu\n", num_out);
-    print_ide_regs_io(regs, NULL);
-  }
-  return 0;
-}
-
-
 /////////////////////////////////////////////////////////////////////////////
 // SMART IOCTL via SCSI MINIPORT ioctl
 
@@ -1724,7 +1528,7 @@ static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS * regs, cha
   // Check result
   if (sb.srbc.ReturnCode) {
     if (ata_debugmode) {
-      pout("  IOCTL_SCSI_MINIPORT_%s failed, ReturnCode=0x%08lx\n", name, sb.srbc.ReturnCode);
+      pout("  IOCTL_SCSI_MINIPORT_%s failed, ReturnCode=0x%08x\n", name, (unsigned)sb.srbc.ReturnCode);
       print_ide_regs_io(regs, NULL);
     }
     errno = EIO;
@@ -1742,8 +1546,8 @@ static int ata_via_scsi_miniport_smart_ioctl(HANDLE hdevice, IDEREGS * regs, cha
   }
 
   if (ata_debugmode > 1) {
-    pout("  IOCTL_SCSI_MINIPORT_%s suceeded, bytes returned: %lu (buffer %lu)\n", name,
-      num_out, sb.params.out.cBufferSize);
+    pout("  IOCTL_SCSI_MINIPORT_%s suceeded, bytes returned: %u (buffer %u)\n", name,
+      (unsigned)num_out, (unsigned)sb.params.out.cBufferSize);
     print_ide_regs_io(regs, (code == IOCTL_SCSI_MINIPORT_RETURN_STATUS ?
                              (const IDEREGS *)(sb.params.out.bBuffer) : 0));
   }
@@ -1775,7 +1579,7 @@ static int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS * regs, char * d
     return -1;
   }
   memset(&sb, 0, sizeof(sb));
-  strcpy((char *)sb.srbc.Signature, "<3ware>");
+  strncpy((char *)sb.srbc.Signature, "<3ware>", sizeof(sb.srbc.Signature));
   sb.srbc.HeaderLength = sizeof(SRB_IO_CONTROL);
   sb.srbc.Timeout = 60; // seconds
   sb.srbc.ControlCode = 0xA0000000;
@@ -1798,7 +1602,7 @@ static int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS * regs, char * d
 
   if (sb.srbc.ReturnCode) {
     if (ata_debugmode) {
-      pout("  ATA via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08lx\n", sb.srbc.ReturnCode);
+      pout("  ATA via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08x\n", (unsigned)sb.srbc.ReturnCode);
       print_ide_regs_io(regs, NULL);
     }
     errno = EIO;
@@ -1810,7 +1614,7 @@ static int ata_via_3ware_miniport_ioctl(HANDLE hdevice, IDEREGS * regs, char * d
     memcpy(data, sb.buffer, datasize);
 
   if (ata_debugmode > 1) {
-    pout("  ATA via IOCTL_SCSI_MINIPORT suceeded, bytes returned: %lu\n", num_out);
+    pout("  ATA via IOCTL_SCSI_MINIPORT suceeded, bytes returned: %u\n", (unsigned)num_out);
     print_ide_regs_io(regs, &sb.regs);
   }
   *regs = sb.regs;
@@ -1828,7 +1632,7 @@ static int update_3ware_devicemap_ioctl(HANDLE hdevice)
 {
   SRB_IO_CONTROL srbc;
   memset(&srbc, 0, sizeof(srbc));
-  strcpy((char *)srbc.Signature, "<3ware>");
+  strncpy((char *)srbc.Signature, "<3ware>", sizeof(srbc.Signature));
   srbc.HeaderLength = sizeof(SRB_IO_CONTROL);
   srbc.Timeout = 60; // seconds
   srbc.ControlCode = 0xCC010014;
@@ -1846,7 +1650,7 @@ static int update_3ware_devicemap_ioctl(HANDLE hdevice)
   }
   if (srbc.ReturnCode) {
     if (ata_debugmode)
-      pout("  UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08lx\n", srbc.ReturnCode);
+      pout("  UPDATE DEVICEMAP via IOCTL_SCSI_MINIPORT failed, ReturnCode=0x%08x\n", (unsigned)srbc.ReturnCode);
     errno = EIO;
     return -1;
   }
@@ -2135,7 +1939,7 @@ static int storage_query_property_ioctl(HANDLE hdevice, STORAGE_DEVICE_DESCRIPTO
   if (!DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY,
     &query, sizeof(query), data, sizeof(*data), &num_out, NULL)) {
     if (ata_debugmode > 1 || scsi_debugmode > 1)
-      pout("  IOCTL_STORAGE_QUERY_PROPERTY failed, Error=%ld\n", GetLastError());
+      pout("  IOCTL_STORAGE_QUERY_PROPERTY failed, Error=%u\n", (unsigned)GetLastError());
     errno = ENOSYS;
     return -1;
   }
@@ -2173,16 +1977,16 @@ static int storage_predict_failure_ioctl(HANDLE hdevice, char * data = 0)
   if (!DeviceIoControl(hdevice, IOCTL_STORAGE_PREDICT_FAILURE,
     0, 0, &pred, sizeof(pred), &num_out, NULL)) {
     if (ata_debugmode > 1)
-      pout("  IOCTL_STORAGE_PREDICT_FAILURE failed, Error=%ld\n", GetLastError());
+      pout("  IOCTL_STORAGE_PREDICT_FAILURE failed, Error=%u\n", (unsigned)GetLastError());
     errno = ENOSYS;
     return -1;
   }
 
   if (ata_debugmode > 1) {
     pout("  IOCTL_STORAGE_PREDICT_FAILURE returns:\n"
-         "    PredictFailure: 0x%08lx\n"
+         "    PredictFailure: 0x%08x\n"
          "    VendorSpecific: 0x%02x,0x%02x,0x%02x,...,0x%02x\n",
-         pred.PredictFailure,
+         (unsigned)pred.PredictFailure,
          pred.VendorSpecific[0], pred.VendorSpecific[1], pred.VendorSpecific[2],
          pred.VendorSpecific[sizeof(pred.VendorSpecific)-1]
     );
@@ -2330,6 +2134,31 @@ static int get_identify_from_device_property(HANDLE hdevice, ata_identify_device
   return 0;
 }
 
+// Get Serial Number in IDENTIFY from WMI
+static bool get_serial_from_wmi(int drive, ata_identify_device * id)
+{
+  bool debug = (ata_debugmode > 1);
+
+  wbem_services ws;
+  if (!ws.connect()) {
+    if (debug)
+      pout("WMI connect failed\n");
+    return false;
+  }
+
+  wbem_object wo;
+  if (!ws.query1(wo, "SELECT Model,SerialNumber FROM Win32_DiskDrive WHERE "
+                     "DeviceID=\"\\\\\\\\.\\\\PHYSICALDRIVE%d\"", drive))
+    return false;
+
+  std::string serial = wo.get_str("SerialNumber");
+  if (debug)
+    pout("  WMI:PhysicalDrive%d: \"%s\", S/N:\"%s\"\n", drive, wo.get_str("Model").c_str(), serial.c_str());
+
+  copy_swapped(id->serial_no, serial.c_str(), sizeof(id->serial_no));
+  return true;
+}
+
 
 /////////////////////////////////////////////////////////////////////////////
 // USB ID detection using WMI
@@ -2416,7 +2245,7 @@ static bool get_usb_id(int drive, unsigned short & vendor_id, unsigned short & p
         continue;
       }
 
-      // Fail if previos USB bridge is associated to other controller or ID is unknown
+      // Fail if previous USB bridge is associated to other controller or ID is unknown
       if (!(ant == prev_usb_ant && prev_usb_venid)) {
         if (debug)
           pout("  +---> \"%s\" (Error: No USB bridge found)\n", name2.c_str());
@@ -2459,43 +2288,14 @@ static bool get_usb_id(int drive, unsigned short & vendor_id, unsigned short & p
 
 /////////////////////////////////////////////////////////////////////////////
 
-// Call GetDevicePowerState() if available (Win98/ME/2000/XP/2003)
+// Call GetDevicePowerState()
 // returns: 1=active, 0=standby, -1=error
 // (This would also work for SCSI drives)
 
 static int get_device_power_state(HANDLE hdevice)
 {
-  static bool unsupported = false;
-  if (unsupported) {
-    errno = ENOSYS;
-    return -1;
-  }
-
-#ifdef __CYGWIN__
-  static DWORD kernel_dll_pid = 0;
-#endif
-  static BOOL (WINAPI * GetDevicePowerState_p)(HANDLE, BOOL *) = 0;
-
-  if (!GetDevicePowerState_p
-#ifdef __CYGWIN__
-      || kernel_dll_pid != GetCurrentProcessId() // detect fork()
-#endif
-     ) {
-    if (!(GetDevicePowerState_p = (BOOL (WINAPI *)(HANDLE, BOOL *))
-          GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetDevicePowerState"))) {
-      if (ata_debugmode)
-        pout("  GetDevicePowerState() not found, Error=%ld\n", GetLastError());
-      unsupported = true;
-      errno = ENOSYS;
-      return -1;
-    }
-#ifdef __CYGWIN__
-    kernel_dll_pid = GetCurrentProcessId();
-#endif
-  }
-
   BOOL state = TRUE;
-  if (!GetDevicePowerState_p(hdevice, &state)) {
+  if (!GetDevicePowerState(hdevice, &state)) {
     long err = GetLastError();
     if (ata_debugmode)
       pout("  GetDevicePowerState() failed, Error=%ld\n", err);
@@ -2513,68 +2313,12 @@ static int get_device_power_state(HANDLE hdevice)
 
 /////////////////////////////////////////////////////////////////////////////
 
-#if WIN9X_SUPPORT
-// Print SMARTVSD error message, return errno
-
-static int smartvsd_error()
-{
-  char path[MAX_PATH];
-  unsigned len;
-  if (!(5 <= (len = GetSystemDirectoryA(path, MAX_PATH)) && len < MAX_PATH/2))
-    return ENOENT;
-  // SMARTVSD.VXD present?
-  strcpy(path+len, "\\IOSUBSYS\\SMARTVSD.VXD");
-  if (!access(path, 0)) {
-    // Yes, standard IDE driver used?
-    HANDLE h;
-    if (   (h = CreateFileA("\\\\.\\ESDI_506",
-                 GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
-                 NULL, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE
-        && GetLastError() == ERROR_FILE_NOT_FOUND                             ) {
-      pout("Standard IDE driver ESDI_506.PDR not used, or no IDE/ATA drives present.\n");
-      return ENOENT;
-    }
-    else {
-      if (h != INVALID_HANDLE_VALUE) // should not happen
-        CloseHandle(h);
-      pout("SMART driver SMARTVSD.VXD is installed, but not loaded.\n");
-      return ENOSYS;
-    }
-  }
-  else {
-    strcpy(path+len, "\\SMARTVSD.VXD");
-    if (!access(path, 0)) {
-      // Some Windows versions install SMARTVSD.VXD in SYSTEM directory
-      // (http://support.microsoft.com/kb/265854/en-us).
-      path[len] = 0;
-      pout("SMART driver is not properly installed,\n"
-         " move SMARTVSD.VXD from \"%s\" to \"%s\\IOSUBSYS\"\n"
-         " and reboot Windows.\n", path, path);
-    }
-    else {
-      // Some Windows versions do not provide SMARTVSD.VXD
-      // (http://support.microsoft.com/kb/199886/en-us).
-      path[len] = 0;
-      pout("SMARTVSD.VXD is missing in folder \"%s\\IOSUBSYS\".\n", path);
-    }
-    return ENOSYS;
-  }
-}
-
-#endif // WIN9X_SUPPORT
-
 // Get default ATA device options
 
 static const char * ata_get_def_options()
 {
-  DWORD ver = GetVersion();
-  if ((ver & 0x80000000) || (ver & 0xff) < 4) // Win9x/ME
-    return "s"; // SMART_* only
-  else if ((ver & 0xff) == 4) // WinNT4
-    return "sc"; // SMART_*, SCSI_PASS_THROUGH
-  else // WinXP, 2003, Vista
-    return "pasifm"; // GetDevicePowerState(), ATA_, SMART_*, IDE_PASS_THROUGH,
-                     // STORAGE_*, SCSI_MINIPORT_*
+  return "pasifm"; // GetDevicePowerState(), ATA_, SMART_*, IDE_PASS_THROUGH,
+                   // STORAGE_*, SCSI_MINIPORT_*
 }
 
 
@@ -2606,9 +2350,9 @@ win_ata_device::win_ata_device(smart_interface * intf, const char * dev_name, co
 : smart_device(intf, dev_name, "ata", req_type),
   m_usr_options(false),
   m_admin(false),
+  m_phydrive(-1),
   m_id_is_cached(false),
   m_is_3ware(false),
-  m_drive(0),
   m_port(-1),
   m_smartver_state(0)
 {
@@ -2624,18 +2368,18 @@ win_ata_device::~win_ata_device() throw()
 bool win_ata_device::open()
 {
   const char * name = skipdev(get_dev_name()); int len = strlen(name);
-  // [sh]d[a-z](:[saicmfp]+)? => Physical drive 0-25, with options
-  char drive[1+1] = "", options[8+1] = ""; int n1 = -1, n2 = -1;
-  if (   sscanf(name, "%*[sh]d%1[a-z]%n:%7[saicmfp]%n", drive, &n1, options, &n2) >= 1
-      && ((n1 == len && !options[0]) || n2 == len)                                       ) {
-    return open(drive[0] - 'a', -1, options, -1);
+  // [sh]d[a-z]([a-z])?(:[saicmfp]+)? => Physical drive 0-701, with options
+  char drive[2+1] = "", options[8+1] = ""; int n1 = -1, n2 = -1;
+  if (   sscanf(name, "%*[sh]d%2[a-z]%n:%6[saimfp]%n", drive, &n1, options, &n2) >= 1
+      && ((n1 == len && !options[0]) || n2 == len)                                   ) {
+    return open(sdxy_to_phydrive(drive), -1, options, -1);
   }
-  // [sh]d[a-z],N(:[saicmfp3]+)? => Physical drive 0-25, RAID port N, with options
+  // [sh]d[a-z],N(:[saicmfp3]+)? => Physical drive 0-701, RAID port N, with options
   drive[0] = 0; options[0] = 0; n1 = -1; n2 = -1;
   unsigned port = ~0;
-  if (   sscanf(name, "%*[sh]d%1[a-z],%u%n:%8[saicmfp3]%n", drive, &port, &n1, options, &n2) >= 2
-      && port < 32 && ((n1 == len && !options[0]) || n2 == len)                                     ) {
-    return open(drive[0] - 'a', -1, options, port);
+  if (   sscanf(name, "%*[sh]d%2[a-z],%u%n:%7[saimfp3]%n", drive, &port, &n1, options, &n2) >= 2
+      && port < 32 && ((n1 == len && !options[0]) || n2 == len)                                  ) {
+    return open(sdxy_to_phydrive(drive), -1, options, port);
   }
   // pd<m>,N => Physical drive <m>, RAID port N
   int phydrive = -1; port = ~0; n1 = -1; n2 = -1;
@@ -2655,28 +2399,25 @@ bool win_ata_device::open()
 
 bool win_ata_device::open(int phydrive, int logdrive, const char * options, int port)
 {
-  // path depends on Windows Version
+  m_phydrive = -1;
   char devpath[30];
-  if (win9x && 0 <= phydrive && phydrive <= 7)
-    // Use patched "smartvse.vxd" for drives 4-7, see INSTALL file for details
-    strcpy(devpath, (phydrive <= 3 ? "\\\\.\\SMARTVSD" : "\\\\.\\SMARTVSE"));
-  else if (!win9x && 0 <= phydrive && phydrive <= 255)
-    snprintf(devpath, sizeof(devpath)-1, "\\\\.\\PhysicalDrive%d", phydrive);
-  else if (!win9x && 0 <= logdrive && logdrive <= 'Z'-'A')
+  if (0 <= phydrive && phydrive <= 255)
+    snprintf(devpath, sizeof(devpath)-1, "\\\\.\\PhysicalDrive%d", (m_phydrive = phydrive));
+  else if (0 <= logdrive && logdrive <= 'Z'-'A')
     snprintf(devpath, sizeof(devpath)-1, "\\\\.\\%c:", 'A'+logdrive);
   else
     return set_err(ENOENT);
 
   // Open device
   HANDLE h = INVALID_HANDLE_VALUE;
-  if (win9x || !(*options && !options[strspn(options, "fp")])) {
+  if (!(*options && !options[strspn(options, "fp")])) {
     // Open with admin rights
     m_admin = true;
     h = CreateFileA(devpath, GENERIC_READ|GENERIC_WRITE,
       FILE_SHARE_READ|FILE_SHARE_WRITE,
       NULL, OPEN_EXISTING, 0, 0);
   }
-  if (!win9x && h == INVALID_HANDLE_VALUE) {
+  if (h == INVALID_HANDLE_VALUE) {
     // Open without admin rights
     m_admin = false;
     h = CreateFileA(devpath, 0,
@@ -2685,10 +2426,6 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
   }
   if (h == INVALID_HANDLE_VALUE) {
     long err = GetLastError();
-#if WIN9X_SUPPORT
-    if (win9x && phydrive <= 3 && err == ERROR_FILE_NOT_FOUND)
-      smartvsd_error();
-#endif
     if (err == ERROR_FILE_NOT_FOUND)
       set_err(ENOENT, "%s: not found", devpath);
     else if (err == ERROR_ACCESS_DENIED)
@@ -2725,13 +2462,12 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
     m_options = def_options;
   }
 
-  // NT4/2000/XP: SMART_GET_VERSION may spin up disk, so delay until first real SMART_* call
-  m_drive = 0; m_port = port;
-  if (!win9x && port < 0)
+  // SMART_GET_VERSION may spin up disk, so delay until first real SMART_* call
+  m_port = port;
+  if (port < 0)
     return true;
 
-  // Win9X/ME: Get drive map
-  // RAID: Get port map
+  // 3ware RAID: Get port map
   GETVERSIONINPARAMS_EX vers_ex;
   int devmap = smart_get_version(h, &vers_ex);
 
@@ -2760,7 +2496,7 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
   }
   m_smartver_state = 1;
 
-  if (port >= 0) {
+  {
     // 3ware RAID: update devicemap first
 
     if (!update_3ware_devicemap_ioctl(h)) {
@@ -2775,75 +2511,23 @@ bool win_ata_device::open(int phydrive, int logdrive, const char * options, int
         return set_err(ENOENT, "%s: Port %d is empty or does not exist", devpath, port);
       }
     }
-    return true;
   }
 
-  // Win9x/ME: Check device presence & type
-  if (((devmap >> (phydrive & 0x3)) & 0x11) != 0x01) {
-    unsigned char atapi = (devmap >> (phydrive & 0x3)) & 0x10;
-    // Win9x drive existence check may not work as expected
-    // The atapi.sys driver incorrectly fills in the bIDEDeviceMap with 0x01
-    // (The related KB Article Q196120 is no longer available)
-    if (!is_permissive()) {
-      close();
-      return set_err((atapi ? ENOSYS : ENOENT), "%s: Drive %d %s (IDEDeviceMap=0x%02x)",
-        devpath, phydrive, (atapi?"is an ATAPI device":"does not exist"), devmap);
-    }
-  }
-  // Drive number must be passed to ioctl
-  m_drive = (phydrive & 0x3);
   return true;
 }
 
 
-#if WIN9X_SUPPORT
-
-// Scan for ATA drives on Win9x/ME
-
-bool win9x_smart_interface::ata_scan(smart_device_list & devlist)
-{
-  // Open device
-  const char devpath[] = "\\\\.\\SMARTVSD";
-  HANDLE h = CreateFileA(devpath, GENERIC_READ|GENERIC_WRITE,
-    FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
-  if (h == INVALID_HANDLE_VALUE) {
-    if (ata_debugmode > 1)
-      pout(" %s: Open failed, Error=%ld\n", devpath, GetLastError());
-    return true; // SMARTVSD.VXD missing or no ATA devices
-  }
-
-  // Get drive map
-  int devmap = smart_get_version(h);
-  CloseHandle(h);
-  if (devmap < 0)
-    return true; // Should not happen
-
-  // Check ATA device presence, remove ATAPI devices
-  devmap = (devmap & 0xf) & ~((devmap >> 4) & 0xf);
-  char name[20];
-  for (int i = 0; i < 4; i++) {
-    if (!(devmap & (1 << i)))
-      continue;
-    sprintf(name, "/dev/hd%c", 'a'+i);
-    devlist.push_back( new win_ata_device(this, name, "ata") );
-  }
-  return true;
-}
-
-#endif // WIN9X_SUPPORT
-
-
-/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
 
 // Interface to ATA devices
 bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
   // No multi-sector support for now, see above
   // warning about IOCTL_ATA_PASS_THROUGH
-  if (!ata_cmd_is_ok(in,
-    true, // data_out_support
-    false, // !multi_sector_support
-    true) // ata_48bit_support
+  if (!ata_cmd_is_supported(in,
+    ata_device::supports_data_out |
+    ata_device::supports_output_regs |
+    ata_device::supports_48bit)
   )
     return false;
 
@@ -2861,7 +2545,7 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
     case ATA_IDENTIFY_PACKET_DEVICE:
       // SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH, STORAGE_PREDICT_FAILURE
       // and SCSI_MINIPORT_* if requested by user
-      valid_options = (m_usr_options ? "saicmf" : "saicf");
+      valid_options = (m_usr_options ? "saimf" : "saif");
       break;
 
     case ATA_CHECK_POWER_MODE:
@@ -2879,21 +2563,21 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
         case ATA_SMART_AUTO_OFFLINE:
           // SMART_*, ATA_, IDE_, SCSI_PASS_THROUGH, STORAGE_PREDICT_FAILURE
           // and SCSI_MINIPORT_* if requested by user
-          valid_options = (m_usr_options ? "saicmf" : "saicf");
+          valid_options = (m_usr_options ? "saimf" : "saif");
           break;
 
         case ATA_SMART_IMMEDIATE_OFFLINE:
-          // SMART_SEND_DRIVE_COMMAND supports ABORT_SELF_TEST only on Win9x/ME
-          valid_options = (m_usr_options || in.in_regs.lba_low != 127/*ABORT*/ || win9x ?
-                           "saicm3" : "aicm3");
+          // SMART_SEND_DRIVE_COMMAND does not support ABORT_SELF_TEST
+          valid_options = (m_usr_options || in.in_regs.lba_low != 127/*ABORT*/ ?
+                           "saim3" : "aim3");
           break;
 
         case ATA_SMART_READ_LOG_SECTOR:
-          // SMART_RCV_DRIVE_DATA supports this only on Win9x/ME
+          // SMART_RCV_DRIVE_DATA does not support READ_LOG
           // Try SCSI_MINIPORT also to skip buggy class driver
           // SMART functions do not support multi sector I/O.
           if (in.size == 512)
-            valid_options = (m_usr_options || win9x ? "saicm3" : "aicm3");
+            valid_options = (m_usr_options ? "saim3" : "aim3");
           else
             valid_options = "a";
           break;
@@ -2905,11 +2589,7 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
           break;
 
         case ATA_SMART_STATUS:
-          // May require lba_mid,lba_high register return
-          if (in.out_needed.is_set())
-            valid_options = (m_usr_options ? "saimf" : "saif");
-          else
-            valid_options = (m_usr_options ? "saicmf" : "saicf");
+          valid_options = (m_usr_options ? "saimf" : "saif");
           break;
 
         default:
@@ -2930,11 +2610,9 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
          ||  in.in_regs.is_48bit_cmd()                               )
       // DATA_OUT, more than one sector, 48-bit command: ATA_PASS_THROUGH only
       valid_options = "a";
-    else if (in.out_needed.is_set())
-      // Need output registers: ATA/IDE_PASS_THROUGH
-      valid_options = "ai";
     else
-      valid_options = "aic";
+      // ATA/IDE_PASS_THROUGH
+      valid_options = "ai";
   }
 
   if (!m_admin) {
@@ -3047,13 +2725,13 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 
           m_smartver_state = 1;
         }
-        rc = smart_ioctl(get_fh(), m_drive, &regs, data, datasize, m_port);
+        rc = smart_ioctl(get_fh(), &regs, data, datasize, m_port);
         out_regs_set = (in.in_regs.features == ATA_SMART_STATUS);
-        id_is_cached = (m_port < 0 && !win9x); // Not cached by 3ware or Win9x/ME driver
+        id_is_cached = (m_port < 0); // Not cached by 3ware driver
         break;
       case 'm':
         rc = ata_via_scsi_miniport_smart_ioctl(get_fh(), &regs, data, datasize);
-        id_is_cached = (m_port < 0 && !win9x);
+        id_is_cached = (m_port < 0);
         break;
       case 'a':
         rc = ata_pass_through_ioctl(get_fh(), &regs,
@@ -3065,12 +2743,11 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
         rc = ide_pass_through_ioctl(get_fh(), &regs, data, datasize);
         out_regs_set = true;
         break;
-      case 'c':
-        rc = ata_via_scsi_pass_through_ioctl(get_fh(), &regs, data, datasize);
-        break;
       case 'f':
         if (in.in_regs.command == ATA_IDENTIFY_DEVICE) {
             rc = get_identify_from_device_property(get_fh(), (ata_identify_device *)data);
+            if (rc == 0 && m_phydrive >= 0)
+              get_serial_from_wmi(m_phydrive, (ata_identify_device *)data);
             id_is_cached = true;
         }
         else if (in.in_regs.command == ATA_SMART_CMD) switch (in.in_regs.features) {
@@ -3261,10 +2938,12 @@ bool csmi_device::select_phy(unsigned phy_no)
 
 bool csmi_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
-  if (!ata_cmd_is_ok(in,
-    true, // data_out_support
-    true, // multi_sector_support
-    true) // ata_48bit_support
+  if (!ata_cmd_is_supported(in,
+    ata_device::supports_data_out |
+    ata_device::supports_output_regs |
+    ata_device::supports_multi_sector |
+    ata_device::supports_48bit,
+    "CMSI")
   )
     return false;
 
@@ -3479,556 +3158,19 @@ bool win_csmi_device::csmi_ioctl(unsigned code, IOCTL_HEADER * csmi_buffer,
   // Check result
   if (csmi_buffer->ReturnCode) {
     if (scsi_debugmode) {
-      pout("  IOCTL_SCSI_MINIPORT(CC_CSMI_%u) failed, ReturnCode=%lu\n",
-        code, csmi_buffer->ReturnCode);
+      pout("  IOCTL_SCSI_MINIPORT(CC_CSMI_%u) failed, ReturnCode=%u\n",
+        code, (unsigned)csmi_buffer->ReturnCode);
     }
-    return set_err(EIO, "CSMI(%u) failed with ReturnCode=%lu", code, csmi_buffer->ReturnCode);
+    return set_err(EIO, "CSMI(%u) failed with ReturnCode=%u", code, (unsigned)csmi_buffer->ReturnCode);
   }
 
   if (scsi_debugmode > 1)
-    pout("  IOCTL_SCSI_MINIPORT(CC_CSMI_%u) succeeded, bytes returned: %lu\n", code, num_out);
+    pout("  IOCTL_SCSI_MINIPORT(CC_CSMI_%u) succeeded, bytes returned: %u\n", code, (unsigned)num_out);
 
   return true;
 }
 
 
-/////////////////////////////////////////////////////////////////////////////
-// ASPI Interface (for SCSI devices on 9x/ME)
-/////////////////////////////////////////////////////////////////////////////
-
-#if WIN9X_SUPPORT
-
-#pragma pack(1)
-
-#define ASPI_SENSE_SIZE 18
-
-// ASPI SCSI Request block header
-
-typedef struct {
-  unsigned char cmd;             // 00: Command code
-  unsigned char status;          // 01: ASPI status
-  unsigned char adapter;         // 02: Host adapter number
-  unsigned char flags;           // 03: Request flags
-  unsigned char reserved[4];     // 04: 0
-} ASPI_SRB_HEAD;
-
-// SRB for host adapter inquiry
-
-typedef struct {
-  ASPI_SRB_HEAD h;               // 00: Header
-  unsigned char adapters;        // 08: Number of adapters
-  unsigned char target_id;       // 09: Target ID ?
-  char manager_id[16];           // 10: SCSI manager ID
-  char adapter_id[16];           // 26: Host adapter ID
-  unsigned char parameters[16];  // 42: Host adapter unique parmameters
-} ASPI_SRB_INQUIRY;
-
-// SRB for get device type
-
-typedef struct {
-  ASPI_SRB_HEAD h;               // 00: Header
-  unsigned char target_id;       // 08: Target ID
-  unsigned char lun;             // 09: LUN
-  unsigned char devtype;         // 10: Device type
-  unsigned char reserved;        // 11: Reserved
-} ASPI_SRB_DEVTYPE;
-
-// SRB for SCSI I/O
-
-typedef struct {
-  ASPI_SRB_HEAD h;               // 00: Header
-  unsigned char target_id;       // 08: Target ID
-  unsigned char lun;             // 09: LUN
-  unsigned char reserved[2];     // 10: Reserved
-  unsigned long data_size;       // 12: Data alloc. lenght
-  void * data_addr;              // 16: Data buffer pointer
-  unsigned char sense_size;      // 20: Sense alloc. length
-  unsigned char cdb_size;        // 21: CDB length
-  unsigned char host_status;     // 22: Host status
-  unsigned char target_status;   // 23: Target status
-  void * event_handle;           // 24: Event handle
-  unsigned char workspace[20];   // 28: ASPI workspace
-  unsigned char cdb[16+ASPI_SENSE_SIZE];
-} ASPI_SRB_IO;
-
-// Macro to retrieve start of sense information
-#define ASPI_SRB_SENSE(srb,cdbsz) ((srb)->cdb + 16)
-
-// SRB union
-
-typedef union {
-  ASPI_SRB_HEAD h;       // Common header
-  ASPI_SRB_INQUIRY q;    // Inquiry
-  ASPI_SRB_DEVTYPE t;    // Device type
-  ASPI_SRB_IO i;         // I/O
-} ASPI_SRB;
-
-#pragma pack()
-
-// ASPI commands
-#define ASPI_CMD_ADAPTER_INQUIRE        0x00
-#define ASPI_CMD_GET_DEVICE_TYPE        0x01
-#define ASPI_CMD_EXECUTE_IO             0x02
-#define ASPI_CMD_ABORT_IO               0x03
-
-// Request flags
-#define ASPI_REQFLAG_DIR_TO_HOST        0x08
-#define ASPI_REQFLAG_DIR_TO_TARGET      0x10
-#define ASPI_REQFLAG_DIR_NO_XFER        0x18
-#define ASPI_REQFLAG_EVENT_NOTIFY       0x40
-
-// ASPI status
-#define ASPI_STATUS_IN_PROGRESS         0x00
-#define ASPI_STATUS_NO_ERROR            0x01
-#define ASPI_STATUS_ABORTED             0x02
-#define ASPI_STATUS_ABORT_ERR           0x03
-#define ASPI_STATUS_ERROR               0x04
-#define ASPI_STATUS_INVALID_COMMAND     0x80
-#define ASPI_STATUS_INVALID_ADAPTER     0x81
-#define ASPI_STATUS_INVALID_TARGET      0x82
-#define ASPI_STATUS_NO_ADAPTERS         0xE8
-
-// Adapter (host) status
-#define ASPI_HSTATUS_NO_ERROR           0x00
-#define ASPI_HSTATUS_SELECTION_TIMEOUT  0x11
-#define ASPI_HSTATUS_DATA_OVERRUN       0x12
-#define ASPI_HSTATUS_BUS_FREE           0x13
-#define ASPI_HSTATUS_BUS_PHASE_ERROR    0x14
-#define ASPI_HSTATUS_BAD_SGLIST         0x1A
-
-// Target status
-#define ASPI_TSTATUS_NO_ERROR           0x00
-#define ASPI_TSTATUS_CHECK_CONDITION    0x02
-#define ASPI_TSTATUS_BUSY               0x08
-#define ASPI_TSTATUS_RESERV_CONFLICT    0x18
-
-
-static HINSTANCE h_aspi_dll; // DLL handle
-static UINT (* aspi_entry)(ASPI_SRB * srb); // ASPI entrypoint
-static unsigned num_aspi_adapters;
-
-#ifdef __CYGWIN__
-// h_aspi_dll+aspi_entry is not inherited by Cygwin's fork()
-static DWORD aspi_dll_pid; // PID of DLL owner to detect fork()
-#define aspi_entry_valid() (aspi_entry && (aspi_dll_pid == GetCurrentProcessId()))
-#else
-#define aspi_entry_valid() (!!aspi_entry)
-#endif
-
-
-static int aspi_call(ASPI_SRB * srb)
-{
-  int i;
-  aspi_entry(srb);
-  i = 0;
-  while (((volatile ASPI_SRB *)srb)->h.status == ASPI_STATUS_IN_PROGRESS) {
-    if (++i > 100/*10sek*/) {
-      pout("ASPI Adapter %u: Timed out\n", srb->h.adapter);
-      aspi_entry = 0;
-      h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
-      errno = EIO;
-      return -1;
-    }
-    if (scsi_debugmode > 1)
-      pout("ASPI Adapter %u: Waiting (%d) ...\n", srb->h.adapter, i);
-    Sleep(100);
-  }
-  return 0;
-}
-
-
-// Get ASPI entrypoint from wnaspi32.dll
-
-static FARPROC aspi_get_address(const char * name, int verbose)
-{
-  FARPROC addr;
-  assert(h_aspi_dll && h_aspi_dll != INVALID_HANDLE_VALUE);
-
-  if (!(addr = GetProcAddress(h_aspi_dll, name))) {
-    if (verbose)
-      pout("Missing %s() in WNASPI32.DLL\n", name);
-    aspi_entry = 0;
-    FreeLibrary(h_aspi_dll);
-    h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
-    errno = ENOSYS;
-    return 0;
-  }
-  return addr;
-}
-
-
-static int aspi_open_dll(int verbose)
-{
-  UINT (*aspi_info)(void);
-  UINT info, rc;
-
-  assert(!aspi_entry_valid());
-
-  // Check structure layout
-  assert(sizeof(ASPI_SRB_HEAD) == 8);
-  assert(sizeof(ASPI_SRB_INQUIRY) == 58);
-  assert(sizeof(ASPI_SRB_DEVTYPE) == 12);
-  assert(sizeof(ASPI_SRB_IO) == 64+ASPI_SENSE_SIZE);
-  assert(offsetof(ASPI_SRB,h.cmd) == 0);
-  assert(offsetof(ASPI_SRB,h.flags) == 3);
-  assert(offsetof(ASPI_SRB_IO,lun) == 9);
-  assert(offsetof(ASPI_SRB_IO,data_addr) == 16);
-  assert(offsetof(ASPI_SRB_IO,workspace) == 28);
-  assert(offsetof(ASPI_SRB_IO,cdb) == 48);
-
-  if (h_aspi_dll == INVALID_HANDLE_VALUE) {
-    // do not retry
-    errno = ENOENT;
-    return -1;
-  }
-
-  // Load ASPI DLL
-  if (!(h_aspi_dll = LoadLibraryA("WNASPI32.DLL"))) {
-    if (verbose)
-      pout("Cannot load WNASPI32.DLL, Error=%ld\n", GetLastError());
-    h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
-    errno = ENOENT;
-    return -1;
-  }
-  if (scsi_debugmode > 1) {
-    // Print full path of WNASPI32.DLL
-    char path[MAX_PATH];
-    if (!GetModuleFileName(h_aspi_dll, path, sizeof(path)))
-      strcpy(path, "*unknown*");
-    pout("Using ASPI interface \"%s\"\n", path);
-  }
-
-  // Get ASPI entrypoints
-  if (!(aspi_info = (UINT (*)(void))aspi_get_address("GetASPI32SupportInfo", verbose)))
-    return -1;
-  if (!(aspi_entry = (UINT (*)(ASPI_SRB *))aspi_get_address("SendASPI32Command", verbose)))
-    return -1;
-
-  // Init ASPI manager and get number of adapters
-  info = (aspi_info)();
-  if (scsi_debugmode > 1)
-    pout("GetASPI32SupportInfo() returns 0x%04x\n", info);
-  rc = (info >> 8) & 0xff;
-  if (rc == ASPI_STATUS_NO_ADAPTERS) {
-    num_aspi_adapters = 0;
-  }
-  else if (rc == ASPI_STATUS_NO_ERROR) {
-    num_aspi_adapters = info & 0xff;
-  }
-  else {
-    if (verbose)
-      pout("Got strange 0x%04x from GetASPI32SupportInfo()\n", info);
-    aspi_entry = 0;
-    FreeLibrary(h_aspi_dll);
-    h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
-    errno = ENOENT;
-    return -1;
-  }
-
-  if (scsi_debugmode)
-    pout("%u ASPI Adapter%s detected\n",num_aspi_adapters, (num_aspi_adapters!=1?"s":""));
-
-#ifdef __CYGWIN__
-  // save PID to detect fork() in aspi_entry_valid()
-  aspi_dll_pid = GetCurrentProcessId();
-#endif
-  assert(aspi_entry_valid());
-  return 0;
-}
-
-
-static int aspi_io_call(ASPI_SRB * srb, unsigned timeout)
-{
-  HANDLE event;
-  // Create event
-  if (!(event = CreateEventA(NULL, FALSE, FALSE, NULL))) {
-    pout("CreateEvent(): Error=%ld\n", GetLastError()); return -EIO;
-  }
-  srb->i.event_handle = event;
-  srb->h.flags |= ASPI_REQFLAG_EVENT_NOTIFY;
-  // Start ASPI request
-  aspi_entry(srb);
-  if (((volatile ASPI_SRB *)srb)->h.status == ASPI_STATUS_IN_PROGRESS) {
-    // Wait for event
-    DWORD rc = WaitForSingleObject(event, timeout*1000L);
-    if (rc != WAIT_OBJECT_0) {
-      if (rc == WAIT_TIMEOUT) {
-        pout("ASPI Adapter %u, ID %u: Timed out after %u seconds\n",
-          srb->h.adapter, srb->i.target_id, timeout);
-      }
-      else {
-        pout("WaitForSingleObject(%lx) = 0x%lx,%ld, Error=%ld\n",
-          (unsigned long)(ULONG_PTR)event, rc, rc, GetLastError());
-      }
-      // TODO: ASPI_ABORT_IO command
-      aspi_entry = 0;
-      h_aspi_dll = (HINSTANCE)INVALID_HANDLE_VALUE;
-      return -EIO;
-    }
-  }
-  CloseHandle(event);
-  return 0;
-}
-
-
-win_aspi_device::win_aspi_device(smart_interface * intf,
-  const char * dev_name, const char * req_type)
-: smart_device(intf, dev_name, "scsi", req_type),
-  m_adapter(-1), m_id(0)
-{
-}
-
-bool win_aspi_device::is_open() const
-{
-  return (m_adapter >= 0);
-}
-
-bool win_aspi_device::open()
-{
-  // scsi[0-9][0-f] => ASPI Adapter 0-9, ID 0-15, LUN 0
-  unsigned adapter = ~0, id = ~0; int n1 = -1;
-  const char * name = skipdev(get_dev_name());
-  if (!(sscanf(name,"scsi%1u%1x%n", &adapter, &id, &n1) == 2 && n1 == (int)strlen(name)
-        && adapter <= 9 && id < 16))
-    return set_err(EINVAL);
-
-  if (!aspi_entry_valid()) {
-    if (aspi_open_dll(1/*verbose*/))
-      return set_err(ENOENT);
-  }
-
-  // Adapter OK?
-  if (adapter >= num_aspi_adapters) {
-    pout("ASPI Adapter %u does not exist (%u Adapter%s detected).\n",
-      adapter, num_aspi_adapters, (num_aspi_adapters!=1?"s":""));
-    if (!is_permissive())
-      return set_err(ENOENT);
-  }
-
-  // Device present ?
-  ASPI_SRB srb;
-  memset(&srb, 0, sizeof(srb));
-  srb.h.cmd = ASPI_CMD_GET_DEVICE_TYPE;
-  srb.h.adapter = adapter; srb.i.target_id = id;
-  if (aspi_call(&srb))
-    return set_err(EIO);
-  if (srb.h.status != ASPI_STATUS_NO_ERROR) {
-    pout("ASPI Adapter %u, ID %u: No such device (Status=0x%02x)\n", adapter, id, srb.h.status);
-    if (!is_permissive())
-      return set_err(srb.h.status == ASPI_STATUS_INVALID_TARGET ? ENOENT : EIO);
-  }
-  else if (scsi_debugmode)
-    pout("ASPI Adapter %u, ID %u: Device Type=0x%02x\n", adapter, id, srb.t.devtype);
-
-  m_adapter = (int)adapter; m_id = (unsigned char)id;
-  return true;
-}
-
-
-bool win_aspi_device::close()
-{
-  // No FreeLibrary(h_aspi_dll) to prevent problems with ASPI threads
-  return true;
-}
-
-
-// Scan for ASPI drives
-
-bool win9x_smart_interface::scsi_scan(smart_device_list & devlist)
-{
-  if (!aspi_entry_valid()) {
-    if (aspi_open_dll(scsi_debugmode/*default is quiet*/))
-      return true;
-  }
-
-  for (unsigned ad = 0; ad < num_aspi_adapters; ad++) {
-    ASPI_SRB srb;
-
-    if (ad > 9) {
-      if (scsi_debugmode)
-        pout(" ASPI Adapter %u: Ignored\n", ad);
-      continue;
-    }
-
-    // Get adapter name
-    memset(&srb, 0, sizeof(srb));
-    srb.h.cmd = ASPI_CMD_ADAPTER_INQUIRE;
-    srb.h.adapter = ad;
-    if (aspi_call(&srb))
-      break;
-
-    if (srb.h.status != ASPI_STATUS_NO_ERROR) {
-      if (scsi_debugmode)
-        pout(" ASPI Adapter %u: Status=0x%02x\n", ad, srb.h.status);
-      continue;
-    }
-
-    if (scsi_debugmode) {
-      for (int i = 1; i < 16 && srb.q.adapter_id[i]; i++)
-        if (!(' ' <= srb.q.adapter_id[i] && srb.q.adapter_id[i] <= '~'))
-          srb.q.adapter_id[i] = '?';
-      pout(" ASPI Adapter %u (\"%.16s\"):\n", ad, srb.q.adapter_id);
-    }
-
-    bool ignore = !strnicmp(srb.q.adapter_id, "3ware", 5);
-
-    for (unsigned id = 0; id <= 7; id++) {
-      // Get device type
-      memset(&srb, 0, sizeof(srb));
-      srb.h.cmd = ASPI_CMD_GET_DEVICE_TYPE;
-      srb.h.adapter = ad; srb.i.target_id = id;
-      if (aspi_call(&srb))
-        return 0;
-      if (srb.h.status != ASPI_STATUS_NO_ERROR) {
-        if (scsi_debugmode > 1)
-          pout("  ID %u: No such device (Status=0x%02x)\n", id, srb.h.status);
-        continue;
-      }
-
-      if (!ignore && srb.t.devtype == 0x00/*HDD*/) {
-        if (scsi_debugmode)
-          pout("  ID %u: Device Type=0x%02x\n", id, srb.t.devtype);
-        char name[20];
-        sprintf(name, "/dev/scsi%u%u", ad, id);
-        devlist.push_back( new win_aspi_device(this, name, "scsi") );
-      }
-      else if (scsi_debugmode)
-        pout("  ID %u: Device Type=0x%02x (ignored)\n", id, srb.t.devtype);
-    }
-  }
-  return true;
-}
-
-
-// Interface to ASPI SCSI devices
-bool win_aspi_device::scsi_pass_through(scsi_cmnd_io * iop)
-{
-  int report = scsi_debugmode; // TODO
-
-  if (m_adapter < 0) {
-    set_err(EBADF);
-    return false;
-  }
-
-  if (!aspi_entry_valid()) {
-    set_err(EBADF);
-    return false;
-  }
-
-  if (!(iop->cmnd_len == 6 || iop->cmnd_len == 10 || iop->cmnd_len == 12 || iop->cmnd_len == 16)) {
-    set_err(EINVAL, "bad CDB length");
-    return false;
-  }
-
-  if (report > 0) {
-    // From os_linux.c
-    int k, j;
-    const unsigned char * ucp = iop->cmnd;
-    const char * np;
-    char buff[256];
-    const int sz = (int)sizeof(buff);
-
-    np = scsi_get_opcode_name(ucp[0]);
-    j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>");
-    for (k = 0; k < (int)iop->cmnd_len; ++k)
-      j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "%02x ", ucp[k]);
-    if ((report > 1) &&
-      (DXFER_TO_DEVICE == iop->dxfer_dir) && (iop->dxferp)) {
-      int trunc = (iop->dxfer_len > 256) ? 1 : 0;
-
-      j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n  Outgoing "
-              "data, len=%d%s:\n", (int)iop->dxfer_len,
-              (trunc ? " [only first 256 bytes shown]" : ""));
-      dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
-    }
-    else
-      j += snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n");
-    pout("%s", buff);
-  }
-
-  ASPI_SRB srb;
-  memset(&srb, 0, sizeof(srb));
-  srb.h.cmd = ASPI_CMD_EXECUTE_IO;
-  srb.h.adapter = m_adapter;
-  srb.i.target_id = m_id;
-  //srb.i.lun = 0;
-  srb.i.sense_size = ASPI_SENSE_SIZE;
-  srb.i.cdb_size = iop->cmnd_len;
-  memcpy(srb.i.cdb, iop->cmnd, iop->cmnd_len);
-
-  switch (iop->dxfer_dir) {
-    case DXFER_NONE:
-      srb.h.flags = ASPI_REQFLAG_DIR_NO_XFER;
-      break;
-    case DXFER_FROM_DEVICE:
-      srb.h.flags = ASPI_REQFLAG_DIR_TO_HOST;
-      srb.i.data_size = iop->dxfer_len;
-      srb.i.data_addr = iop->dxferp;
-      break;
-    case DXFER_TO_DEVICE:
-      srb.h.flags = ASPI_REQFLAG_DIR_TO_TARGET;
-      srb.i.data_size = iop->dxfer_len;
-      srb.i.data_addr = iop->dxferp;
-      break;
-    default:
-      set_err(EINVAL, "bad dxfer_dir");
-      return false;
-  }
-
-  iop->resp_sense_len = 0;
-  iop->scsi_status = 0;
-  iop->resid = 0;
-
-  if (aspi_io_call(&srb, (iop->timeout ? iop->timeout : 60))) {
-    // Timeout
-    set_err(EIO, "ASPI Timeout"); return false;
-  }
-
-  if (srb.h.status != ASPI_STATUS_NO_ERROR) {
-    if (   srb.h.status        == ASPI_STATUS_ERROR
-        && srb.i.host_status   == ASPI_HSTATUS_NO_ERROR
-        && srb.i.target_status == ASPI_TSTATUS_CHECK_CONDITION) {
-      // Sense valid
-      const unsigned char * sense = ASPI_SRB_SENSE(&srb.i, iop->cmnd_len);
-      int len = (ASPI_SENSE_SIZE < iop->max_sense_len ? ASPI_SENSE_SIZE : iop->max_sense_len);
-      iop->scsi_status = SCSI_STATUS_CHECK_CONDITION;
-      if (len > 0 && iop->sensep) {
-        memcpy(iop->sensep, sense, len);
-        iop->resp_sense_len = len;
-        if (report > 1) {
-          pout("  >>> Sense buffer, len=%d:\n", (int)len);
-          dStrHex(iop->sensep, len , 1);
-        }
-      }
-      if (report) {
-        pout("  sense_key=%x asc=%x ascq=%x\n",
-         sense[2] & 0xf, sense[12], sense[13]);
-      }
-      return true;
-    }
-    else {
-      if (report)
-        pout("  ASPI call failed, (0x%02x,0x%02x,0x%02x)\n", srb.h.status, srb.i.host_status, srb.i.target_status);
-      set_err(EIO);
-      return false;
-    }
-  }
-
-  if (report > 0)
-    pout("  OK\n");
-
-  if (iop->dxfer_dir == DXFER_FROM_DEVICE && report > 1) {
-     int trunc = (iop->dxfer_len > 256) ? 1 : 0;
-     pout("  Incoming data, len=%d%s:\n", (int)iop->dxfer_len,
-        (trunc ? " [only first 256 bytes shown]" : ""));
-        dStrHex(iop->dxferp, (trunc ? 256 : iop->dxfer_len) , 1);
-  }
-
-  return true;
-}
-
-#endif // WIN9X_SUPPORT
-
 /////////////////////////////////////////////////////////////////////////////
 // SPT Interface (for SCSI devices and ATA devices behind SATLs)
 // Only supported in NT and later
@@ -4043,11 +3185,11 @@ win_scsi_device::win_scsi_device(smart_interface * intf,
 bool win_scsi_device::open()
 {
   const char * name = skipdev(get_dev_name()); int len = strlen(name);
-  // sd[a-z],N => Physical drive 0-26, RAID port N
-  char drive[1+1] = ""; int sub_addr = -1; int n1 = -1; int n2 = -1;
-  if (   sscanf(name, "sd%1[a-z]%n,%d%n", drive, &n1, &sub_addr, &n2) >= 1
+  // sd[a-z]([a-z])?,N => Physical drive 0-701, RAID port N
+  char drive[2+1] = ""; int sub_addr = -1; int n1 = -1; int n2 = -1;
+  if (   sscanf(name, "sd%2[a-z]%n,%d%n", drive, &n1, &sub_addr, &n2) >= 1
       && ((n1 == len && sub_addr == -1) || (n2 == len && sub_addr >= 0))  ) {
-    return open(drive[0] - 'a', -1, -1, sub_addr);
+    return open(sdxy_to_phydrive(drive), -1, -1, sub_addr);
   }
   // pd<m>,N => Physical drive <m>, RAID port N
   int pd_num = -1; sub_addr = -1; n1 = -1; n2 = -1;
@@ -4098,7 +3240,7 @@ bool win_scsi_device::open(int pd_num, int ld_num, int tape_num, int /*sub_addr*
            FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
            OPEN_EXISTING, 0, 0);
   if (h == INVALID_HANDLE_VALUE) {
-    set_err(ENODEV, "%s: Open failed, Error=%ld", b, GetLastError());
+    set_err(ENODEV, "%s: Open failed, Error=%u", b, (unsigned)GetLastError());
     return false;
   }
   set_fh(h);
@@ -4285,7 +3427,7 @@ bool win_scsi_device::scsi_pass_through(struct scsi_cmnd_io * iop)
 }
 
 // Interface to SPT SCSI devices.  See scsicmds.h and os_linux.c
-static long scsi_pass_through_direct(HANDLE fd, struct scsi_cmnd_io * iop)
+static long scsi_pass_through_direct(HANDLE fd, UCHAR targetid, struct scsi_cmnd_io * iop)
 {
   int report = scsi_debugmode; // TODO
 
@@ -4322,7 +3464,7 @@ static long scsi_pass_through_direct(HANDLE fd, struct scsi_cmnd_io * iop)
   memset(&sb, 0, sizeof(sb));
   sb.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
   //sb.spt.PathId = 0;
-  sb.spt.TargetId = 127;
+  sb.spt.TargetId = targetid;
   //sb.spt.Lun = 0;
   sb.spt.CdbLength = iop->cmnd_len;
   memcpy(sb.spt.Cdb, iop->cmnd, iop->cmnd_len);
@@ -4411,229 +3553,109 @@ static long scsi_pass_through_direct(HANDLE fd, struct scsi_cmnd_io * iop)
   return 0;
 }
 
-
-#if 0 // For debugging areca code
-
-static void dumpdata(unsigned char *block, int len)
+// Areca RAID Controller(SAS Device)
+win_areca_scsi_device::win_areca_scsi_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca")
 {
-  int ln = (len / 16) + 1;   // total line#
-  unsigned char c;
-  int pos = 0;
-
-  printf(" Address = %p, Length = (0x%x)%d\n", block, len, len);
-  printf("      0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F      ASCII      \n");
-  printf("=====================================================================\n");
-
-  for ( int l = 0; l < ln && len; l++ )
-  {
-    // printf the line# and the HEX data
-    // if a line data length < 16 then append the space to the tail of line to reach 16 chars
-    printf("%02X | ", l);
-    for ( pos = 0; pos < 16 && len; pos++, len-- )
-    {
-      c = block[l*16+pos];
-      printf("%02X ", c);
-    }
-
-    if ( pos < 16 )
-    {
-      for ( int loop = pos; loop < 16; loop++ )
-      {
-        printf("   ");
-      }
-    }
-
-    // print ASCII char
-    for ( int loop = 0; loop < pos; loop++ )
-    {
-      c = block[l*16+loop];
-      if ( c >= 0x20 && c <= 0x7F )
-      {
-        printf("%c", c);
-      }
-      else
-      {
-        printf(".");
-      }
-    }
-    printf("\n");
-  }
-  printf("=====================================================================\n");
+    set_fh(INVALID_HANDLE_VALUE);
+    set_disknum(disknum);
+    set_encnum(encnum);
+    set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
 }
 
-#endif
-
-// PURPOSE
-//   This is an interface routine meant to isolate the OS dependent
-//   parts of the code, and to provide a debugging interface.  Each
-//   different port and OS needs to provide it's own interface.  This
-//   is the Windows interface to the Areca "arcmsr" driver.  It allows ATA
-//   commands to be passed through the SCSI driver.
-// DETAILED DESCRIPTION OF ARGUMENTS
-//   fd: is the file descriptor provided by open()
-//   disknum is the disk number (0 to 127) in the RAID array
-//   command: defines the different operations.
-//   select: additional input data if needed (which log, which type of
-//           self-test).
-//   data:   location to write output data, if needed (512 bytes).
-//   Note: not all commands use all arguments.
-// RETURN VALUES
-//  -1 if the command failed
-//   0 if the command succeeded,
-//   STATUS_CHECK routine:
-//  -1 if the command failed
-//   0 if the command succeeded and disk SMART status is "OK"
-//   1 if the command succeeded and disk SMART status is "FAILING"
-int win_areca_device::arcmsr_command_handler(HANDLE fd, unsigned long arcmsr_cmd, unsigned char *data, int data_len)
+bool win_areca_scsi_device::open()
 {
-  int ioctlreturn = 0;
-  sSRB_BUFFER sBuf;
-  struct scsi_cmnd_io io_hdr;
-  int dir = DXFER_TO_DEVICE;
-
-  UINT8 cdb[10];
-  UINT8 sense[32];
-
-  unsigned char *areca_return_packet;
-  int total = 0;
-  int expected = -1;
-  unsigned char return_buff[2048];
-  unsigned char *ptr = &return_buff[0];
-  memset(return_buff, 0, sizeof(return_buff));
-
-  memset((unsigned char *)&sBuf, 0, sizeof(sBuf));
-  memset(&io_hdr, 0, sizeof(io_hdr));
-  memset(cdb, 0, sizeof(cdb));
-  memset(sense, 0, sizeof(sense));
-
-
-  sBuf.srbioctl.HeaderLength = sizeof(sSRB_IO_CONTROL);
-  memcpy(sBuf.srbioctl.Signature, ARECA_SIG_STR, strlen(ARECA_SIG_STR));
-  sBuf.srbioctl.Timeout = 10000;
-  sBuf.srbioctl.ControlCode = arcmsr_cmd;
+  HANDLE hFh;
 
-  switch ( arcmsr_cmd )
+  if( is_open() )
   {
-  // command for writing data to driver
-  case ARCMSR_IOCTL_WRITE_WQBUFFER:
-    if ( data && data_len )
-    {
-      sBuf.srbioctl.Length = data_len;
-      memcpy((unsigned char *)sBuf.ioctldatabuffer, (unsigned char *)data, data_len);
-    }
-    // commands for clearing related buffer of driver
-  case ARCMSR_IOCTL_CLEAR_RQBUFFER:
-  case ARCMSR_IOCTL_CLEAR_WQBUFFER:
-    cdb[0] = 0x3B; //SCSI_WRITE_BUF command;
-    break;
-  // command for reading data from driver
-  case ARCMSR_IOCTL_READ_RQBUFFER:
-  // command for identifying driver
-  case ARCMSR_IOCTL_RETURN_CODE_3F:
-    cdb[0] = 0x3C; //SCSI_READ_BUF command;
-    dir = DXFER_FROM_DEVICE;
-    break;
-  default:
-    // unknown arcmsr commands
-    return -1;
+    return true;
+  }
+  hFh = CreateFile( get_dev_name(),
+                    GENERIC_READ|GENERIC_WRITE,
+                    FILE_SHARE_READ|FILE_SHARE_WRITE,
+                    NULL,
+                    OPEN_EXISTING,
+                    0,
+                    NULL );
+  if(hFh == INVALID_HANDLE_VALUE)
+  {
+    return false;
   }
 
-  cdb[1] = 0x01;
-  cdb[2] = 0xf0;
+  set_fh(hFh);
+  return true;
+}
 
-  io_hdr.dxfer_dir = dir;
-  io_hdr.dxfer_len = sizeof(sBuf);
-  io_hdr.dxferp = (unsigned char *)&sBuf;
-  io_hdr.cmnd = cdb;
-  io_hdr.cmnd_len = sizeof(cdb);
-  io_hdr.sensep = sense;
-  io_hdr.max_sense_len = sizeof(sense);
-  io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
+smart_device * win_areca_scsi_device::autodetect_open()
+{
+  return this;
+}
 
-  while ( 1 )
-  {
-    ioctlreturn = scsi_pass_through_direct(fd, &io_hdr);
-    if ( ioctlreturn || io_hdr.scsi_status )
-    {
-      // errors found
-      break;
-    }
+int win_areca_scsi_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
+{
+   int ioctlreturn = 0;
 
-    if ( arcmsr_cmd != ARCMSR_IOCTL_READ_RQBUFFER )
-    {
-      // if succeeded, just returns the length of outgoing data
-      return data_len;
-    }
+   ioctlreturn = scsi_pass_through_direct(get_fh(), 16, iop);
+   if ( ioctlreturn || iop->scsi_status )
+   {
+     ioctlreturn = scsi_pass_through_direct(get_fh(), 127, iop);
+     if ( ioctlreturn || iop->scsi_status )
+     {
+       // errors found
+       return -1;
+     }
+   }
 
-    if ( sBuf.srbioctl.Length )
-    {
-      //dumpdata(&sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
-      memcpy(ptr, &sBuf.ioctldatabuffer[0], sBuf.srbioctl.Length);
-      ptr += sBuf.srbioctl.Length;
-      total += sBuf.srbioctl.Length;
-      // the returned bytes enough to compute payload length ?
-      if ( expected < 0 && total >= 5 )
-      {
-        areca_return_packet = (unsigned char *)&return_buff[0];
-        if ( areca_return_packet[0] == 0x5E &&
-           areca_return_packet[1] == 0x01 &&
-           areca_return_packet[2] == 0x61 )
-        {
-          // valid header, let's compute the returned payload length,
-          // we expected the total length is
-          // payload + 3 bytes header + 2 bytes length + 1 byte checksum
-          expected = areca_return_packet[4] * 256 + areca_return_packet[3] + 6;
-        }
-      }
+   return ioctlreturn;
+}
 
-      if ( total >= 7 && total >= expected )
-      {
-        //printf("total bytes received = %d, expected length = %d\n", total, expected);
+bool win_areca_scsi_device::arcmsr_lock()
+{
+#define    SYNCOBJNAME "Global\\SynIoctlMutex"
+  int ctlrnum = -1;
+  char mutexstr[64];
 
-        // ------ Okay! we received enough --------
-        break;
-      }
-    }
-  }
+  if (sscanf(get_dev_name(), "\\\\.\\scsi%d:", &ctlrnum) < 1)
+    return set_err(EINVAL, "unable to parse device name");
 
-  // Deal with the different error cases
-  if ( arcmsr_cmd == ARCMSR_IOCTL_RETURN_CODE_3F )
+  snprintf(mutexstr, sizeof(mutexstr), "%s%d", SYNCOBJNAME, ctlrnum);
+  m_mutex = CreateMutex(NULL, FALSE, mutexstr);
+  if ( m_mutex == NULL )
   {
-    // Silence the ARCMSR_IOCTL_RETURN_CODE_3F's error, no pout(...)
-    return -4;
+    return set_err(EIO, "CreateMutex failed");
   }
 
-  if ( ioctlreturn )
-  {
-    pout("do_scsi_cmnd_io with write buffer failed code = %x\n", ioctlreturn);
-    return -2;
-  }
+  // atomic access to driver
+  WaitForSingleObject(m_mutex, INFINITE);
+
+  return true;
+}
 
-  if ( io_hdr.scsi_status )
-  {
-    pout("io_hdr.scsi_status with write buffer failed code = %x\n", io_hdr.scsi_status);
-    return -3;
-  }
 
-  if ( data )
+bool win_areca_scsi_device::arcmsr_unlock()
+{
+  if( m_mutex != NULL)
   {
-    memcpy(data, return_buff, total);
+      ReleaseMutex(m_mutex);
+      CloseHandle(m_mutex);
   }
 
-  return total;
+  return true;
 }
 
 
-win_areca_device::win_areca_device(smart_interface * intf, const char * dev_name, HANDLE fh, int disknum, int encnum)
-: smart_device(intf, dev_name, "areca", "areca"),
-  m_disknum(disknum),
-  m_encnum(encnum)
+// Areca RAID Controller(SATA Disk)
+win_areca_ata_device::win_areca_ata_device(smart_interface * intf, const char * dev_name, int disknum, int encnum)
+: smart_device(intf, dev_name, "areca", "areca")
 {
-  set_fh(fh);
+  set_fh(INVALID_HANDLE_VALUE);
+  set_disknum(disknum);
+  set_encnum(encnum);
   set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
 }
 
-bool win_areca_device::open()
+bool win_areca_ata_device::open()
 {
   HANDLE hFh;
 
@@ -4641,7 +3663,6 @@ bool win_areca_device::open()
   {
     return true;
   }
-
   hFh = CreateFile( get_dev_name(),
                     GENERIC_READ|GENERIC_WRITE,
                     FILE_SHARE_READ|FILE_SHARE_WRITE,
@@ -4658,256 +3679,83 @@ bool win_areca_device::open()
   return true;
 }
 
-// Areca RAID Controller
-bool win_areca_device::arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
+smart_device * win_areca_ata_device::autodetect_open()
 {
-  // ATA input registers
-  typedef struct _ATA_INPUT_REGISTERS
-  {
-    unsigned char features;
-    unsigned char sector_count;
-    unsigned char sector_number;
-    unsigned char cylinder_low;
-    unsigned char cylinder_high;
-    unsigned char device_head;
-    unsigned char command;
-    unsigned char reserved[8];
-    unsigned char data[512]; // [in/out] buffer for outgoing/incoming data
-  } sATA_INPUT_REGISTERS;
-
-  // ATA output registers
-  // Note: The output registers is re-sorted for areca internal use only
-  typedef struct _ATA_OUTPUT_REGISTERS
-  {
-    unsigned char error;
-    unsigned char status;
-    unsigned char sector_count;
-    unsigned char sector_number;
-    unsigned char cylinder_low;
-    unsigned char cylinder_high;
-  } sATA_OUTPUT_REGISTERS;
-
-  // Areca packet format for outgoing:
-  // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
-  // B[3~4] : 2 bytes command length + variant data length, little endian
-  // B[5]   : 1 bytes areca defined command code, ATA passthrough command code is 0x1c
-  // B[6~last-1] : variant bytes payload data
-  // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
-  //
-  //
-  //   header 3 bytes  length 2 bytes   cmd 1 byte    payload data x bytes  cs 1 byte
-  // +--------------------------------------------------------------------------------+
-  // + 0x5E 0x01 0x61 |   0x00 0x00   |     0x1c   | .................... |   0x00    |
-  // +--------------------------------------------------------------------------------+
-  //
-
-  //Areca packet format for incoming:
-  // B[0~2] : 3 bytes header, fixed value 0x5E, 0x01, 0x61
-  // B[3~4] : 2 bytes payload length, little endian
-  // B[5~last-1] : variant bytes returned payload data
-  // B[last] : 1 byte checksum, simply sum(B[3] ~ B[last -1])
-  //
-  //
-  //   header 3 bytes  length 2 bytes   payload data x bytes  cs 1 byte
-  // +-------------------------------------------------------------------+
-  // + 0x5E 0x01 0x61 |   0x00 0x00   | .................... |   0x00    |
-  // +-------------------------------------------------------------------+
-  unsigned char    areca_packet[640];
-  int areca_packet_len = sizeof(areca_packet);
-  unsigned char cs = 0;
-
-  sATA_INPUT_REGISTERS *ata_cmd;
-
-  // For debugging
-#if 0
-  memset(sInq, 0, sizeof(sInq));
-  scsiStdInquiry(fd, (unsigned char *)sInq, (int)sizeof(sInq));
-  dumpdata((unsigned char *)sInq, sizeof(sInq));
-#endif
-  memset(areca_packet, 0, areca_packet_len);
+  int is_ata = 1;
 
-  // ----- BEGIN TO SETUP HEADERS -------
-  areca_packet[0] = 0x5E;
-  areca_packet[1] = 0x01;
-  areca_packet[2] = 0x61;
-  areca_packet[3] = (unsigned char)((areca_packet_len - 6) & 0xff);
-  areca_packet[4] = (unsigned char)(((areca_packet_len - 6) >> 8) & 0xff);
-  areca_packet[5] = 0x1c;  // areca defined code for ATA passthrough command
-
-  // ----- BEGIN TO SETUP PAYLOAD DATA -----
-  memcpy(&areca_packet[7], "SmrT", 4);  // areca defined password
-  ata_cmd = (sATA_INPUT_REGISTERS *)&areca_packet[12];
-
-  // Set registers
-  {
-    const ata_in_regs & r = in.in_regs;
-    ata_cmd->features      = r.features;
-    ata_cmd->sector_count  = r.sector_count;
-    ata_cmd->sector_number = r.lba_low;
-    ata_cmd->cylinder_low  = r.lba_mid;
-    ata_cmd->cylinder_high = r.lba_high;
-    ata_cmd->device_head   = r.device;
-    ata_cmd->command       = r.command;
-  }
-  bool readdata = false;
-  if (in.direction == ata_cmd_in::data_in) {
-      readdata = true;
-      // the command will read data
-      areca_packet[6] = 0x13;
-  }
-  else if ( in.direction == ata_cmd_in::no_data )
+  // autodetect device type
+  is_ata = arcmsr_get_dev_type();
+  if(is_ata < 0)
   {
-    // the commands will return no data
-    areca_packet[6] = 0x15;
+    set_err(EIO);
+    return this;
   }
-  else if (in.direction == ata_cmd_in::data_out)
-  {
-    // the commands will write data
-    memcpy(ata_cmd->data, in.buffer, in.size);
-    areca_packet[6] = 0x14;
-  }
-  else {
-      // COMMAND NOT SUPPORTED VIA ARECA IOCTL INTERFACE
-      return set_err(ENOSYS);
-  }
-
-  areca_packet[11] = m_disknum - 1;  // disk#
-  areca_packet[19] = m_encnum - 1;   // enc#
 
-  // ----- BEGIN TO SETUP CHECKSUM -----
-  for ( int loop = 3; loop < areca_packet_len - 1; loop++ )
+  if(is_ata == 1)
   {
-    cs += areca_packet[loop];
-  }
-  areca_packet[areca_packet_len-1] = cs;
-
-  // ----- BEGIN TO SEND TO ARECA DRIVER ------
-  int expected = 0;
-  unsigned char return_buff[2048];
-  memset(return_buff, 0, sizeof(return_buff));
-
-  expected = arcmsr_command_handler(get_fh(), ARCMSR_IOCTL_CLEAR_RQBUFFER, NULL, 0);
-  if (expected==-3) {
-      return set_err(EIO);
+    // SATA device
+    return this;
   }
 
-  expected = arcmsr_command_handler(get_fh(), ARCMSR_IOCTL_CLEAR_WQBUFFER, NULL, 0);
-  expected = arcmsr_command_handler(get_fh(), ARCMSR_IOCTL_WRITE_WQBUFFER, areca_packet, areca_packet_len);
-  if ( expected > 0 )
-  {
-    expected = arcmsr_command_handler(get_fh(), ARCMSR_IOCTL_READ_RQBUFFER, return_buff, sizeof(return_buff));
-  }
-  if ( expected < 0 )
-  {
-    return set_err(EIO);
-  }
+  // SAS device
+  smart_device_auto_ptr newdev(new win_areca_scsi_device(smi(), get_dev_name(), get_disknum(), get_encnum()));
+  close();
+  delete this;
+  newdev->open(); // TODO: Can possibly pass open fd
 
-  // ----- VERIFY THE CHECKSUM -----
-  cs = 0;
-  for ( int loop = 3; loop < expected - 1; loop++ )
-  {
-    cs += return_buff[loop];
-  }
+  return newdev.release();
+}
 
-  if ( return_buff[expected - 1] != cs )
-  {
-    return set_err(EIO);
-  }
+int win_areca_ata_device::arcmsr_do_scsi_io(struct scsi_cmnd_io * iop)
+{
+   int ioctlreturn = 0;
 
-  sATA_OUTPUT_REGISTERS *ata_out = (sATA_OUTPUT_REGISTERS *)&return_buff[5] ;
-  if ( ata_out->status )
-  {
-    if ( in.in_regs.command == ATA_IDENTIFY_DEVICE
-     && !nonempty((unsigned char *)in.buffer, in.size))
+   ioctlreturn = scsi_pass_through_direct(get_fh(), 16, iop);
+   if ( ioctlreturn || iop->scsi_status )
+   {
+     ioctlreturn = scsi_pass_through_direct(get_fh(), 127, iop);
+     if ( ioctlreturn || iop->scsi_status )
      {
-        return set_err(ENODEV, "No drive on port %d", m_disknum);
+       // errors found
+       return -1;
      }
-  }
+   }
 
-  // returns with data
-  if (readdata)
-  {
-    memcpy(in.buffer, &return_buff[7], in.size);
-  }
-
-  // Return register values
-  {
-    ata_out_regs & r = out.out_regs;
-    r.error          = ata_out->error;
-    r.sector_count   = ata_out->sector_count;
-    r.lba_low        = ata_out->sector_number;
-    r.lba_mid        = ata_out->cylinder_low;
-    r.lba_high       = ata_out->cylinder_high;
-    r.status         = ata_out->status;
-  }
-  return true;
+   return ioctlreturn;
 }
 
-
-bool win_areca_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
+bool win_areca_ata_device::arcmsr_lock()
 {
 #define    SYNCOBJNAME "Global\\SynIoctlMutex"
   int ctlrnum = -1;
   char mutexstr[64];
-  SECURITY_ATTRIBUTES sa;
-  PSECURITY_DESCRIPTOR pSD;
-  HANDLE hmutex;
-
-  if (!ata_cmd_is_ok(in,
-    true, // data_out_support
-    false, // TODO: multi_sector_support
-    true) // ata_48bit_support
-  )
-    return false;
-
-  // Support 48-bit commands with zero high bytes
-  if (in.in_regs.is_real_48bit_cmd())
-    return set_err(ENOSYS, "48-bit ATA commands not fully supported by Areca");
 
   if (sscanf(get_dev_name(), "\\\\.\\scsi%d:", &ctlrnum) < 1)
     return set_err(EINVAL, "unable to parse device name");
 
-  memset(mutexstr, 0, sizeof(mutexstr));
-  sprintf(mutexstr, "%s%d",SYNCOBJNAME, ctlrnum);
-  pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
-  if ( !InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) )
+  snprintf(mutexstr, sizeof(mutexstr), "%s%d", SYNCOBJNAME, ctlrnum);
+  m_mutex = CreateMutex(NULL, FALSE, mutexstr);
+  if ( m_mutex == NULL )
   {
-    LocalFree((HLOCAL)pSD);
-    return set_err(EIO, "InitializeSecurityDescriptor failed");
-  }
-
-  if ( !SetSecurityDescriptorDacl(pSD, TRUE, (PACL)NULL, FALSE) )
-  {
-    LocalFree((HLOCAL)pSD);
-    return set_err(EIO, "SetSecurityDescriptor failed");
-  }
-
-  sa.nLength = sizeof(SECURITY_ATTRIBUTES);
-  sa.lpSecurityDescriptor = pSD;
-  sa.bInheritHandle = TRUE;
-  hmutex = CreateMutex(&sa, FALSE, mutexstr);
-  if ( hmutex == NULL )
-  {
-    LocalFree((HLOCAL)pSD);
     return set_err(EIO, "CreateMutex failed");
   }
 
   // atomic access to driver
-  WaitForSingleObject(hmutex, INFINITE);
-  bool ok = arcmsr_ata_pass_through(in,out);
-  ReleaseMutex(hmutex);
+  WaitForSingleObject(m_mutex, INFINITE);
 
-  if(hmutex)
-  {
-    CloseHandle(hmutex);
-  }
+  return true;
+}
 
-  if ( (HLOCAL)pSD )
+
+bool win_areca_ata_device::arcmsr_unlock()
+{
+  if( m_mutex != NULL)
   {
-    LocalFree((HLOCAL)pSD);
+      ReleaseMutex(m_mutex);
+      CloseHandle(m_mutex);
   }
 
-  return ok;
+  return true;
 }
 
 
@@ -4930,19 +3778,8 @@ void smart_interface::init()
       SetDllDirectoryA_p("");
   }
 
-  // Select interface for Windows flavor
-  if (GetVersion() & 0x80000000) {
-#if WIN9X_SUPPORT
-    static os_win32::win9x_smart_interface the_win9x_interface;
-    smart_interface::set(&the_win9x_interface);
-#else
-    throw std::runtime_error("Win9x/ME not supported");
-#endif
-  }
-  else {
-    static os_win32::winnt_smart_interface the_winnt_interface;
-    smart_interface::set(&the_winnt_interface);
-  }
+  static os_win32::win_smart_interface the_win_interface;
+  smart_interface::set(&the_win_interface);
 }
 
 
index 481f0b5faf187cbcab5f18389f5eaa0ba86f6139..ae3dc29173697a84f4c779df12f1a1d338279283 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2004-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2004-13 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
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
-// Need MB_SERVICE_NOTIFICATION (NT4/2000/XP), IsDebuggerPresent() (Win98/ME/NT4/2000/XP)
-#define WINVER 0x0400
+#define WINVER 0x0600
 #define _WIN32_WINNT WINVER
 
+#include "daemon_win32.h"
+
+const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 3760 2013-01-30 18:43:39Z chrfranke $"
+  DAEMON_WIN32_H_CVSID;
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <crtdbg.h>
 #endif
 
-#include "daemon_win32.h"
-
-const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 3426 2011-10-06 18:23:15Z chrfranke $"
-  DAEMON_WIN32_H_CVSID;
+#ifndef SERVICE_CONFIG_DELAYED_AUTO_START_INFO
+// Missing in older MinGW headers
+#define SERVICE_CONFIG_DELAYED_AUTO_START_INFO 3
+#endif
 
 
 /////////////////////////////////////////////////////////////////////////////
 
-#define ARGUSED(x) ((void)(x))
-
 // Prevent spawning of child process if debugging
 #ifdef _DEBUG
 #define debugging() IsDebuggerPresent()
@@ -58,94 +59,94 @@ const char * daemon_win32_cpp_cvsid = "$Id: daemon_win32.cpp 3426 2011-10-06 18:
 
 static void make_name(char * name, int sig)
 {
-       int i;
-       if (!GetModuleFileNameA(NULL, name, EVT_NAME_LEN-10))
-               strcpy(name, "DaemonEvent");
-       for (i = 0; name[i]; i++) {
-               char c = name[i];
-               if (!(   ('0' <= c && c <= '9')
-                     || ('A' <= c && c <= 'Z')
-                     || ('a' <= c && c <= 'z')))
-                         name[i] = '_';
-       }
-       sprintf(name+strlen(name), "-%d", sig);
+  int i;
+  if (!GetModuleFileNameA(NULL, name, EVT_NAME_LEN-10))
+    strcpy(name, "DaemonEvent");
+  for (i = 0; name[i]; i++) {
+    char c = name[i];
+    if (!(   ('0' <= c && c <= '9')
+          || ('A' <= c && c <= 'Z')
+          || ('a' <= c && c <= 'z')))
+        name[i] = '_';
+  }
+  sprintf(name+strlen(name), "-%d", sig);
 }
 
 
 static HANDLE create_event(int sig, BOOL initial, BOOL errmsg, BOOL * exists)
 {
-       char name[EVT_NAME_LEN];
-       HANDLE h;
-       if (sig >= 0)
-               make_name(name, sig);
-       else
-               name[0] = 0;
-       if (exists)
-               *exists = FALSE;
-       if (!(h = CreateEventA(NULL, FALSE, initial, (name[0] ? name : NULL)))) {
-               if (errmsg)
-                       fprintf(stderr, "CreateEvent(.,\"%s\"): Error=%ld\n", name, GetLastError());
-               return 0;
-       }
-
-       if (GetLastError() == ERROR_ALREADY_EXISTS) {
-               if (!exists) {
-                       if (errmsg)
-                               fprintf(stderr, "CreateEvent(.,\"%s\"): Exists\n", name);
-                       CloseHandle(h);
-                       return 0;
-               }
-               *exists = TRUE;
-       }
-       return h;
+  char name[EVT_NAME_LEN];
+  HANDLE h;
+  if (sig >= 0)
+    make_name(name, sig);
+  else
+    name[0] = 0;
+  if (exists)
+    *exists = FALSE;
+  if (!(h = CreateEventA(NULL, FALSE, initial, (name[0] ? name : NULL)))) {
+    if (errmsg)
+      fprintf(stderr, "CreateEvent(.,\"%s\"): Error=%ld\n", name, GetLastError());
+    return 0;
+  }
+
+  if (GetLastError() == ERROR_ALREADY_EXISTS) {
+    if (!exists) {
+      if (errmsg)
+        fprintf(stderr, "CreateEvent(.,\"%s\"): Exists\n", name);
+      CloseHandle(h);
+      return 0;
+    }
+    *exists = TRUE;
+  }
+  return h;
 }
 
 
 static HANDLE open_event(int sig)
 {
-       char name[EVT_NAME_LEN];
-       make_name(name, sig);
-       return OpenEventA(EVENT_MODIFY_STATE, FALSE, name);
+  char name[EVT_NAME_LEN];
+  make_name(name, sig);
+  return OpenEventA(EVENT_MODIFY_STATE, FALSE, name);
 }
 
 
 static int event_exists(int sig)
 {
-       char name[EVT_NAME_LEN];
-       HANDLE h;
-       make_name(name, sig);
-       if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name)))
-               return 0;
-       CloseHandle(h);
-       return 1;
+  char name[EVT_NAME_LEN];
+  HANDLE h;
+  make_name(name, sig);
+  if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name)))
+    return 0;
+  CloseHandle(h);
+  return 1;
 }
 
 
 static int sig_event(int sig)
 {
-       char name[EVT_NAME_LEN];
-       HANDLE h;
-       make_name(name, sig);
-       if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name))) {
-               make_name(name, EVT_RUNNING);
-               if (!(h = OpenEvent(EVENT_MODIFY_STATE, FALSE, name)))
-                       return -1;
-               CloseHandle(h);
-               return 0;
-       }
-       SetEvent(h);
-       CloseHandle(h);
-       return 1;
+  char name[EVT_NAME_LEN];
+  HANDLE h;
+  make_name(name, sig);
+  if (!(h = OpenEventA(EVENT_MODIFY_STATE, FALSE, name))) {
+    make_name(name, EVT_RUNNING);
+    if (!(h = OpenEvent(EVENT_MODIFY_STATE, FALSE, name)))
+      return -1;
+    CloseHandle(h);
+    return 0;
+  }
+  SetEvent(h);
+  CloseHandle(h);
+  return 1;
 }
 
 
 static void daemon_help(FILE * f, const char * ident, const char * message)
 {
-       fprintf(f,
-               "%s: %s.\n"
-               "Use \"%s status|stop|reload|restart|sigusr1|sigusr2\" to control daemon.\n",
-               ident, message, ident);
-       fflush(f);
+  fprintf(f,
+    "%s: %s.\n"
+    "Use \"%s status|stop|reload|restart|sigusr1|sigusr2\" to control daemon.\n",
+    ident, message, ident);
+  fflush(f);
 }
 
 
@@ -155,64 +156,64 @@ static void daemon_help(FILE * f, const char * ident, const char * message)
 
 static BOOL WINAPI parent_console_handler(DWORD event)
 {
-       switch (event) {
-               case CTRL_C_EVENT:
-               case CTRL_BREAK_EVENT:
-                       return TRUE; // Ignore
-       }
-       return FALSE; // continue with next handler ...
+  switch (event) {
+    case CTRL_C_EVENT:
+    case CTRL_BREAK_EVENT:
+      return TRUE; // Ignore
+  }
+  return FALSE; // continue with next handler ...
 }
 
 
 static int parent_main(HANDLE rev)
 {
-       HANDLE dev;
-       HANDLE ht[2];
-       char * cmdline;
-       STARTUPINFO si;
-       PROCESS_INFORMATION pi;
-       DWORD rc, exitcode;
-
-       // Ignore ^C, ^BREAK in parent
-       SetConsoleCtrlHandler(parent_console_handler, TRUE/*add*/);
-
-       // Create event used by child to signal daemon_detach()
-       if (!(dev = create_event(EVT_DETACHED, FALSE/*not signaled*/, TRUE, NULL/*must not exist*/))) {
-               CloseHandle(rev);
-               return 101;
-       }
-
-       // Restart process with same args
-       cmdline = GetCommandLineA();
-       memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-       
-       if (!CreateProcessA(
-               NULL, cmdline,
-               NULL, NULL, TRUE/*inherit*/,
-               0, NULL, NULL, &si, &pi)) {
-               fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
-               CloseHandle(rev); CloseHandle(dev);
-               return 101;
-       }
-       CloseHandle(pi.hThread);
-
-       // Wait for daemon_detach() or exit()
-       ht[0] = dev; ht[1] = pi.hProcess;
-       rc = WaitForMultipleObjects(2, ht, FALSE/*or*/, INFINITE);
-       if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+2)) {
-               fprintf(stderr, "WaitForMultipleObjects returns %lX\n", rc);
-               TerminateProcess(pi.hProcess, 200);
-       }
-       CloseHandle(rev); CloseHandle(dev);
-
-       // Get exit code
-       if (!GetExitCodeProcess(pi.hProcess, &exitcode))
-               exitcode = 201;
-       else if (exitcode == STILL_ACTIVE) // detach()ed, assume OK
-               exitcode = 0;
-
-       CloseHandle(pi.hProcess);
-       return exitcode;
+  HANDLE dev;
+  HANDLE ht[2];
+  char * cmdline;
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  DWORD rc, exitcode;
+
+  // Ignore ^C, ^BREAK in parent
+  SetConsoleCtrlHandler(parent_console_handler, TRUE/*add*/);
+
+  // Create event used by child to signal daemon_detach()
+  if (!(dev = create_event(EVT_DETACHED, FALSE/*not signaled*/, TRUE, NULL/*must not exist*/))) {
+    CloseHandle(rev);
+    return 101;
+  }
+
+  // Restart process with same args
+  cmdline = GetCommandLineA();
+  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+
+  if (!CreateProcessA(
+    NULL, cmdline,
+    NULL, NULL, TRUE/*inherit*/,
+    0, NULL, NULL, &si, &pi)) {
+    fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
+    CloseHandle(rev); CloseHandle(dev);
+    return 101;
+  }
+  CloseHandle(pi.hThread);
+
+  // Wait for daemon_detach() or exit()
+  ht[0] = dev; ht[1] = pi.hProcess;
+  rc = WaitForMultipleObjects(2, ht, FALSE/*or*/, INFINITE);
+  if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+2)) {
+    fprintf(stderr, "WaitForMultipleObjects returns %lX\n", rc);
+    TerminateProcess(pi.hProcess, 200);
+  }
+  CloseHandle(rev); CloseHandle(dev);
+
+  // Get exit code
+  if (!GetExitCodeProcess(pi.hProcess, &exitcode))
+    exitcode = 201;
+  else if (exitcode == STILL_ACTIVE) // detach()ed, assume OK
+    exitcode = 0;
+
+  CloseHandle(pi.hProcess);
+  return exitcode;
 }
 
 
@@ -248,77 +249,77 @@ static int reopen_stdin, reopen_stdout, reopen_stderr;
 
 static BOOL WINAPI child_console_handler(DWORD event)
 {
-       // Caution: runs in a new thread
-       // TODO: Guard with a mutex
-       HANDLE h = 0;
-       switch (event) {
-               case CTRL_C_EVENT: // <CONTROL-C> (SIGINT)
-                       h = sigint_handle; break;
-               case CTRL_BREAK_EVENT: // <CONTROL-Break> (SIGBREAK/SIGQUIT)
-               case CTRL_CLOSE_EVENT: // User closed console or abort via task manager
-                       h = sigbreak_handle; break;
-               case CTRL_LOGOFF_EVENT: // Logout/Shutdown (SIGTERM)
-               case CTRL_SHUTDOWN_EVENT:
-                       h = sigterm_handle; break;
-       }
-       if (!h)
-               return FALSE; // continue with next handler
-       // Signal event
-       if (!SetEvent(h))
-               return FALSE;
-       return TRUE;
+  // Caution: runs in a new thread
+  // TODO: Guard with a mutex
+  HANDLE h = 0;
+  switch (event) {
+    case CTRL_C_EVENT: // <CONTROL-C> (SIGINT)
+      h = sigint_handle; break;
+    case CTRL_BREAK_EVENT: // <CONTROL-Break> (SIGBREAK/SIGQUIT)
+    case CTRL_CLOSE_EVENT: // User closed console or abort via task manager
+      h = sigbreak_handle; break;
+    case CTRL_LOGOFF_EVENT: // Logout/Shutdown (SIGTERM)
+    case CTRL_SHUTDOWN_EVENT:
+      h = sigterm_handle; break;
+  }
+  if (!h)
+    return FALSE; // continue with next handler
+  // Signal event
+  if (!SetEvent(h))
+    return FALSE;
+  return TRUE;
 }
 
 
 static void child_exit(void)
 {
-       int i;
-       char * cmdline;
-       HANDLE rst;
-       STARTUPINFO si;
-       PROCESS_INFORMATION pi;
-
-       for (i = 0; i < num_sig_handlers; i++)
-               CloseHandle(sig_events[i]);
-       num_sig_handlers = 0;
-       CloseHandle(running_event); running_event = 0;
-
-       // Restart?
-       if (!(rst = open_event(EVT_RESTART)))
-               return; // No => normal exit
-
-       // Yes => Signal exit and restart process
-       Sleep(500);
-       SetEvent(rst);
-       CloseHandle(rst);
-       Sleep(500);
-
-       cmdline = GetCommandLineA();
-       memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-       si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE;
-
-       if (!CreateProcessA(
-               NULL, cmdline,
-               NULL, NULL, TRUE/*inherit*/,
-               0, NULL, NULL, &si, &pi)) {
-               fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
-       }
-       CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
+  int i;
+  char * cmdline;
+  HANDLE rst;
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+
+  for (i = 0; i < num_sig_handlers; i++)
+    CloseHandle(sig_events[i]);
+  num_sig_handlers = 0;
+  CloseHandle(running_event); running_event = 0;
+
+  // Restart?
+  if (!(rst = open_event(EVT_RESTART)))
+    return; // No => normal exit
+
+  // Yes => Signal exit and restart process
+  Sleep(500);
+  SetEvent(rst);
+  CloseHandle(rst);
+  Sleep(500);
+
+  cmdline = GetCommandLineA();
+  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+  si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE;
+
+  if (!CreateProcessA(
+    NULL, cmdline,
+    NULL, NULL, TRUE/*inherit*/,
+    0, NULL, NULL, &si, &pi)) {
+    fprintf(stderr, "CreateProcess(.,\"%s\",.) failed, Error=%ld\n", cmdline, GetLastError());
+  }
+  CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
 }
 
 static int child_main(HANDLE hev,int (*main_func)(int, char **), int argc, char **argv)
 {
-       // Keep EVT_RUNNING open until exit
-       running_event = hev;
+  // Keep EVT_RUNNING open until exit
+  running_event = hev;
 
-       // Install console handler
-       SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
+  // Install console handler
+  SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
 
-       // Install restart handler
-       atexit(child_exit);
+  // Install restart handler
+  atexit(child_exit);
 
-       // Continue in main_func() to do the real work
-       return main_func(argc, argv);
+  // Continue in main_func() to do the real work
+  return main_func(argc, argv);
 }
 
 
@@ -326,33 +327,33 @@ static int child_main(HANDLE hev,int (*main_func)(int, char **), int argc, char
 
 sigfunc_t daemon_signal(int sig, sigfunc_t func)
 {
-       int i;
-       HANDLE h;
-       if (func == SIG_DFL || func == SIG_IGN)
-               return func; // TODO
-       for (i = 0; i < num_sig_handlers; i++) {
-               if (sig_numbers[i] == sig) {
-                       sigfunc_t old = sig_handlers[i];
-                       sig_handlers[i] = func;
-                       return old;
-               }
-       }
-       if (num_sig_handlers >= MAX_SIG_HANDLERS)
-               return SIG_ERR;
-       if (!(h = create_event((!svc_mode ? sig : -1), FALSE, TRUE, NULL)))
-               return SIG_ERR;
-       sig_events[num_sig_handlers]   = h;
-       sig_numbers[num_sig_handlers]  = sig;
-       sig_handlers[num_sig_handlers] = func;
-       switch (sig) {
-               case SIGHUP:   sighup_handle   = h; break;
-               case SIGINT:   sigint_handle   = h; break;
-               case SIGTERM:  sigterm_handle  = h; break;
-               case SIGBREAK: sigbreak_handle = h; break;
-               case SIGUSR1:  sigusr1_handle  = h; break;
-       }
-       num_sig_handlers++;
-       return SIG_DFL;
+  int i;
+  HANDLE h;
+  if (func == SIG_DFL || func == SIG_IGN)
+    return func; // TODO
+  for (i = 0; i < num_sig_handlers; i++) {
+    if (sig_numbers[i] == sig) {
+      sigfunc_t old = sig_handlers[i];
+      sig_handlers[i] = func;
+      return old;
+    }
+  }
+  if (num_sig_handlers >= MAX_SIG_HANDLERS)
+    return SIG_ERR;
+  if (!(h = create_event((!svc_mode ? sig : -1), FALSE, TRUE, NULL)))
+    return SIG_ERR;
+  sig_events[num_sig_handlers]   = h;
+  sig_numbers[num_sig_handlers]  = sig;
+  sig_handlers[num_sig_handlers] = func;
+  switch (sig) {
+    case SIGHUP:   sighup_handle   = h; break;
+    case SIGINT:   sigint_handle   = h; break;
+    case SIGTERM:  sigterm_handle  = h; break;
+    case SIGBREAK: sigbreak_handle = h; break;
+    case SIGUSR1:  sigusr1_handle  = h; break;
+  }
+  num_sig_handlers++;
+  return SIG_DFL;
 }
 
 
@@ -360,15 +361,15 @@ sigfunc_t daemon_signal(int sig, sigfunc_t func)
 
 const char * daemon_strsignal(int sig)
 {
-       switch (sig) {
-               case SIGHUP:  return "SIGHUP";
-               case SIGINT:  return "SIGINT";
-               case SIGTERM: return "SIGTERM";
-               case SIGBREAK:return "SIGBREAK";
-               case SIGUSR1: return "SIGUSR1";
-               case SIGUSR2: return "SIGUSR2";
-               default:      return "*UNKNOWN*";
-       }
+  switch (sig) {
+    case SIGHUP:  return "SIGHUP";
+    case SIGINT:  return "SIGINT";
+    case SIGTERM: return "SIGTERM";
+    case SIGBREAK:return "SIGBREAK";
+    case SIGUSR1: return "SIGUSR1";
+    case SIGUSR2: return "SIGUSR2";
+    default:      return "*UNKNOWN*";
+  }
 }
 
 
@@ -376,26 +377,26 @@ const char * daemon_strsignal(int sig)
 
 void daemon_sleep(int seconds)
 {
-       do {
-               if (num_sig_handlers <= 0) {
-                       Sleep(seconds*1000L);
-               }
-               else {
-                       // Wait for any signal or timeout
-                       DWORD rc = WaitForMultipleObjects(num_sig_handlers, sig_events,
-                               FALSE/*OR*/, seconds*1000L);
-                       if (rc != WAIT_TIMEOUT) {
-                               if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+(unsigned)num_sig_handlers)) {
-                                       fprintf(stderr,"WaitForMultipleObjects returns %lu\n", rc);
-                                       Sleep(seconds*1000L);
-                                       return;
-                               }
-                               // Call Handler
-                               sig_handlers[rc-WAIT_OBJECT_0](sig_numbers[rc-WAIT_OBJECT_0]);
-                               break;
-                       }
-               }
-       } while (svc_paused);
+  do {
+    if (num_sig_handlers <= 0) {
+      Sleep(seconds*1000L);
+    }
+    else {
+      // Wait for any signal or timeout
+      DWORD rc = WaitForMultipleObjects(num_sig_handlers, sig_events,
+        FALSE/*OR*/, seconds*1000L);
+      if (rc != WAIT_TIMEOUT) {
+        if (!(/*WAIT_OBJECT_0(0) <= rc && */ rc < WAIT_OBJECT_0+(unsigned)num_sig_handlers)) {
+          fprintf(stderr,"WaitForMultipleObjects returns %lu\n", rc);
+          Sleep(seconds*1000L);
+          return;
+        }
+        // Call Handler
+        sig_handlers[rc-WAIT_OBJECT_0](sig_numbers[rc-WAIT_OBJECT_0]);
+        break;
+      }
+    }
+  } while (svc_paused);
 }
 
 
@@ -403,39 +404,39 @@ void daemon_sleep(int seconds)
 
 void daemon_disable_console()
 {
-       SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
-       reopen_stdin = reopen_stdout = reopen_stderr = 0;
-       if (isatty(fileno(stdin))) {
-               fclose(stdin); reopen_stdin = 1;
-       }
-       if (isatty(fileno(stdout))) {
-               fclose(stdout); reopen_stdout = 1;
-       }
-       if (isatty(fileno(stderr))) {
-               fclose(stderr); reopen_stderr = 1;
-       }
-       FreeConsole();
-       SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
+  SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
+  reopen_stdin = reopen_stdout = reopen_stderr = 0;
+  if (isatty(fileno(stdin))) {
+    fclose(stdin); reopen_stdin = 1;
+  }
+  if (isatty(fileno(stdout))) {
+    fclose(stdout); reopen_stdout = 1;
+  }
+  if (isatty(fileno(stderr))) {
+    fclose(stderr); reopen_stderr = 1;
+  }
+  FreeConsole();
+  SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
 }
 
 int daemon_enable_console(const char * title)
 {
-       BOOL ok;
-       SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
-       ok = AllocConsole();
-       SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
-       if (!ok)
-               return -1;
-       if (title)
-               SetConsoleTitleA(title);
-       if (reopen_stdin)
-               freopen("conin$",  "r", stdin);
-       if (reopen_stdout)
-               freopen("conout$", "w", stdout);
-       if (reopen_stderr)
-               freopen("conout$", "w", stderr);
-       reopen_stdin = reopen_stdout = reopen_stderr = 0;
-       return 0;
+  BOOL ok;
+  SetConsoleCtrlHandler(child_console_handler, FALSE/*remove*/);
+  ok = AllocConsole();
+  SetConsoleCtrlHandler(child_console_handler, TRUE/*add*/);
+  if (!ok)
+    return -1;
+  if (title)
+    SetConsoleTitleA(title);
+  if (reopen_stdin)
+    freopen("conin$",  "r", stdin);
+  if (reopen_stdout)
+    freopen("conout$", "w", stdout);
+  if (reopen_stderr)
+    freopen("conout$", "w", stderr);
+  reopen_stdin = reopen_stdout = reopen_stderr = 0;
+  return 0;
 }
 
 
@@ -443,101 +444,28 @@ int daemon_enable_console(const char * title)
 
 int daemon_detach(const char * ident)
 {
-       if (!svc_mode) {
-               if (ident) {
-                       // Print help
-                       FILE * f = ( isatty(fileno(stdout)) ? stdout
-                                          : isatty(fileno(stderr)) ? stderr : NULL);
-                       if (f)
-                               daemon_help(f, ident, "now detaches from console into background mode");
-               }
-               // Signal detach to parent
-               if (sig_event(EVT_DETACHED) != 1) {
-                       if (!debugging())
-                               return -1;
-               }
-               daemon_disable_console();
-       }
-       else {
-               // Signal end of initialization to service control manager
-               service_report_status(SERVICE_RUNNING, 0);
-               reopen_stdin = reopen_stdout = reopen_stderr = 1;
-       }
-
-       return 0;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////
-// MessageBox
-
-#ifndef _MT
-//MT runtime not necessary, because mbox_thread uses no unsafe lib functions
-//#error Program must be linked with multithreaded runtime library
-#endif
-
-static LONG mbox_count; // # mbox_thread()s
-static HANDLE mbox_mutex; // Show 1 box at a time (not necessary for service)
-
-typedef struct mbox_args_s {
-       HANDLE taken; const char * title, * text; int mode;
-} mbox_args;
-
-
-// Thread to display one message box
-
-static ULONG WINAPI mbox_thread(LPVOID arg)
-{
-       // Take args
-       mbox_args * mb = (mbox_args *)arg;
-       char title[100]; char text[1000]; int mode;
-       strncpy(title, mb->title, sizeof(title)-1); title[sizeof(title)-1] = 0;
-       strncpy(text , mb->text , sizeof(text )-1); text [sizeof(text )-1] = 0;
-       mode = mb->mode;
-       SetEvent(mb->taken);
-
-       // Show only one box at a time
-       WaitForSingleObject(mbox_mutex, INFINITE);
-       MessageBoxA(NULL, text, title, mode);
-       ReleaseMutex(mbox_mutex);
-
-       InterlockedDecrement(&mbox_count);
-       return 0;
-}
-
-
-// Display a message box
-int daemon_messagebox(int system, const char * title, const char * text)
-{
-       mbox_args mb;
-       HANDLE ht; DWORD tid;
-
-       // Create mutex during first call
-       if (!mbox_mutex)
-               mbox_mutex = CreateMutex(NULL/*!inherit*/, FALSE/*!owned*/, NULL/*unnamed*/);
-
-       // Allow at most 10 threads
-       if (InterlockedIncrement(&mbox_count) > 10) {
-               InterlockedDecrement(&mbox_count);
-               return -1;
-       }
-
-       // Create thread
-       mb.taken = CreateEvent(NULL/*!inherit*/, FALSE, FALSE/*!signaled*/, NULL/*unnamed*/);
-       mb.mode = MB_OK|MB_ICONWARNING
-                |(svc_mode?MB_SERVICE_NOTIFICATION:0)
-                |(system?MB_SYSTEMMODAL:MB_APPLMODAL);
-       mb.title = title;
-       mb.text = text;
-       if (!(ht = CreateThread(NULL, 0, mbox_thread, &mb, 0, &tid)))
-               return -1;
-
-       // Wait for args taken
-       if (WaitForSingleObject(mb.taken, 10000) != WAIT_OBJECT_0)
-               TerminateThread(ht, 0);
-       CloseHandle(mb.taken);
-       CloseHandle(ht);
-       return 0;
+  if (!svc_mode) {
+    if (ident) {
+      // Print help
+      FILE * f = ( isatty(fileno(stdout)) ? stdout
+             : isatty(fileno(stderr)) ? stderr : NULL);
+      if (f)
+        daemon_help(f, ident, "now detaches from console into background mode");
+    }
+    // Signal detach to parent
+    if (sig_event(EVT_DETACHED) != 1) {
+      if (!debugging())
+        return -1;
+    }
+    daemon_disable_console();
+  }
+  else {
+    // Signal end of initialization to service control manager
+    service_report_status(SERVICE_RUNNING, 0);
+    reopen_stdin = reopen_stdout = reopen_stderr = 1;
+  }
+
+  return 0;
 }
 
 
@@ -550,151 +478,108 @@ int daemon_spawn(const char * cmd,
                  const char * inpbuf, int inpsize,
                  char *       outbuf, int outsize )
 {
-       HANDLE pipe_inp_r, pipe_inp_w, pipe_out_r, pipe_out_w, pipe_err_w, h;
-       char temp_path[MAX_PATH];
-       DWORD flags, num_io, exitcode;
-       int use_file, state, i;
-       SECURITY_ATTRIBUTES sa;
-       STARTUPINFO si; PROCESS_INFORMATION pi;
-       HANDLE self = GetCurrentProcess();
-
-       if (GetVersion() & 0x80000000L) {
-               // Win9x/ME: A calling process never receives EOF if output of COMMAND.COM or
-               // any other DOS program is redirected via a pipe. Using a temp file instead.
-               use_file = 1; flags = DETACHED_PROCESS;
-       }
-       else {
-               // NT4/2000/XP: If DETACHED_PROCESS is used, CMD.EXE opens a new console window
-               // for each external command in a redirected .BAT file.
-               // Even (DETACHED_PROCESS|CREATE_NO_WINDOW) does not work.
-               use_file = 0; flags = CREATE_NO_WINDOW;
-       }
-
-       // Create stdin pipe with inheritable read side
-       memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
-       sa.bInheritHandle = TRUE;
-       if (!CreatePipe(&pipe_inp_r, &h, &sa/*inherit*/, inpsize*2+13))
-               return -1;
-       if (!DuplicateHandle(self, h, self, &pipe_inp_w,
-               0, FALSE/*!inherit*/, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
-               CloseHandle(pipe_inp_r);
-               return -1;
-       }
-
-       memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
-       sa.bInheritHandle = TRUE;
-       if (!use_file) {
-               // Create stdout pipe with inheritable write side
-               if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) {
-                       CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-       }
-       else {
-               // Create temp file with inheritable write handle
-               char temp_dir[MAX_PATH];
-               if (!GetTempPathA(sizeof(temp_dir), temp_dir))
-                       strcpy(temp_dir, ".");
-               if (!GetTempFileNameA(temp_dir, "out"/*prefix*/, 0/*create unique*/, temp_path)) {
-                       CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-               if ((h = CreateFileA(temp_path, GENERIC_READ|GENERIC_WRITE,
-                       0/*no sharing*/, &sa/*inherit*/, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) {
-                       CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-               if (!DuplicateHandle(self, h, self, &pipe_out_w,
-                       GENERIC_WRITE, TRUE/*inherit*/, 0)) {
-                       CloseHandle(h); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-                       return -1;
-               }
-       }
-
-       if (!DuplicateHandle(self, h, self, &pipe_out_r,
-               GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
-               CloseHandle(pipe_out_w); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-               return -1;
-       }
-
-       // Create stderr handle as dup of stdout write side
-       if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
-               0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
-               CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-               CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-               return -1;
-       }
-
-       // Create process with pipes/file as stdio
-       memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
-       si.hStdInput  = pipe_inp_r;
-       si.hStdOutput = pipe_out_w;
-       si.hStdError  = pipe_err_w;
-       si.dwFlags = STARTF_USESTDHANDLES;
-       if (!CreateProcessA(
-               NULL, (char*)cmd,
-               NULL, NULL, TRUE/*inherit*/,
-               flags/*DETACHED_PROCESS or CREATE_NO_WINDOW*/,
-               NULL, NULL, &si, &pi)) {
-               CloseHandle(pipe_err_w);
-               CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
-               CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
-               return -1;
-       }
-       CloseHandle(pi.hThread);
-       // Close inherited handles
-       CloseHandle(pipe_inp_r);
-       CloseHandle(pipe_out_w);
-       CloseHandle(pipe_err_w);
-
-       // Copy inpbuf to stdin
-       // convert \n => \r\n 
-       for (i = 0; i < inpsize; ) {
-               int len = 0;
-               while (i+len < inpsize && inpbuf[i+len] != '\n')
-                       len++;
-               if (len > 0)
-                       WriteFile(pipe_inp_w, inpbuf+i, len, &num_io, NULL);
-               i += len;
-               if (i < inpsize) {
-                       WriteFile(pipe_inp_w, "\r\n", 2, &num_io, NULL);
-                       i++;
-               }
-       }
-       CloseHandle(pipe_inp_w);
-
-       exitcode = 42;
-       for (state = 0; state < 2; state++) {
-               // stdout pipe: read pipe first
-               // stdout file: wait for process first
-               if (state == use_file) {
-                       // Copy stdout to output buffer until full, rest to /dev/null
-                       // convert \r\n => \n
-                       if (use_file)
-                               SetFilePointer(pipe_out_r, 0, NULL, FILE_BEGIN);
-                       for (i = 0; ; ) {
-                               char buf[256];
-                               int j;
-                               if (!ReadFile(pipe_out_r, buf, sizeof(buf), &num_io, NULL) || num_io == 0)
-                                       break;
-                               for (j = 0; i < outsize-1 && j < (int)num_io; j++) {
-                                       if (buf[j] != '\r')
-                                               outbuf[i++] = buf[j];
-                               }
-                       }
-                       outbuf[i] = 0;
-                       CloseHandle(pipe_out_r);
-                       if (use_file)
-                               DeleteFileA(temp_path);
-               }
-               else {
-                       // Wait for process exitcode
-                       WaitForSingleObject(pi.hProcess, INFINITE);
-                       GetExitCodeProcess(pi.hProcess, &exitcode);
-                       CloseHandle(pi.hProcess);
-               }
-       }
-       return exitcode;
+  HANDLE self = GetCurrentProcess();
+
+  // Create stdin pipe with inheritable read side
+  SECURITY_ATTRIBUTES sa;
+  memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
+  sa.bInheritHandle = TRUE;
+  HANDLE pipe_inp_r, pipe_inp_w, h;
+  if (!CreatePipe(&pipe_inp_r, &h, &sa/*inherit*/, inpsize*2+13))
+    return -1;
+  if (!DuplicateHandle(self, h, self, &pipe_inp_w,
+    0, FALSE/*!inherit*/, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
+    CloseHandle(pipe_inp_r);
+    return -1;
+  }
+
+  // Create stdout pipe with inheritable write side
+  memset(&sa, 0, sizeof(sa)); sa.nLength = sizeof(sa);
+  sa.bInheritHandle = TRUE;
+  HANDLE pipe_out_w;
+  if (!CreatePipe(&h, &pipe_out_w, &sa/*inherit*/, outsize)) {
+    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+
+  HANDLE pipe_out_r;
+  if (!DuplicateHandle(self, h, self, &pipe_out_r,
+    GENERIC_READ, FALSE/*!inherit*/, DUPLICATE_CLOSE_SOURCE)) {
+    CloseHandle(pipe_out_w); CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+
+  // Create stderr handle as dup of stdout write side
+  HANDLE pipe_err_w;
+  if (!DuplicateHandle(self, pipe_out_w, self, &pipe_err_w,
+    0, TRUE/*inherit*/, DUPLICATE_SAME_ACCESS)) {
+    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
+    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+
+  // Create process with pipes as stdio
+  STARTUPINFO si;
+  memset(&si, 0, sizeof(si)); si.cb = sizeof(si);
+  si.hStdInput  = pipe_inp_r;
+  si.hStdOutput = pipe_out_w;
+  si.hStdError  = pipe_err_w;
+  si.dwFlags = STARTF_USESTDHANDLES;
+  PROCESS_INFORMATION pi;
+  if (!CreateProcessA(
+    NULL, (char*)cmd,
+    NULL, NULL, TRUE/*inherit*/,
+    CREATE_NO_WINDOW, // DETACHED_PROCESS does not work
+    NULL, NULL, &si, &pi)) {
+    CloseHandle(pipe_err_w);
+    CloseHandle(pipe_out_r); CloseHandle(pipe_out_w);
+    CloseHandle(pipe_inp_r); CloseHandle(pipe_inp_w);
+    return -1;
+  }
+  CloseHandle(pi.hThread);
+  // Close inherited handles
+  CloseHandle(pipe_inp_r);
+  CloseHandle(pipe_out_w);
+  CloseHandle(pipe_err_w);
+
+  // Copy inpbuf to stdin
+  // convert \n => \r\n
+  DWORD num_io;
+  int i;
+  for (i = 0; i < inpsize; ) {
+    int len = 0;
+    while (i+len < inpsize && inpbuf[i+len] != '\n')
+      len++;
+    if (len > 0)
+      WriteFile(pipe_inp_w, inpbuf+i, len, &num_io, NULL);
+    i += len;
+    if (i < inpsize) {
+      WriteFile(pipe_inp_w, "\r\n", 2, &num_io, NULL);
+      i++;
+    }
+  }
+  CloseHandle(pipe_inp_w);
+
+  // Copy stdout to output buffer until full, rest to /dev/null
+  // convert \r\n => \n
+  for (i = 0; ; ) {
+    char buf[256];
+    if (!ReadFile(pipe_out_r, buf, sizeof(buf), &num_io, NULL) || num_io == 0)
+      break;
+    for (int j = 0; i < outsize-1 && j < (int)num_io; j++) {
+      if (buf[j] != '\r')
+        outbuf[i++] = buf[j];
+    }
+  }
+  outbuf[i] = 0;
+  CloseHandle(pipe_out_r);
+
+  // Wait for process exitcode
+  DWORD exitcode = 42;
+  WaitForSingleObject(pi.hProcess, INFINITE);
+  GetExitCodeProcess(pi.hProcess, &exitcode);
+  CloseHandle(pi.hProcess);
+  return exitcode;
 }
 
 
@@ -703,128 +588,128 @@ int daemon_spawn(const char * cmd,
 
 static int wait_signaled(HANDLE h, int seconds)
 {
-       int i;
-       for (i = 0; ; ) {
-               if (WaitForSingleObject(h, 1000L) == WAIT_OBJECT_0)
-                       return 0;
-               if (++i >= seconds)
-                       return -1;
-               fputchar('.'); fflush(stdout);
-       }
+  int i;
+  for (i = 0; ; ) {
+    if (WaitForSingleObject(h, 1000L) == WAIT_OBJECT_0)
+      return 0;
+    if (++i >= seconds)
+      return -1;
+    fputchar('.'); fflush(stdout);
+  }
 }
 
 
 static int wait_evt_running(int seconds, int exists)
 {
-       int i;
-       if (event_exists(EVT_RUNNING) == exists)
-               return 0;
-       for (i = 0; ; ) {
-               Sleep(1000);
-               if (event_exists(EVT_RUNNING) == exists)
-                       return 0;
-               if (++i >= seconds)
-                       return -1;
-               fputchar('.'); fflush(stdout);
-       }
+  int i;
+  if (event_exists(EVT_RUNNING) == exists)
+    return 0;
+  for (i = 0; ; ) {
+    Sleep(1000);
+    if (event_exists(EVT_RUNNING) == exists)
+      return 0;
+    if (++i >= seconds)
+      return -1;
+    fputchar('.'); fflush(stdout);
+  }
 }
 
 
 static int is_initd_command(char * s)
 {
-       if (!strcmp(s, "status"))
-               return EVT_RUNNING;
-       if (!strcmp(s, "stop"))
-               return SIGTERM;
-       if (!strcmp(s, "reload"))
-               return SIGHUP;
-       if (!strcmp(s, "sigusr1"))
-               return SIGUSR1;
-       if (!strcmp(s, "sigusr2"))
-               return SIGUSR2;
-       if (!strcmp(s, "restart"))
-               return EVT_RESTART;
-       return -1;
+  if (!strcmp(s, "status"))
+    return EVT_RUNNING;
+  if (!strcmp(s, "stop"))
+    return SIGTERM;
+  if (!strcmp(s, "reload"))
+    return SIGHUP;
+  if (!strcmp(s, "sigusr1"))
+    return SIGUSR1;
+  if (!strcmp(s, "sigusr2"))
+    return SIGUSR2;
+  if (!strcmp(s, "restart"))
+    return EVT_RESTART;
+  return -1;
 }
 
 
 static int initd_main(const char * ident, int argc, char **argv)
 {
-       int rc;
-       if (argc < 2)
-               return -1;
-       if ((rc = is_initd_command(argv[1])) < 0)
-               return -1;
-       if (argc != 2) {
-               printf("%s: no arguments allowed for command %s\n", ident, argv[1]);
-               return 1;
-       }
-
-       switch (rc) {
-               default:
-               case EVT_RUNNING:
-                       printf("Checking for %s:", ident); fflush(stdout);
-                       rc = event_exists(EVT_RUNNING);
-                       puts(rc ? " running" : " not running");
-                       return (rc ? 0 : 1);
-
-               case SIGTERM:
-                       printf("Stopping %s:", ident); fflush(stdout);
-                       rc = sig_event(SIGTERM);
-                       if (rc <= 0) {
-                               puts(rc < 0 ? " not running" : " error");
-                               return (rc < 0 ? 0 : 1);
-                       }
-                       rc = wait_evt_running(10, 0);
-                       puts(!rc ? " done" : " timeout");
-                       return (!rc ? 0 : 1);
-
-               case SIGHUP:
-                       printf("Reloading %s:", ident); fflush(stdout);
-                       rc = sig_event(SIGHUP);
-                       puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
-                       return (rc > 0 ? 0 : 1);
-
-               case SIGUSR1:
-               case SIGUSR2:
-                       printf("Sending SIGUSR%d to %s:", (rc-SIGUSR1+1), ident); fflush(stdout);
-                       rc = sig_event(rc);
-                       puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
-                       return (rc > 0 ? 0 : 1);
-
-               case EVT_RESTART:
-                       {
-                               HANDLE rst;
-                               printf("Stopping %s:", ident); fflush(stdout);
-                               if (event_exists(EVT_DETACHED)) {
-                                       puts(" not detached, cannot restart");
-                                       return 1;
-                               }
-                               if (!(rst = create_event(EVT_RESTART, FALSE, FALSE, NULL))) {
-                                       puts(" error");
-                                       return 1;
-                               }
-                               rc = sig_event(SIGTERM);
-                               if (rc <= 0) {
-                                       puts(rc < 0 ? " not running" : " error");
-                                       CloseHandle(rst);
-                                       return 1;
-                               }
-                               rc = wait_signaled(rst, 10);
-                               CloseHandle(rst);
-                               if (rc) {
-                                       puts(" timeout");
-                                       return 1;
-                               }
-                               puts(" done");
-                               Sleep(100);
-
-                               printf("Starting %s:", ident); fflush(stdout);
-                               rc = wait_evt_running(10, 1);
-                               puts(!rc ? " done" : " error");
-                               return (!rc ? 0 : 1);
-                       }
-       }
+  int rc;
+  if (argc < 2)
+    return -1;
+  if ((rc = is_initd_command(argv[1])) < 0)
+    return -1;
+  if (argc != 2) {
+    printf("%s: no arguments allowed for command %s\n", ident, argv[1]);
+    return 1;
+  }
+
+  switch (rc) {
+    default:
+    case EVT_RUNNING:
+      printf("Checking for %s:", ident); fflush(stdout);
+      rc = event_exists(EVT_RUNNING);
+      puts(rc ? " running" : " not running");
+      return (rc ? 0 : 1);
+
+    case SIGTERM:
+      printf("Stopping %s:", ident); fflush(stdout);
+      rc = sig_event(SIGTERM);
+      if (rc <= 0) {
+        puts(rc < 0 ? " not running" : " error");
+        return (rc < 0 ? 0 : 1);
+      }
+      rc = wait_evt_running(10, 0);
+      puts(!rc ? " done" : " timeout");
+      return (!rc ? 0 : 1);
+
+    case SIGHUP:
+      printf("Reloading %s:", ident); fflush(stdout);
+      rc = sig_event(SIGHUP);
+      puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
+      return (rc > 0 ? 0 : 1);
+
+    case SIGUSR1:
+    case SIGUSR2:
+      printf("Sending SIGUSR%d to %s:", (rc-SIGUSR1+1), ident); fflush(stdout);
+      rc = sig_event(rc);
+      puts(rc > 0 ? " done" : rc == 0 ? " error" : " not running");
+      return (rc > 0 ? 0 : 1);
+
+    case EVT_RESTART:
+      {
+        HANDLE rst;
+        printf("Stopping %s:", ident); fflush(stdout);
+        if (event_exists(EVT_DETACHED)) {
+          puts(" not detached, cannot restart");
+          return 1;
+        }
+        if (!(rst = create_event(EVT_RESTART, FALSE, FALSE, NULL))) {
+          puts(" error");
+          return 1;
+        }
+        rc = sig_event(SIGTERM);
+        if (rc <= 0) {
+          puts(rc < 0 ? " not running" : " error");
+          CloseHandle(rst);
+          return 1;
+        }
+        rc = wait_signaled(rst, 10);
+        CloseHandle(rst);
+        if (rc) {
+          puts(" timeout");
+          return 1;
+        }
+        puts(" done");
+        Sleep(100);
+
+        printf("Starting %s:", ident); fflush(stdout);
+        rc = wait_evt_running(10, 1);
+        puts(!rc ? " done" : " error");
+        return (!rc ? 0 : 1);
+      }
+  }
 }
 
 
@@ -841,38 +726,30 @@ static SERVICE_STATUS svc_status;
 
 static void service_report_status(int state, int seconds)
 {
-       // TODO: Avoid race
-       static DWORD checkpoint = 1;
-       static DWORD accept_more = SERVICE_ACCEPT_PARAMCHANGE; // Win2000/XP
-       svc_status.dwCurrentState = state;
-       svc_status.dwWaitHint = seconds*1000;
-       switch (state) {
-               default:
-                       svc_status.dwCheckPoint = checkpoint++;
-                       break;
-               case SERVICE_RUNNING:
-               case SERVICE_STOPPED:
-                       svc_status.dwCheckPoint = 0;
-       }
-       switch (state) {
-               case SERVICE_START_PENDING:
-               case SERVICE_STOP_PENDING:
-                       svc_status.dwControlsAccepted = 0;
-                       break;
-               default:
-                       svc_status.dwControlsAccepted =
-                               SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|
-                               SERVICE_ACCEPT_PAUSE_CONTINUE|accept_more;
-                       break;
-       }
-       if (!SetServiceStatus(svc_handle, &svc_status)) {
-               if (svc_status.dwControlsAccepted & accept_more) {
-                       // Retry without SERVICE_ACCEPT_PARAMCHANGE (WinNT4)
-                       svc_status.dwControlsAccepted &= ~accept_more;
-                       accept_more = 0;
-                       SetServiceStatus(svc_handle, &svc_status);
-               }
-       }
+  // TODO: Avoid race
+  static DWORD checkpoint = 1;
+  svc_status.dwCurrentState = state;
+  svc_status.dwWaitHint = seconds*1000;
+  switch (state) {
+    default:
+      svc_status.dwCheckPoint = checkpoint++;
+      break;
+    case SERVICE_RUNNING:
+    case SERVICE_STOPPED:
+      svc_status.dwCheckPoint = 0;
+  }
+  switch (state) {
+    case SERVICE_START_PENDING:
+    case SERVICE_STOP_PENDING:
+      svc_status.dwControlsAccepted = 0;
+      break;
+    default:
+      svc_status.dwControlsAccepted =
+        SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|
+        SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_PARAMCHANGE;
+      break;
+  }
+  SetServiceStatus(svc_handle, &svc_status);
 }
 
 
@@ -880,35 +757,35 @@ static void service_report_status(int state, int seconds)
 
 static void WINAPI service_control(DWORD ctrlcode)
 {
-       switch (ctrlcode) {
-               case SERVICE_CONTROL_STOP:
-               case SERVICE_CONTROL_SHUTDOWN:
-                       service_report_status(SERVICE_STOP_PENDING, 30);
-                       svc_paused = 0;
-                       SetEvent(sigterm_handle);
-                       break;
-               case SERVICE_CONTROL_PARAMCHANGE: // Win2000/XP
-                       service_report_status(svc_status.dwCurrentState, 0);
-                       svc_paused = 0;
-                       SetEvent(sighup_handle); // reload
-                       break;
-               case SERVICE_CONTROL_PAUSE:
-                       service_report_status(SERVICE_PAUSED, 0);
-                       svc_paused = 1;
-                       break;
-               case SERVICE_CONTROL_CONTINUE:
-                       service_report_status(SERVICE_RUNNING, 0);
-                       {
-                               int was_paused = svc_paused;
-                               svc_paused = 0;
-                               SetEvent(was_paused ? sighup_handle : sigusr1_handle); // reload:recheck
-                       }
-                       break;
-               case SERVICE_CONTROL_INTERROGATE:
-               default: // unknown
-                       service_report_status(svc_status.dwCurrentState, 0);
-                       break;
-       }
+  switch (ctrlcode) {
+    case SERVICE_CONTROL_STOP:
+    case SERVICE_CONTROL_SHUTDOWN:
+      service_report_status(SERVICE_STOP_PENDING, 30);
+      svc_paused = 0;
+      SetEvent(sigterm_handle);
+      break;
+    case SERVICE_CONTROL_PARAMCHANGE: // Win2000/XP
+      service_report_status(svc_status.dwCurrentState, 0);
+      svc_paused = 0;
+      SetEvent(sighup_handle); // reload
+      break;
+    case SERVICE_CONTROL_PAUSE:
+      service_report_status(SERVICE_PAUSED, 0);
+      svc_paused = 1;
+      break;
+    case SERVICE_CONTROL_CONTINUE:
+      service_report_status(SERVICE_RUNNING, 0);
+      {
+        int was_paused = svc_paused;
+        svc_paused = 0;
+        SetEvent(was_paused ? sighup_handle : sigusr1_handle); // reload:recheck
+      }
+      break;
+    case SERVICE_CONTROL_INTERROGATE:
+    default: // unknown
+      service_report_status(svc_status.dwCurrentState, 0);
+      break;
+  }
 }
 
 
@@ -916,19 +793,19 @@ static void WINAPI service_control(DWORD ctrlcode)
 
 static void service_exit(void)
 {
-       // Close signal events
-       int i;
-       for (i = 0; i < num_sig_handlers; i++)
-               CloseHandle(sig_events[i]);
-       num_sig_handlers = 0;
-
-       // Set exitcode
-       if (daemon_winsvc_exitcode) {
-               svc_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
-               svc_status.dwServiceSpecificExitCode = daemon_winsvc_exitcode;
-       }
-       // Report stopped
-       service_report_status(SERVICE_STOPPED, 0);
+  // Close signal events
+  int i;
+  for (i = 0; i < num_sig_handlers; i++)
+    CloseHandle(sig_events[i]);
+  num_sig_handlers = 0;
+
+  // Set exitcode
+  if (daemon_winsvc_exitcode) {
+    svc_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
+    svc_status.dwServiceSpecificExitCode = daemon_winsvc_exitcode;
+  }
+  // Report stopped
+  service_report_status(SERVICE_STOPPED, 0);
 }
 
 
@@ -939,54 +816,106 @@ static char ** svc_main_argv;
 
 // Main function for service, called by service dispatcher
 
-static void WINAPI service_main(DWORD argc, LPSTR * argv)
+static void WINAPI service_main(DWORD /*argc*/, LPSTR * argv)
 {
-       char path[MAX_PATH], *p;
-       ARGUSED(argc);
+  char path[MAX_PATH], *p;
+
+  // Register control handler
+  svc_handle = RegisterServiceCtrlHandler(argv[0], service_control);
 
-       // Register control handler
-       svc_handle = RegisterServiceCtrlHandler(argv[0], service_control);
+  // Init service status
+  svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+  service_report_status(SERVICE_START_PENDING, 10);
 
-       // Init service status
-       svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS;
-       service_report_status(SERVICE_START_PENDING, 10);
+  // Service started in \windows\system32, change to .exe directory
+  if (GetModuleFileNameA(NULL, path, sizeof(path)) && (p = strrchr(path, '\\'))) {
+    *p = 0; SetCurrentDirectoryA(path);
+  }
 
-       // Service started in \windows\system32, change to .exe directory
-       if (GetModuleFileNameA(NULL, path, sizeof(path)) && (p = strrchr(path, '\\'))) {
-               *p = 0; SetCurrentDirectoryA(path);
-       }
-       
-       // Install exit handler
-       atexit(service_exit);
+  // Install exit handler
+  atexit(service_exit);
 
-       // Do the real work, service status later updated by daemon_detach()
-       daemon_winsvc_exitcode = svc_main_func(svc_main_argc, svc_main_argv);
+  // Do the real work, service status later updated by daemon_detach()
+  daemon_winsvc_exitcode = svc_main_func(svc_main_argc, svc_main_argv);
 
-       exit(daemon_winsvc_exitcode);
-       // ... continued in service_exit()
+  exit(daemon_winsvc_exitcode);
+  // ... continued in service_exit()
 }
 
 
 /////////////////////////////////////////////////////////////////////////////
 // Windows Service Admin Functions
 
-// Set Service description (Win2000/XP)
 
-static int svcadm_setdesc(SC_HANDLE hs, const char * desc)
+// Make registry key name for event message file
+static bool make_evtkey(char * buf, unsigned size, const char * ident)
+{
+  static const char prefix[] = "SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\";
+  const unsigned pfxlen = sizeof(prefix)-1;
+  unsigned idlen = strlen(ident);
+  if (pfxlen + idlen >= size) {
+    printf(" Buffer overflow\n");
+    return false;
+  }
+  memcpy(buf, prefix, pfxlen);
+  memcpy(buf+pfxlen, ident, idlen+1);
+  return true;
+}
+
+// Install this exe as event message file
+static void inst_evtmsg(const char * ident)
+{
+  printf("Installing event message file for %s:", ident); fflush(stdout);
+
+  char mypath[MAX_PATH];
+  if (!GetModuleFileNameA((HMODULE)0, mypath, sizeof(mypath))) {
+    printf(" unknown program path, Error=%ld\n", GetLastError());
+    return;
+  }
+
+  char subkey[MAX_PATH];
+  if (!make_evtkey(subkey, sizeof(subkey), ident))
+    return;
+
+  HKEY hk;
+  LONG err = RegCreateKeyExA(HKEY_LOCAL_MACHINE, subkey, 0, (char *)0, 0, KEY_ALL_ACCESS,
+                             (SECURITY_ATTRIBUTES *)0, &hk, (DWORD *)0);
+  if (err != ERROR_SUCCESS) {
+    printf(" RegCreateKeyEx failed, error=%ld\n", err);
+    return;
+  }
+
+  err = RegSetValueExA(hk, "EventMessageFile", 0, REG_SZ,
+                       (const BYTE *)mypath, strlen(mypath)+1);
+  if (err == ERROR_SUCCESS) {
+    DWORD val = EVENTLOG_INFORMATION_TYPE
+               |EVENTLOG_WARNING_TYPE
+               |EVENTLOG_ERROR_TYPE;
+    err = RegSetValueExA(hk, "TypesSupported", 0, REG_DWORD,
+                         (const BYTE *)&val, sizeof(val));
+  }
+  if (err != ERROR_SUCCESS)
+    printf(" RegSetValueEx failed, error=%ld\n", err);
+
+  RegCloseKey(hk);
+  puts(" done");
+}
+
+// Uninstall event message file
+static void uninst_evtmsg(const char * ident)
 {
-       HINSTANCE hdll;
-       BOOL (WINAPI * ChangeServiceConfig2A_p)(SC_HANDLE, DWORD, LPVOID);
-       BOOL ret;
-       if (!(hdll = LoadLibraryA("ADVAPI32.DLL")))
-               return FALSE;
-       if (!((ChangeServiceConfig2A_p = (BOOL (WINAPI *)(SC_HANDLE, DWORD, LPVOID))GetProcAddress(hdll, "ChangeServiceConfig2A"))))
-               ret = FALSE;
-       else {
-               SERVICE_DESCRIPTIONA sd = { (char *)desc };
-               ret = ChangeServiceConfig2A_p(hs, SERVICE_CONFIG_DESCRIPTION, &sd);
-       }
-       FreeLibrary(hdll);
-       return ret;
+  printf("Removing event message file for %s:", ident); fflush(stdout);
+
+  char subkey[MAX_PATH];
+  if (!make_evtkey(subkey, sizeof(subkey), ident))
+    return;
+
+  LONG err = RegDeleteKeyA(HKEY_LOCAL_MACHINE, subkey);
+  if (err != ERROR_SUCCESS && err != ERROR_FILE_NOT_FOUND) {
+    printf(" RegDeleteKey failed, error=%ld\n", err);
+    return;
+  }
+  puts(" done");
 }
 
 
@@ -995,111 +924,128 @@ static int svcadm_setdesc(SC_HANDLE hs, const char * desc)
 static int svcadm_main(const char * ident, const daemon_winsvc_options * svc_opts,
                        int argc, char **argv                                      )
 {
-       int remove; long err;
-       SC_HANDLE hm, hs;
-
-       if (argc < 2)
-               return -1;
-       if (!strcmp(argv[1], "install"))
-               remove = 0;
-       else if (!strcmp(argv[1], "remove")) {
-               if (argc != 2) {
-                       printf("%s: no arguments allowed for command remove\n", ident);
-                       return 1;
-               }
-               remove = 1;
-       }
-       else
-               return -1;
-
-       printf("%s service %s:", (!remove?"Installing":"Removing"), ident); fflush(stdout);
-
-       // Open SCM
-       if (!(hm = OpenSCManager(NULL/*local*/, NULL/*default*/, SC_MANAGER_ALL_ACCESS))) {
-               if ((err = GetLastError()) == ERROR_ACCESS_DENIED)
-                       puts(" access to SCManager denied");
-               else if (err == ERROR_CALL_NOT_IMPLEMENTED)
-                       puts(" services not implemented on this version of Windows");
-               else
-                       printf(" cannot open SCManager, Error=%ld\n", err);
-               return 1;
-       }
-
-       if (!remove) {
-               char path[MAX_PATH+100];
-               int i;
-               // Get program path
-               if (!GetModuleFileNameA(NULL, path, MAX_PATH)) {
-                       printf(" unknown program path, Error=%ld\n", GetLastError());
-                       CloseServiceHandle(hm);
-                       return 1;
-               }
-               // Add quotes if necessary
-               if (strchr(path, ' ')) {
-                       i = strlen(path);
-                       path[i+1] = '"'; path[i+2] = 0;
-                       while (--i >= 0)
-                               path[i+1] = path[i];
-                       path[0] = '"';
-               }
-               // Append options
-               strcat(path, " "); strcat(path, svc_opts->cmd_opt);
-               for (i = 2; i < argc; i++) {
-                       const char * s = argv[i];
-                       if (strlen(path)+1+1+strlen(s)+1 >= sizeof(path))
-                               break;
-                       // Add quotes if necessary
-                       if (strchr(s, ' ') && !strchr(s, '"')) {
-                               strcat(path, " \""); strcat(path, s); strcat(path, "\"");
-                       }
-                       else {
-                               strcat(path, " "); strcat(path, s);
-                       }
-               }
-               // Create
-               if (!(hs = CreateService(hm,
-                       svc_opts->svcname, svc_opts->dispname,
-                       SERVICE_ALL_ACCESS,
-                       SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
-                       SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
-                       NULL/*no load ordering*/, NULL/*no tag id*/,
-                       ""/*no depedencies*/, NULL/*local system account*/, NULL/*no pw*/))) {
-                       if ((err = GetLastError()) == ERROR_SERVICE_EXISTS)
-                               puts(" the service is already installed");
-                       else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
-                               puts(" service is still running and marked for deletion\n"
-                                    "Stop the service and retry install");
-                       else
-                               printf(" failed, Error=%ld\n", err);
-                       CloseServiceHandle(hm);
-                       return 1;
-               }
-               // Set optional description
-               if (svc_opts->descript)
-                       svcadm_setdesc(hs, svc_opts->descript);
-       }
-       else {
-               // Open
-               if (!(hs = OpenService(hm, svc_opts->svcname, SERVICE_ALL_ACCESS))) {
-                       puts(" not found");
-                       CloseServiceHandle(hm);
-                       return 1;
-               }
-               // TODO: Stop service if running
-               // Remove
-               if (!DeleteService(hs)) {
-                       if ((err = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE)
-                               puts(" service is still running and marked for deletion\n"
-                                    "Stop the service to remove it");
-                       else
-                               printf(" failed, Error=%ld\n", err);
-                       CloseServiceHandle(hs); CloseServiceHandle(hm);
-                       return 1;
-               }
-       }
-       puts(" done");
-       CloseServiceHandle(hs); CloseServiceHandle(hm);
-       return 0;
+  int remove; long err;
+  SC_HANDLE hm, hs;
+
+  if (argc < 2)
+    return -1;
+  if (!strcmp(argv[1], "install"))
+    remove = 0;
+  else if (!strcmp(argv[1], "remove")) {
+    if (argc != 2) {
+      printf("%s: no arguments allowed for command remove\n", ident);
+      return 1;
+    }
+    remove = 1;
+  }
+  else
+    return -1;
+
+  printf("%s service %s:", (!remove?"Installing":"Removing"), ident); fflush(stdout);
+
+  // Open SCM
+  if (!(hm = OpenSCManager(NULL/*local*/, NULL/*default*/, SC_MANAGER_ALL_ACCESS))) {
+    if ((err = GetLastError()) == ERROR_ACCESS_DENIED)
+      puts(" access to SCManager denied");
+    else
+      printf(" cannot open SCManager, Error=%ld\n", err);
+    return 1;
+  }
+
+  if (!remove) {
+    char path[MAX_PATH+100];
+    int i;
+    // Get program path
+    if (!GetModuleFileNameA(NULL, path, MAX_PATH)) {
+      printf(" unknown program path, Error=%ld\n", GetLastError());
+      CloseServiceHandle(hm);
+      return 1;
+    }
+    // Add quotes if necessary
+    if (strchr(path, ' ')) {
+      i = strlen(path);
+      path[i+1] = '"'; path[i+2] = 0;
+      while (--i >= 0)
+        path[i+1] = path[i];
+      path[0] = '"';
+    }
+    // Append options
+    strcat(path, " "); strcat(path, svc_opts->cmd_opt);
+    for (i = 2; i < argc; i++) {
+      const char * s = argv[i];
+      if (strlen(path)+1+1+strlen(s)+1 >= sizeof(path))
+        break;
+      // Add quotes if necessary
+      if (strchr(s, ' ') && !strchr(s, '"')) {
+        strcat(path, " \""); strcat(path, s); strcat(path, "\"");
+      }
+      else {
+        strcat(path, " "); strcat(path, s);
+      }
+    }
+    // Create
+    if (!(hs = CreateService(hm,
+      svc_opts->svcname, svc_opts->dispname,
+      SERVICE_ALL_ACCESS,
+      SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS,
+      SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, path,
+      NULL/*no load ordering*/, NULL/*no tag id*/,
+      ""/*no depedencies*/, NULL/*local system account*/, NULL/*no pw*/))) {
+      if ((err = GetLastError()) == ERROR_SERVICE_EXISTS)
+        puts(" the service is already installed");
+      else if (err == ERROR_SERVICE_MARKED_FOR_DELETE)
+        puts(" service is still running and marked for deletion\n"
+             "Stop the service and retry install");
+      else
+        printf(" failed, Error=%ld\n", err);
+      CloseServiceHandle(hm);
+      return 1;
+    }
+    // Set optional description
+    if (svc_opts->descript) {
+      SERVICE_DESCRIPTIONA sd = { const_cast<char *>(svc_opts->descript) };
+      ChangeServiceConfig2A(hs, SERVICE_CONFIG_DESCRIPTION, &sd);
+    }
+    // Enable delayed auto start if supported
+    OSVERSIONINFOA ver; ver.dwOSVersionInfoSize = sizeof(ver);
+    if (   GetVersionExA(&ver)
+        && ver.dwPlatformId == VER_PLATFORM_WIN32_NT
+        && ver.dwMajorVersion >= 6 /* Vista */      ) {
+      SERVICE_DELAYED_AUTO_START_INFO sdasi = { TRUE };
+      ChangeServiceConfig2A(hs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &sdasi);
+    }
+  }
+  else {
+    // Open
+    if (!(hs = OpenService(hm, svc_opts->svcname, SERVICE_ALL_ACCESS))) {
+      puts(" not found");
+      CloseServiceHandle(hm);
+      return 1;
+    }
+    // TODO: Stop service if running
+    // Remove
+    if (!DeleteService(hs)) {
+      if ((err = GetLastError()) == ERROR_SERVICE_MARKED_FOR_DELETE)
+        puts(" service is still running and marked for deletion\n"
+             "Stop the service to remove it");
+      else
+        printf(" failed, Error=%ld\n", err);
+      CloseServiceHandle(hs); CloseServiceHandle(hm);
+      return 1;
+    }
+  }
+  puts(" done");
+  CloseServiceHandle(hs); CloseServiceHandle(hm);
+
+  // Install/Remove event message file registry entry
+  if (!remove) {
+    inst_evtmsg(ident);
+  }
+  else {
+    uninst_evtmsg(ident);
+  }
+
+  return 0;
 }
 
 
@@ -1112,77 +1058,77 @@ static int svcadm_main(const char * ident, const daemon_winsvc_options * svc_opt
 int daemon_main(const char * ident, const daemon_winsvc_options * svc_opts,
                 int (*main_func)(int, char **), int argc, char **argv      )
 {
-       int rc;
+  int rc;
 #ifdef _DEBUG
-       // Enable Debug heap checks
-       _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
-               |_CRTDBG_ALLOC_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF);
+  // Enable Debug heap checks
+  _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)
+    |_CRTDBG_ALLOC_MEM_DF|_CRTDBG_CHECK_ALWAYS_DF|_CRTDBG_LEAK_CHECK_DF);
 #endif
 
-       // Check for [status|stop|reload|restart|sigusr1|sigusr2] parameters
-       if ((rc = initd_main(ident, argc, argv)) >= 0)
-               return rc;
-       // Check for [install|remove] parameters
-       if (svc_opts && (rc = svcadm_main(ident, svc_opts, argc, argv)) >= 0)
-               return rc;
-
-       // Run as service if svc_opts.cmd_opt is given as first(!) argument
-       svc_mode = (svc_opts && argc >= 2 && !strcmp(argv[1], svc_opts->cmd_opt));
-
-       if (!svc_mode) {
-               // Daemon: Try to simulate a Unix-like daemon
-               HANDLE rev;
-               BOOL exists;
-
-               // Create main event to detect process type:
-               // 1. new: parent process => start child and wait for detach() or exit() of child.
-               // 2. exists && signaled: child process => do the real work, signal detach() to parent
-               // 3. exists && !signaled: already running => exit()
-               if (!(rev = create_event(EVT_RUNNING, TRUE/*signaled*/, TRUE, &exists)))
-                       return 100;
-
-               if (!exists && !debugging()) {
-                       // Event new => parent process
-                       return parent_main(rev);
-               }
-
-               if (WaitForSingleObject(rev, 0) == WAIT_OBJECT_0) {
-                       // Event was signaled => In child process
-                       return child_main(rev, main_func, argc, argv);
-               }
-
-               // Event no longer signaled => Already running!
-               daemon_help(stdout, ident, "already running");
-               CloseHandle(rev);
-               return 1;
-       }
-       else {
-               // Service: Start service_main() via SCM
-               SERVICE_TABLE_ENTRY service_table[] = {
-                       { (char*)svc_opts->svcname, service_main }, { NULL, NULL }
-               };
-
-               svc_main_func = main_func;
-               svc_main_argc = argc;
-               svc_main_argv = argv;
-               if (!StartServiceCtrlDispatcher(service_table)) {
-                       printf("%s: cannot dispatch service, Error=%ld\n"
-                               "Option \"%s\" cannot be used to start %s as a service from console.\n"
-                               "Use \"%s install ...\" to install the service\n"
-                               "and \"net start %s\" to start it.\n",
-                               ident, GetLastError(), svc_opts->cmd_opt, ident, ident, ident);
+  // Check for [status|stop|reload|restart|sigusr1|sigusr2] parameters
+  if ((rc = initd_main(ident, argc, argv)) >= 0)
+    return rc;
+  // Check for [install|remove] parameters
+  if (svc_opts && (rc = svcadm_main(ident, svc_opts, argc, argv)) >= 0)
+    return rc;
+
+  // Run as service if svc_opts.cmd_opt is given as first(!) argument
+  svc_mode = (svc_opts && argc >= 2 && !strcmp(argv[1], svc_opts->cmd_opt));
+
+  if (!svc_mode) {
+    // Daemon: Try to simulate a Unix-like daemon
+    HANDLE rev;
+    BOOL exists;
+
+    // Create main event to detect process type:
+    // 1. new: parent process => start child and wait for detach() or exit() of child.
+    // 2. exists && signaled: child process => do the real work, signal detach() to parent
+    // 3. exists && !signaled: already running => exit()
+    if (!(rev = create_event(EVT_RUNNING, TRUE/*signaled*/, TRUE, &exists)))
+      return 100;
+
+    if (!exists && !debugging()) {
+      // Event new => parent process
+      return parent_main(rev);
+    }
+
+    if (WaitForSingleObject(rev, 0) == WAIT_OBJECT_0) {
+      // Event was signaled => In child process
+      return child_main(rev, main_func, argc, argv);
+    }
+
+    // Event no longer signaled => Already running!
+    daemon_help(stdout, ident, "already running");
+    CloseHandle(rev);
+    return 1;
+  }
+  else {
+    // Service: Start service_main() via SCM
+    SERVICE_TABLE_ENTRY service_table[] = {
+      { (char*)svc_opts->svcname, service_main }, { NULL, NULL }
+    };
+
+    svc_main_func = main_func;
+    svc_main_argc = argc;
+    svc_main_argv = argv;
+    if (!StartServiceCtrlDispatcher(service_table)) {
+      printf("%s: cannot dispatch service, Error=%ld\n"
+        "Option \"%s\" cannot be used to start %s as a service from console.\n"
+        "Use \"%s install ...\" to install the service\n"
+        "and \"net start %s\" to start it.\n",
+        ident, GetLastError(), svc_opts->cmd_opt, ident, ident, ident);
 
 #ifdef _DEBUG
-                       if (debugging())
-                               service_main(argc, argv);
+      if (debugging())
+        service_main(argc, argv);
 #endif
-                       return 100;
-               }
-               Sleep(1000);
-               ExitThread(0); // Do not redo exit() processing
-               /*NOTREACHED*/
-               return 0;
-       }
+      return 100;
+    }
+    Sleep(1000);
+    ExitThread(0); // Do not redo exit() processing
+    /*NOTREACHED*/
+    return 0;
+  }
 }
 
 
@@ -1195,88 +1141,88 @@ static volatile sig_atomic_t caughtsig = 0;
 
 static void sig_handler(int sig)
 {
-       caughtsig = sig;
+  caughtsig = sig;
 }
 
 static void test_exit(void)
 {
-       printf("Main exit\n");
+  printf("Main exit\n");
 }
 
 int test_main(int argc, char **argv)
 {
-       int i;
-       int debug = 0;
-       char * cmd = 0;
-
-       printf("PID=%ld\n", GetCurrentProcessId());
-       for (i = 0; i < argc; i++) {
-               printf("%d: \"%s\"\n", i, argv[i]);
-               if (!strcmp(argv[i],"-d"))
-                       debug = 1;
-       }
-       if (argc > 1 && argv[argc-1][0] != '-')
-               cmd = argv[argc-1];
-
-       daemon_signal(SIGINT, sig_handler);
-       daemon_signal(SIGBREAK, sig_handler);
-       daemon_signal(SIGTERM, sig_handler);
-       daemon_signal(SIGHUP, sig_handler);
-       daemon_signal(SIGUSR1, sig_handler);
-       daemon_signal(SIGUSR2, sig_handler);
-
-       atexit(test_exit);
-
-       if (!debug) {
-               printf("Preparing to detach...\n");
-               Sleep(2000);
-               daemon_detach("test");
-               printf("Detached!\n");
-       }
-
-       for (;;) {
-               daemon_sleep(1);
-               printf("."); fflush(stdout);
-               if (caughtsig) {
-                       if (caughtsig == SIGUSR2) {
-                               debug ^= 1;
-                               if (debug)
-                                       daemon_enable_console("Daemon[Debug]");
-                               else
-                                       daemon_disable_console();
-                       }
-                       else if (caughtsig == SIGUSR1 && cmd) {
-                               char inpbuf[200], outbuf[1000]; int rc;
-                               strcpy(inpbuf, "Hello\nWorld!\n");
-                               rc = daemon_spawn(cmd, inpbuf, strlen(inpbuf), outbuf, sizeof(outbuf));
-                               if (!debug)
-                                       daemon_enable_console("Command output");
-                               printf("\"%s\" returns %d\n", cmd, rc);
-                               if (rc >= 0)
-                                       printf("output:\n%s.\n", outbuf);
-                               fflush(stdout);
-                               if (!debug) {
-                                       Sleep(10000); daemon_disable_console();
-                               }
-                       }
-                       printf("[PID=%ld: Signal=%d]", GetCurrentProcessId(), caughtsig); fflush(stdout);
-                       if (caughtsig == SIGTERM || caughtsig == SIGBREAK)
-                               break;
-                       caughtsig = 0;
-               }
-       }
-       printf("\nExiting on signal %d\n", caughtsig);
-       return 0;
+  int i;
+  int debug = 0;
+  char * cmd = 0;
+
+  printf("PID=%ld\n", GetCurrentProcessId());
+  for (i = 0; i < argc; i++) {
+    printf("%d: \"%s\"\n", i, argv[i]);
+    if (!strcmp(argv[i],"-d"))
+      debug = 1;
+  }
+  if (argc > 1 && argv[argc-1][0] != '-')
+    cmd = argv[argc-1];
+
+  daemon_signal(SIGINT, sig_handler);
+  daemon_signal(SIGBREAK, sig_handler);
+  daemon_signal(SIGTERM, sig_handler);
+  daemon_signal(SIGHUP, sig_handler);
+  daemon_signal(SIGUSR1, sig_handler);
+  daemon_signal(SIGUSR2, sig_handler);
+
+  atexit(test_exit);
+
+  if (!debug) {
+    printf("Preparing to detach...\n");
+    Sleep(2000);
+    daemon_detach("test");
+    printf("Detached!\n");
+  }
+
+  for (;;) {
+    daemon_sleep(1);
+    printf("."); fflush(stdout);
+    if (caughtsig) {
+      if (caughtsig == SIGUSR2) {
+        debug ^= 1;
+        if (debug)
+          daemon_enable_console("Daemon[Debug]");
+        else
+          daemon_disable_console();
+      }
+      else if (caughtsig == SIGUSR1 && cmd) {
+        char inpbuf[200], outbuf[1000]; int rc;
+        strcpy(inpbuf, "Hello\nWorld!\n");
+        rc = daemon_spawn(cmd, inpbuf, strlen(inpbuf), outbuf, sizeof(outbuf));
+        if (!debug)
+          daemon_enable_console("Command output");
+        printf("\"%s\" returns %d\n", cmd, rc);
+        if (rc >= 0)
+          printf("output:\n%s.\n", outbuf);
+        fflush(stdout);
+        if (!debug) {
+          Sleep(10000); daemon_disable_console();
+        }
+      }
+      printf("[PID=%ld: Signal=%d]", GetCurrentProcessId(), caughtsig); fflush(stdout);
+      if (caughtsig == SIGTERM || caughtsig == SIGBREAK)
+        break;
+      caughtsig = 0;
+    }
+  }
+  printf("\nExiting on signal %d\n", caughtsig);
+  return 0;
 }
 
 
 int main(int argc, char **argv)
 {
-       static const daemon_winsvc_options svc_opts = {
-       "-s", "test", "Test Service", "Service to test daemon_win32.c Module"
-       };
+  static const daemon_winsvc_options svc_opts = {
+  "-s", "test", "Test Service", "Service to test daemon_win32.c Module"
+  };
 
-       return daemon_main("testd", &svc_opts, test_main, argc, argv);
+  return daemon_main("testd", &svc_opts, test_main, argc, argv);
 }
 
 #endif
index cb20d84018fb98b4eb2eda77c93abad64d81fc89..2d9c1c5baf8725dbe353f689ea8c55f9183987f8 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2004-8 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2004-12 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
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 #ifndef DAEMON_WIN32_H
 #define DAEMON_WIN32_H
 
-#define DAEMON_WIN32_H_CVSID "$Id: daemon_win32.h,v 1.7 2008/03/04 22:09:48 ballen4705 Exp $\n"
+#define DAEMON_WIN32_H_CVSID "$Id: daemon_win32.h 3584 2012-08-05 17:05:32Z chrfranke $"
 
 #include <signal.h>
 
@@ -60,9 +59,6 @@ int daemon_enable_console(const char * title);
 // Detach from console
 int daemon_detach(const char * ident);
 
-// Display a message box
-int daemon_messagebox(int system, const char * title, const char * text);
-
 // Spawn a process and redirect stdio
 int daemon_spawn(const char * cmd,
                  const char * inpbuf, int inpsize,
diff --git a/os_win32/hostname_win32.cpp b/os_win32/hostname_win32.cpp
deleted file mode 100644 (file)
index 1ad4a52..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * os_win32/hostname_win32.cpp
- *
- * Home page of code is: http://smartmontools.sourceforge.net
- *
- * Copyright (C) 2004-8 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, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include "hostname_win32.h"
-
-const char * hostname_win32_c_cvsid = "$Id: hostname_win32.cpp,v 1.6 2008/03/04 22:09:48 ballen4705 Exp $" HOSTNAME_WIN32_H_CVSID;
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <string.h>
-
-#ifndef MAX_HOSTNAME_LEN
-
-// From IPHlpApi.dll:
-
-#define MAX_HOSTNAME_LEN    132
-#define MAX_DOMAIN_NAME_LEN 132
-#define MAX_SCOPE_ID_LEN    260
-
-typedef struct {
-  char String[4 * 4];
-} IP_ADDRESS_STRING, 
-*PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING;
-
-typedef struct _IP_ADDR_STRING {
-  struct _IP_ADDR_STRING* Next;
-  IP_ADDRESS_STRING IpAddress;
-  IP_MASK_STRING IpMask;
-  DWORD Context;
-} IP_ADDR_STRING, 
-*PIP_ADDR_STRING;
-
-typedef struct {
-  char HostName[MAX_HOSTNAME_LEN];
-  char DomainName[MAX_DOMAIN_NAME_LEN];
-  PIP_ADDR_STRING CurrentDnsServer;
-  IP_ADDR_STRING DnsServerList;
-  UINT NodeType;
-  char ScopeId[MAX_SCOPE_ID_LEN];
-  UINT EnableRouting;
-  UINT EnableProxy;
-  UINT EnableDns;
-} FIXED_INFO,
-*PFIXED_INFO;
-
-DWORD WINAPI GetNetworkParams(PFIXED_INFO info, PULONG size);
-
-#endif // MAX_HOSTNAME_LEN
-
-
-// Call GetComputerNameEx() if available (Win2000/XP)
-
-static BOOL CallGetComputerNameExA(int type, LPSTR name, LPDWORD size)
-{
-       HINSTANCE hdll;
-       BOOL (WINAPI * GetComputerNameExA_p)(int/*enum COMPUTER_NAME_FORMAT*/, LPSTR, LPDWORD);
-       BOOL ret;
-       if (!(hdll = LoadLibraryA("KERNEL32.DLL")))
-               return FALSE;
-       if (!(GetComputerNameExA_p = (BOOL (WINAPI *)(int, LPSTR, LPDWORD))GetProcAddress(hdll, "GetComputerNameExA")))
-               ret = FALSE;
-       else
-               ret = GetComputerNameExA_p(type, name, size);
-       FreeLibrary(hdll);
-       return ret;
-}
-
-
-// Call GetNetworkParams() if available (Win98/ME/2000/XP)
-
-static DWORD CallGetNetworkParams(PFIXED_INFO info, PULONG size)
-{
-       HINSTANCE hdll;
-       DWORD (WINAPI * GetNetworkParams_p)(PFIXED_INFO, PULONG);
-       DWORD ret;
-       if (!(hdll = LoadLibraryA("IPHlpApi.dll")))
-               return ERROR_NOT_SUPPORTED;
-       if (!(GetNetworkParams_p = (DWORD (WINAPI *)(PFIXED_INFO, PULONG))GetProcAddress(hdll, "GetNetworkParams")))
-               ret = ERROR_NOT_SUPPORTED;
-       else
-               ret = GetNetworkParams_p(info, size);
-       FreeLibrary(hdll);
-       return ret;
-}
-
-
-// Get host/domainname from registry (Win98/ME/NT4/2000/XP)
-
-static DWORD GetNamesFromRegistry(BOOL domain, char * name, int len)
-{
-       HKEY hk; DWORD size, type;
-       if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
-           (GetVersion() & 0x80000000
-            ? "System\\CurrentControlSet\\Services\\VxD\\MSTCP" //Win9x/ME
-            : "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
-           0, KEY_READ, &hk) != ERROR_SUCCESS)
-               return 0;
-       size = len-1;
-       if (!(RegQueryValueExA(hk, (!domain?"HostName":"Domain"), 0, &type, (unsigned char *)name, &size) == ERROR_SUCCESS && type == REG_SZ))
-               size = 0;
-       if (size == 0 && domain) {
-               size = len-1;
-               if (!(RegQueryValueExA(hk, "DhcpDomain", 0, &type, (unsigned char *)name, &size) == ERROR_SUCCESS && type == REG_SZ))
-                       size = 0;
-       }
-       RegCloseKey(hk);
-       return size;
-}
-
-
-static int gethostdomname(int domain, char * name, int len)
-{
-       DWORD size; FIXED_INFO info;
-
-       // try KERNEL32.dll::GetComputerNameEx()
-       size = len - 1;
-       if (CallGetComputerNameExA((!domain ? 1:2/*ComputerNameDnsHost:Domain*/), name, &size))
-               return 0;
-
-       // try IPHlpApi.dll::GetNetworkParams() 
-       size = sizeof(info);
-       if (CallGetNetworkParams(&info, &size) == ERROR_SUCCESS) {
-               strncpy(name, (!domain?info.HostName:info.DomainName), len-1); name[len-1] = 0;
-               return 0;
-       }
-
-       // try registry
-       if (GetNamesFromRegistry(domain, name, len))
-               return 0;
-
-       if (domain)
-               return -1;
-
-       // last resort: get NETBIOS name
-       size = len - 1;
-       if (GetComputerNameA(name, &size))
-               return 0;
-
-       return -1;
-}
-
-
-int gethostname(char * name, int len)
-{
-       return gethostdomname(0, name, len);
-}
-
-
-int getdomainname(char * name, int len)
-{
-       return gethostdomname(1, name, len);
-}
-
-
-#ifdef TEST
-
-#include <stdio.h>
-
-main()
-{
-       char name[256];
-       if (gethostname(name, sizeof(name)))
-               strcpy(name, "Error");
-       printf("hostname=\"%s\"\n", name);
-       if (getdomainname(name, sizeof(name)))
-               strcpy(name, "Error");
-       printf("domainname=\"%s\"\n", name);
-       return 0;
-}
-
-#endif
diff --git a/os_win32/hostname_win32.h b/os_win32/hostname_win32.h
deleted file mode 100644 (file)
index 7825764..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * os_win32/hostname_win32.h
- *
- * Home page of code is: http://smartmontools.sourceforge.net
- *
- * Copyright (C) 2004-8 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, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef HOSTNAME_WIN32_H
-#define HOSTNAME_WIN32_H
-
-#define HOSTNAME_WIN32_H_CVSID "$Id: hostname_win32.h,v 1.5 2008/03/04 22:09:48 ballen4705 Exp $\n"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int gethostname(char * name, int len);
-int getdomainname(char * name, int len);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // HOSTNAME_WIN32_H
index d918ac6fd7726a05971fcf5ff40123fbeb8618df..9682946b0d2b8c8bfe5096d9599d92c50e6c1fec 100644 (file)
@@ -3,7 +3,7 @@
 ;
 ; Home page of code is: http://smartmontools.sourceforge.net
 ;
-; Copyright (C) 2006-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+; Copyright (C) 2006-13 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
@@ -13,7 +13,7 @@
 ; You should have received a copy of the GNU General Public License
 ; (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
 ;
-; $Id: installer.nsi 3545 2012-05-25 21:19:03Z chrfranke $
+; $Id: installer.nsi 3759 2013-01-26 21:11:02Z chrfranke $
 ;
 
 
@@ -87,7 +87,7 @@ InstType "Drive menu"
 ; Sections
 
 !ifdef INPDIR64
-  Section "64-bit version (EXPERIMENTAL)" X64_SECTION
+  Section "64-bit version" X64_SECTION
     ; Handled in Function CheckX64
   SectionEnd
 !endif
@@ -135,16 +135,15 @@ SectionGroup "!Program files"
     !insertmacro FileExe "bin\smartd.exe" ""
 
     IfFileExists "$INSTDIR\bin\smartd.conf" 0 +2
-      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 "Replace existing configuration file$\n$INSTDIR\bin\smartd.conf ?" IDYES 0 IDNO +2
+      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 "Replace existing configuration file$\n$INSTDIR\bin\smartd.conf ?" /SD IDNO IDYES 0 IDNO +2
         File "${INPDIR}\doc\smartd.conf"
 
-    IfFileExists "$WINDIR\system32\cmd.exe" 0 nosysl
-      !insertmacro FileExe "bin\syslogevt.exe" /nonfatal
-    nosysl:
+    File "${INPDIR}\bin\smartd_warning.cmd"
+    !insertmacro FileExe "bin\wtssendmsg.exe" ""
 
     ; Restart service ?
     StrCmp $1 "0" 0 +3
-      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Restart smartd service ?" IDYES 0 IDNO +2
+      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Restart smartd service ?" /SD IDNO IDYES 0 IDNO +2
         ExecWait "net start smartd"
 
   SectionEnd
@@ -176,7 +175,8 @@ Section "!Documentation" DOC_SECTION
 
   SetOutPath "$INSTDIR\doc"
   File "${INPDIR}\doc\AUTHORS.txt"
-  File "${INPDIR}\doc\CHANGELOG.txt"
+  File "${INPDIR}\doc\ChangeLog.txt"
+  File "${INPDIR}\doc\ChangeLog-5.0-6.0.txt"
   File "${INPDIR}\doc\COPYING.txt"
   File "${INPDIR}\doc\INSTALL.txt"
   File "${INPDIR}\doc\NEWS.txt"
@@ -253,16 +253,14 @@ Section "Start Menu Shortcuts" MENU_SECTION
   ; smartctl
   IfFileExists "$INSTDIR\bin\smartctl.exe" 0 noctl
     SetOutPath "$INSTDIR\bin"
-    IfFileExists "$WINDIR\system32\cmd.exe" 0 nocmd
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl (Admin CMD).lnk" "$WINDIR\system32\cmd.exe" '/k PATH=$INSTDIR\bin;%PATH%&cd /d "$INSTDIR\bin"'
-    nocmd:
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl (Admin CMD).lnk" "$WINDIR\system32\cmd.exe" '/k PATH=$INSTDIR\bin;%PATH%&cd /d "$INSTDIR\bin"'
     CreateDirectory "$SMPROGRAMS\smartmontools\smartctl Examples"
     FileOpen $0 "$SMPROGRAMS\smartmontools\smartctl Examples\!Read this first!.txt" "w"
     FileWrite $0 "All the example commands in this directory$\r$\napply to the first drive (sda).$\r$\n"
     FileClose $0
-    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\All info (-a).lnk"                    "$INSTDIR\bin\runcmdu.exe" "smartctl -a sda"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\All info (-x).lnk"                    "$INSTDIR\bin\runcmdu.exe" "smartctl -x sda"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\Identify drive (-i).lnk"              "$INSTDIR\bin\runcmdu.exe" "smartctl -i sda"
-    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\SMART attributes (-A).lnk"            "$INSTDIR\bin\runcmdu.exe" "smartctl -A sda"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\SMART attributes (-A -f brief).lnk"   "$INSTDIR\bin\runcmdu.exe" "smartctl -A -f brief sda"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\SMART capabilities (-c).lnk"          "$INSTDIR\bin\runcmdu.exe" "smartctl -c sda"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\SMART health status (-H).lnk"         "$INSTDIR\bin\runcmdu.exe" "smartctl -H sda"
     !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartctl Examples\SMART error log (-l error).lnk"       "$INSTDIR\bin\runcmdu.exe" "smartctl -l error sda"
@@ -288,15 +286,13 @@ Section "Start Menu Shortcuts" MENU_SECTION
     CreateShortCut "$SMPROGRAMS\smartmontools\smartd Examples\smartd.conf (view).lnk"                   "$EDITOR" "$INSTDIR\bin\smartd.conf"
     CreateShortCut "$SMPROGRAMS\smartmontools\smartd Examples\smartd.log (view).lnk"                    "$EDITOR" "$INSTDIR\bin\smartd.log"
 
-    ; smartd service (not on 9x/ME)
-    IfFileExists "$WINDIR\system32\cmd.exe" 0 nosvc
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service install, eventlog, 30min.lnk"   "$INSTDIR\bin\runcmdu.exe" "smartd install"
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service install, smartd.log, 10min.lnk" "$INSTDIR\bin\runcmdu.exe" "smartd install -l local0 -i 600"
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service install, smartd.log, 30min.lnk" "$INSTDIR\bin\runcmdu.exe" "smartd install -l local0"
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service remove.lnk"                     "$INSTDIR\bin\runcmdu.exe" "smartd remove"
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service start.lnk"                      "$INSTDIR\bin\runcmdu.exe" "net start smartd"
-      !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service stop.lnk"                       "$INSTDIR\bin\runcmdu.exe" "net stop smartd"
-    nosvc:
+    ; smartd service
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service install, eventlog, 30min.lnk"   "$INSTDIR\bin\runcmdu.exe" "smartd install"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service install, smartd.log, 10min.lnk" "$INSTDIR\bin\runcmdu.exe" "smartd install -l local0 -i 600"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service install, smartd.log, 30min.lnk" "$INSTDIR\bin\runcmdu.exe" "smartd install -l local0"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service remove.lnk"                     "$INSTDIR\bin\runcmdu.exe" "smartd remove"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service start.lnk"                      "$INSTDIR\bin\runcmdu.exe" "net start smartd"
+    !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\smartd Examples\Service stop.lnk"                       "$INSTDIR\bin\runcmdu.exe" "net stop smartd"
   nod:
 
   ; Documentation
@@ -314,14 +310,9 @@ Section "Start Menu Shortcuts" MENU_SECTION
         CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\drivedb.h (view).lnk" "$EDITOR" "$INSTDIR\bin\drivedb.h"
         !insertmacro CreateAdminShortCut "$SMPROGRAMS\smartmontools\Documentation\drivedb-add.h (create, edit).lnk" "$EDITOR" "$INSTDIR\bin\drivedb-add.h"
     nodb:
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\AUTHORS.lnk"   "$INSTDIR\doc\AUTHORS.txt"
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\CHANGELOG.lnk" "$INSTDIR\doc\CHANGELOG.txt"
+    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\ChangeLog.lnk" "$INSTDIR\doc\ChangeLog.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\COPYING.lnk"   "$INSTDIR\doc\COPYING.txt"
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\INSTALL.lnk"   "$INSTDIR\doc\INSTALL.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\NEWS.lnk"      "$INSTDIR\doc\NEWS.txt"
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\README.lnk"    "$INSTDIR\doc\README.txt"
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\TODO.lnk"      "$INSTDIR\doc\TODO.txt"
-    CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\WARNINGS.lnk"  "$INSTDIR\doc\WARNINGS.txt"
     CreateShortCut "$SMPROGRAMS\smartmontools\Documentation\Windows version download page.lnk" "http://smartmontools-win32.dyndns.org/smartmontools/"
   nodoc:
 
@@ -346,9 +337,8 @@ Section "Add install dir to PATH" PATH_SECTION
 
   SectionIn 1
 
-  IfFileExists "$WINDIR\system32\cmd.exe" 0 +3
-    Push "$INSTDIR\bin"
-    Call AddToPath
+  Push "$INSTDIR\bin"
+  Call AddToPath
  
 SectionEnd
 
@@ -379,9 +369,9 @@ SectionGroup "Add smartctl to drive menu"
   SectionEnd
 !macroend
 
-  !insertmacro DriveSection 0 "SMART all info"       "-a"
+  !insertmacro DriveSection 0 "SMART all info"       "-x"
   !insertmacro DriveSection 1 "SMART status"         "-Hc"
-  !insertmacro DriveSection 2 "SMART attributes"     "-A"
+  !insertmacro DriveSection 2 "SMART attributes"     "-A -f brief"
   !insertmacro DriveSection 3 "SMART short selftest" "-t short"
   !insertmacro DriveSection 4 "SMART long selftest"  "-t long"
   !insertmacro DriveSection 5 "SMART continue selective selftest"  '-t "selective,cont"'
@@ -397,7 +387,7 @@ Section "Uninstall"
     ReadRegStr $0 HKLM "System\CurrentControlSet\Services\smartd" "ImagePath"
     StrCmp $0 "" nosrv
       ExecWait "net stop smartd"
-      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Remove smartd service ?" IDYES 0 IDNO nosrv
+      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Remove smartd service ?" /SD IDNO IDYES 0 IDNO nosrv
         ExecWait "$INSTDIR\bin\smartd.exe remove"
   nosrv:
 
@@ -411,25 +401,25 @@ Section "Uninstall"
     GetFileTime "$INSTDIR\bin\smartd.conf" $0 $1
     GetFileTime "$INSTDIR\doc\smartd.conf" $2 $3
     StrCmp "$0:$1" "$2:$3" +2 0
-      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete configuration file$\n$INSTDIR\bin\smartd.conf ?" IDYES 0 IDNO noconf
+      MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete configuration file$\n$INSTDIR\bin\smartd.conf ?" /SD IDNO IDYES 0 IDNO noconf
         Delete "$INSTDIR\bin\smartd.conf"
   noconf:
 
   ; Remove log file ?
   IfFileExists "$INSTDIR\bin\smartd.log" 0 +3
-    MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete log file$\n$INSTDIR\bin\smartd.log ?" IDYES 0 IDNO +2
+    MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete log file$\n$INSTDIR\bin\smartd.log ?" /SD IDNO IDYES 0 IDNO +2
       Delete "$INSTDIR\bin\smartd.log"
 
   ; Remove drivedb-add file ?
   IfFileExists "$INSTDIR\bin\drivedb-add.h" 0 +3
-    MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete local drive database file$\n$INSTDIR\bin\drivedb-add.h ?" IDYES 0 IDNO +2
+    MessageBox MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2  "Delete local drive database file$\n$INSTDIR\bin\drivedb-add.h ?" /SD IDNO IDYES 0 IDNO +2
       Delete "$INSTDIR\bin\drivedb-add.h"
 
   ; Remove files
   Delete "$INSTDIR\bin\smartctl.exe"
   Delete "$INSTDIR\bin\smartctl-nc.exe"
   Delete "$INSTDIR\bin\smartd.exe"
-  Delete "$INSTDIR\bin\syslogevt.exe"
+  Delete "$INSTDIR\bin\smartd_warning.cmd" ; TODO: Check for modifications?
   Delete "$INSTDIR\bin\drivedb.h"
   Delete "$INSTDIR\bin\drivedb.h.error"
   Delete "$INSTDIR\bin\drivedb.h.lastcheck"
@@ -442,8 +432,10 @@ Section "Uninstall"
   Delete "$INSTDIR\bin\runcmda.exe.manifest"
   Delete "$INSTDIR\bin\runcmdu.exe"
   Delete "$INSTDIR\bin\runcmdu.exe.manifest"
+  Delete "$INSTDIR\bin\wtssendmsg.exe"
   Delete "$INSTDIR\doc\AUTHORS.txt"
-  Delete "$INSTDIR\doc\CHANGELOG.txt"
+  Delete "$INSTDIR\doc\ChangeLog.txt"
+  Delete "$INSTDIR\doc\ChangeLog-5.0-6.0.txt"
   Delete "$INSTDIR\doc\COPYING.txt"
   Delete "$INSTDIR\doc\INSTALL.txt"
   Delete "$INSTDIR\doc\NEWS.txt"
@@ -477,22 +469,21 @@ Section "Uninstall"
   RMDir  "$INSTDIR"
 
   ; Remove install dir from PATH
-  IfFileExists "$WINDIR\system32\cmd.exe" 0 +3
-    Push "$INSTDIR\bin"
-    Call un.RemoveFromPath
+  Push "$INSTDIR\bin"
+  Call un.RemoveFromPath
 
   ; Remove drive menu registry entries
   !insertmacro DriveMenuRemove
 
   ; Check for still existing entries
   IfFileExists "$INSTDIR\bin\smartd.exe" 0 +3
-    MessageBox MB_OK|MB_ICONEXCLAMATION "$INSTDIR\bin\smartd.exe could not be removed.$\nsmartd is possibly still running."
+    MessageBox MB_OK|MB_ICONEXCLAMATION "$INSTDIR\bin\smartd.exe could not be removed.$\nsmartd is possibly still running." /SD IDOK
     Goto +3
   IfFileExists "$INSTDIR" 0 +2
-    MessageBox MB_OK "Note: $INSTDIR could not be removed."
+    MessageBox MB_OK "Note: $INSTDIR could not be removed." /SD IDOK
 
   IfFileExists "$SMPROGRAMS\smartmontools" 0 +2
-    MessageBox MB_OK "Note: $SMPROGRAMS\smartmontools could not be removed."
+    MessageBox MB_OK "Note: $SMPROGRAMS\smartmontools could not be removed." /SD IDOK
 
 SectionEnd
 
@@ -530,10 +521,6 @@ Function .onInit
   IfFileExists "$EDITOR" +2 0
     StrCpy $EDITOR "notepad.exe"
 
-  ; Hide "Add install dir to PATH" on 9x/ME
-  IfFileExists "$WINDIR\system32\cmd.exe" +2 0
-    SectionSetText ${PATH_SECTION} ""
-
   Call ParseCmdLine
 FunctionEnd
 
diff --git a/os_win32/runcmd_vc10.vcxproj b/os_win32/runcmd_vc10.vcxproj
deleted file mode 100644 (file)
index f254c6f..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{11A4B619-D97B-499F-AF17-CF9F80BF70E8}</ProjectGuid>
-    <Keyword>Win32Proj</Keyword>
-    <RootNamespace>runcmd</RootNamespace>
-    <ProjectName>runcmd</ProjectName>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>true</UseDebugLibraries>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <UseDebugLibraries>false</UseDebugLibraries>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <OutDir>.\runcmdu_vc10.d\</OutDir>
-    <IntDir>.\runcmdu_vc10.d\</IntDir>
-    <TargetName>$(ProjectName)u</TargetName>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <OutDir>.\runcmdu_vc10.r\</OutDir>
-    <IntDir>.\runcmdu_vc10.r\</IntDir>
-    <TargetName>$(ProjectName)u</TargetName>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <WarningLevel>Level3</WarningLevel>
-      <Optimization>MaxSpeed</Optimization>
-      <FunctionLevelLinking>true</FunctionLevelLinking>
-      <IntrinsicFunctions>true</IntrinsicFunctions>
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-    </ClCompile>
-    <Link>
-      <SubSystem>Console</SubSystem>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <OptimizeReferences>true</OptimizeReferences>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="runcmd.c" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/os_win32/smartctl_res.rc.in b/os_win32/smartctl_res.rc.in
new file mode 100644 (file)
index 0000000..b4d6d37
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// os_win32/smartctl_res.rc.in
+//
+// $Id: smartctl_res.rc.in 3755 2013-01-26 15:13:08Z chrfranke $
+//
+
+1 VERSIONINFO
+    FILEVERSION @BINARY_VERSION@
+    PRODUCTVERSION @BINARY_VERSION@
+    FILEFLAGSMASK 0x0
+    FILEFLAGS 0x0
+    FILEOS 0x4 // VOS__WINDOWS32
+    FILETYPE 0x1 // VFT_APP
+    FILESUBTYPE 0x0
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "04090000"
+        BEGIN
+            VALUE "CompanyName", "www.smartmontools.org"
+            VALUE "FileDescription", "Control and Monitor Utility for SMART Disks"
+            VALUE "FileVersion", "@TEXT_VERSION@"
+            VALUE "InternalName", "smartctl"
+            VALUE "LegalCopyright", "(C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org"
+            VALUE "OriginalFilename", "smartctl.exe"
+            VALUE "ProductName", "smartmontools"
+            VALUE "ProductVersion", "@TEXT_VERSION@"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0409, 0x0000
+    END
+END
diff --git a/os_win32/smartctl_vc10.vcxproj b/os_win32/smartctl_vc10.vcxproj
deleted file mode 100644 (file)
index 97f5bcb..0000000
+++ /dev/null
@@ -1,304 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{3AFEDCDD-D289-4543-A91D-EFBA6C710247}</ProjectGuid>
-    <RootNamespace>smartctl</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <ProjectName>smartctl</ProjectName>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\smartctl_vc10.d\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\smartctl_vc10.d\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\smartctl_vc10.r\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>.;..\getopt;..\regex;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Console</SubSystem>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\getopt;..\regex;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <OptimizeReferences>true</OptimizeReferences>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="daemon_win32.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="hostname_win32.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="syslog_win32.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="wmiquery.cpp" />
-    <ClCompile Include="..\regex\regcomp.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\regex\regex.c" />
-    <ClCompile Include="..\regex\regex_internal.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\regex\regexec.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\getopt\getopt.c" />
-    <ClCompile Include="..\getopt\getopt1.c" />
-    <ClCompile Include="..\atacmdnames.cpp" />
-    <ClCompile Include="..\atacmds.cpp" />
-    <ClCompile Include="..\ataprint.cpp" />
-    <ClCompile Include="..\cciss.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\dev_ata_cmd_set.cpp" />
-    <ClCompile Include="..\dev_interface.cpp" />
-    <ClCompile Include="..\dev_legacy.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\knowndrives.cpp" />
-    <ClCompile Include="..\os_darwin.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_freebsd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_generic.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_linux.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_netbsd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_openbsd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_os2.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_qnxnto.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_solaris.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_win32.cpp" />
-    <ClCompile Include="..\scsiata.cpp" />
-    <ClCompile Include="..\scsicmds.cpp" />
-    <ClCompile Include="..\scsiprint.cpp" />
-    <ClCompile Include="..\smartctl.cpp" />
-    <ClCompile Include="..\smartd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\utility.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuildStep Include="daemon_win32.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="hostname_win32.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="syslog.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <ClInclude Include="wbemcli_small.h" />
-    <ClInclude Include="wmiquery.h" />
-    <ClInclude Include="..\regex\regex.h" />
-    <ClInclude Include="..\regex\regex_internal.h" />
-    <ClInclude Include="..\getopt\getopt.h" />
-    <ClInclude Include="..\atacmdnames.h" />
-    <ClInclude Include="..\atacmds.h" />
-    <ClInclude Include="..\ataprint.h" />
-    <CustomBuildStep Include="..\cciss.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <ClInclude Include="..\cissio_freebsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClInclude>
-    <CustomBuild Include="config_vc10.h">
-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Copy %(FullPath) $(IntDir)config.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy %(FullPath) $(IntDir)config.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)config.h;%(Outputs)</Outputs>
-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Copy %(FullPath) $(IntDir)config.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy %(FullPath) $(IntDir)config.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)config.h;%(Outputs)</Outputs>
-    </CustomBuild>
-    <ClInclude Include="..\csmisas.h" />
-    <ClInclude Include="..\dev_ata_cmd_set.h" />
-    <ClInclude Include="..\dev_interface.h" />
-    <ClInclude Include="..\dev_tunnelled.h" />
-    <ClInclude Include="..\drivedb.h" />
-    <ClInclude Include="..\int64.h" />
-    <ClInclude Include="..\knowndrives.h" />
-    <CustomBuildStep Include="..\megaraid.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_darwin.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_freebsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_generic.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_linux.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_netbsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_openbsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_os2.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_qnxnto.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_solaris.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <ClInclude Include="..\scsicmds.h" />
-    <ClInclude Include="..\scsiprint.h" />
-    <ClInclude Include="..\smartctl.h" />
-    <CustomBuild Include="svnversion_vc10.h">
-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Copy %(FullPath) $(IntDir)svnversion.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy %(FullPath) $(IntDir)svnversion.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)svnversion.h;%(Outputs)</Outputs>
-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Copy %(FullPath) $(IntDir)svnversion.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy %(FullPath) $(IntDir)svnversion.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)svnversion.h;%(Outputs)</Outputs>
-    </CustomBuild>
-    <ClInclude Include="..\utility.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="installer.nsi" />
-    <None Include="update-smart-drivedb.nsi" />
-    <None Include="..\AUTHORS" />
-    <None Include="..\autogen.sh" />
-    <None Include="..\CHANGELOG" />
-    <None Include="..\config.h.in" />
-    <None Include="..\configure.in" />
-    <None Include="..\do_release" />
-    <None Include="..\Doxyfile" />
-    <None Include="..\INSTALL" />
-    <None Include="..\Makefile.am" />
-    <None Include="..\NEWS" />
-    <None Include="..\README" />
-    <None Include="..\smartctl.8.in" />
-    <None Include="..\smartd.8.in" />
-    <None Include="..\smartd.conf.5.in" />
-    <None Include="..\smartd.initd.in" />
-    <None Include="..\TODO" />
-    <None Include="..\update-smart-drivedb.in" />
-    <None Include="..\WARNINGS" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/os_win32/smartctl_vc10.vcxproj.filters b/os_win32/smartctl_vc10.vcxproj.filters
deleted file mode 100644 (file)
index fbcb4bf..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="os_win32">
-      <UniqueIdentifier>{9321e988-dd03-496d-9933-7c8b235a46bf}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="regex">
-      <UniqueIdentifier>{bfbfd4ea-fae3-45ec-9cfb-c5424218c47c}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="getopt">
-      <UniqueIdentifier>{8ff0bf5f-c96e-45c3-bcb4-7450cecfa0d4}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="daemon_win32.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="hostname_win32.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="syslog_win32.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="wmiquery.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regcomp.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regex.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regex_internal.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regexec.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\getopt\getopt.c">
-      <Filter>getopt</Filter>
-    </ClCompile>
-    <ClCompile Include="..\getopt\getopt1.c">
-      <Filter>getopt</Filter>
-    </ClCompile>
-    <ClCompile Include="..\atacmdnames.cpp" />
-    <ClCompile Include="..\atacmds.cpp" />
-    <ClCompile Include="..\ataprint.cpp" />
-    <ClCompile Include="..\cciss.cpp" />
-    <ClCompile Include="..\dev_ata_cmd_set.cpp" />
-    <ClCompile Include="..\dev_interface.cpp" />
-    <ClCompile Include="..\dev_legacy.cpp" />
-    <ClCompile Include="..\knowndrives.cpp" />
-    <ClCompile Include="..\os_darwin.cpp" />
-    <ClCompile Include="..\os_freebsd.cpp" />
-    <ClCompile Include="..\os_generic.cpp" />
-    <ClCompile Include="..\os_linux.cpp" />
-    <ClCompile Include="..\os_netbsd.cpp" />
-    <ClCompile Include="..\os_openbsd.cpp" />
-    <ClCompile Include="..\os_os2.cpp" />
-    <ClCompile Include="..\os_qnxnto.cpp" />
-    <ClCompile Include="..\os_solaris.cpp" />
-    <ClCompile Include="..\os_win32.cpp" />
-    <ClCompile Include="..\scsiata.cpp" />
-    <ClCompile Include="..\scsicmds.cpp" />
-    <ClCompile Include="..\scsiprint.cpp" />
-    <ClCompile Include="..\smartctl.cpp" />
-    <ClCompile Include="..\smartd.cpp" />
-    <ClCompile Include="..\utility.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="wbemcli_small.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="wmiquery.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="..\regex\regex.h">
-      <Filter>regex</Filter>
-    </ClInclude>
-    <ClInclude Include="..\regex\regex_internal.h">
-      <Filter>regex</Filter>
-    </ClInclude>
-    <ClInclude Include="..\getopt\getopt.h">
-      <Filter>getopt</Filter>
-    </ClInclude>
-    <ClInclude Include="..\atacmdnames.h" />
-    <ClInclude Include="..\atacmds.h" />
-    <ClInclude Include="..\ataprint.h" />
-    <ClInclude Include="..\cissio_freebsd.h" />
-    <ClInclude Include="..\csmisas.h" />
-    <ClInclude Include="..\dev_ata_cmd_set.h" />
-    <ClInclude Include="..\dev_interface.h" />
-    <ClInclude Include="..\dev_tunnelled.h" />
-    <ClInclude Include="..\drivedb.h" />
-    <ClInclude Include="..\int64.h" />
-    <ClInclude Include="..\knowndrives.h" />
-    <ClInclude Include="..\scsicmds.h" />
-    <ClInclude Include="..\scsiprint.h" />
-    <ClInclude Include="..\smartctl.h" />
-    <ClInclude Include="..\utility.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="installer.nsi">
-      <Filter>os_win32</Filter>
-    </None>
-    <None Include="update-smart-drivedb.nsi">
-      <Filter>os_win32</Filter>
-    </None>
-    <None Include="..\AUTHORS" />
-    <None Include="..\autogen.sh" />
-    <None Include="..\CHANGELOG" />
-    <None Include="..\config.h.in" />
-    <None Include="..\configure.in" />
-    <None Include="..\do_release" />
-    <None Include="..\Doxyfile" />
-    <None Include="..\INSTALL" />
-    <None Include="..\Makefile.am" />
-    <None Include="..\NEWS" />
-    <None Include="..\README" />
-    <None Include="..\smartctl.8.in" />
-    <None Include="..\smartd.8.in" />
-    <None Include="..\smartd.conf.5.in" />
-    <None Include="..\smartd.initd.in" />
-    <None Include="..\TODO" />
-    <None Include="..\update-smart-drivedb.in" />
-    <None Include="..\WARNINGS" />
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuildStep Include="daemon_win32.h">
-      <Filter>os_win32</Filter>
-    </CustomBuildStep>
-    <CustomBuildStep Include="hostname_win32.h">
-      <Filter>os_win32</Filter>
-    </CustomBuildStep>
-    <CustomBuildStep Include="syslog.h">
-      <Filter>os_win32</Filter>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\cciss.h" />
-    <CustomBuildStep Include="..\megaraid.h" />
-    <CustomBuildStep Include="..\os_darwin.h" />
-    <CustomBuildStep Include="..\os_freebsd.h" />
-    <CustomBuildStep Include="..\os_generic.h" />
-    <CustomBuildStep Include="..\os_linux.h" />
-    <CustomBuildStep Include="..\os_netbsd.h" />
-    <CustomBuildStep Include="..\os_openbsd.h" />
-    <CustomBuildStep Include="..\os_os2.h" />
-    <CustomBuildStep Include="..\os_qnxnto.h" />
-    <CustomBuildStep Include="..\os_solaris.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuild Include="config_vc10.h" />
-    <CustomBuild Include="svnversion_vc10.h" />
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/os_win32/smartd_res.rc.in b/os_win32/smartd_res.rc.in
new file mode 100644 (file)
index 0000000..f7900ee
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// os_win32/smartd_res.rc.in
+//
+// $Id: smartd_res.rc.in 3756 2013-01-26 16:16:35Z chrfranke $
+//
+
+1 VERSIONINFO
+    FILEVERSION @BINARY_VERSION@
+    PRODUCTVERSION @BINARY_VERSION@
+    FILEFLAGSMASK 0x0
+    FILEFLAGS 0x0
+    FILEOS 0x4 // VOS__WINDOWS32
+    FILETYPE 0x1 // VFT_APP
+    FILESUBTYPE 0x0
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "04090000"
+        BEGIN
+            VALUE "CompanyName", "www.smartmontools.org"
+            VALUE "FileDescription", "SMART Disk Monitoring Daemon"
+            VALUE "FileVersion", "@TEXT_VERSION@"
+            VALUE "InternalName", "smartd"
+            VALUE "LegalCopyright", "(C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org"
+            VALUE "OriginalFilename", "smartd.exe"
+            VALUE "ProductName", "smartmontools"
+            VALUE "ProductVersion", "@TEXT_VERSION@"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x0409, 0x0000
+    END
+END
+
+// eventlog MESSAGETABLE for syslog() emulation
+#include "syslogevt.rc"
diff --git a/os_win32/smartd_vc10.vcxproj b/os_win32/smartd_vc10.vcxproj
deleted file mode 100644 (file)
index af63ceb..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}</ProjectGuid>
-    <RootNamespace>smartd</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <ProjectName>smartd</ProjectName>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\smartd_vc10.d\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\smartd_vc10.d\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\smartd_vc10.r\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <AdditionalIncludeDirectories>.;..\getopt;..\regex;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>_DEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Console</SubSystem>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <AdditionalIncludeDirectories>.;..\getopt;..\regex;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>NDEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <OptimizeReferences>true</OptimizeReferences>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="daemon_win32.cpp" />
-    <ClCompile Include="hostname_win32.cpp" />
-    <ClCompile Include="syslog_win32.cpp" />
-    <ClCompile Include="wmiquery.cpp" />
-    <ClCompile Include="..\regex\regcomp.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\regex\regex.c" />
-    <ClCompile Include="..\regex\regex_internal.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\regex\regexec.c">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\getopt\getopt.c" />
-    <ClCompile Include="..\getopt\getopt1.c" />
-    <ClCompile Include="..\atacmdnames.cpp" />
-    <ClCompile Include="..\atacmds.cpp" />
-    <ClCompile Include="..\ataprint.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\cciss.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\dev_ata_cmd_set.cpp" />
-    <ClCompile Include="..\dev_interface.cpp" />
-    <ClCompile Include="..\dev_legacy.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\knowndrives.cpp" />
-    <ClCompile Include="..\os_darwin.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_freebsd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_generic.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_linux.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_netbsd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_openbsd.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_os2.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_qnxnto.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_solaris.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\os_win32.cpp" />
-    <ClCompile Include="..\scsiata.cpp" />
-    <ClCompile Include="..\scsicmds.cpp" />
-    <ClCompile Include="..\scsiprint.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\smartctl.cpp">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClCompile>
-    <ClCompile Include="..\smartd.cpp" />
-    <ClCompile Include="..\utility.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="daemon_win32.h" />
-    <ClInclude Include="hostname_win32.h" />
-    <ClInclude Include="syslog.h" />
-    <ClInclude Include="wbemcli_small.h" />
-    <ClInclude Include="wmiquery.h" />
-    <ClInclude Include="..\regex\regex.h" />
-    <ClInclude Include="..\regex\regex_internal.h" />
-    <ClInclude Include="..\getopt\getopt.h" />
-    <ClInclude Include="..\atacmdnames.h" />
-    <ClInclude Include="..\atacmds.h" />
-    <CustomBuildStep Include="..\ataprint.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\cciss.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <ClInclude Include="..\cissio_freebsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </ClInclude>
-    <CustomBuild Include="config_vc10.h">
-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Copy %(FullPath) $(IntDir)config.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy %(FullPath) $(IntDir)config.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)config.h;%(Outputs)</Outputs>
-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Copy %(FullPath) $(IntDir)config.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy %(FullPath) $(IntDir)config.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)config.h;%(Outputs)</Outputs>
-    </CustomBuild>
-    <ClInclude Include="..\csmisas.h" />
-    <ClInclude Include="..\dev_ata_cmd_set.h" />
-    <ClInclude Include="..\dev_interface.h" />
-    <ClInclude Include="..\dev_tunnelled.h" />
-    <ClInclude Include="..\drivedb.h" />
-    <ClInclude Include="..\int64.h" />
-    <ClInclude Include="..\knowndrives.h" />
-    <CustomBuildStep Include="..\megaraid.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_darwin.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_freebsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_generic.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_linux.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_netbsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_openbsd.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_os2.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_qnxnto.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\os_solaris.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <ClInclude Include="..\scsicmds.h" />
-    <CustomBuildStep Include="..\scsiprint.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuildStep Include="..\smartctl.h">
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
-      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
-    </CustomBuildStep>
-    <CustomBuild Include="svnversion_vc10.h">
-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Copy %(FullPath) $(IntDir)svnversion.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">copy %(FullPath) $(IntDir)svnversion.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)svnversion.h;%(Outputs)</Outputs>
-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Copy %(FullPath) $(IntDir)svnversion.h</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">copy %(FullPath) $(IntDir)svnversion.h
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)svnversion.h;%(Outputs)</Outputs>
-    </CustomBuild>
-    <ClInclude Include="..\utility.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="installer.nsi" />
-    <None Include="update-smart-drivedb.nsi" />
-    <None Include="..\AUTHORS" />
-    <None Include="..\autogen.sh" />
-    <None Include="..\CHANGELOG" />
-    <None Include="..\config.h.in" />
-    <None Include="..\configure.in" />
-    <None Include="..\do_release" />
-    <None Include="..\Doxyfile" />
-    <None Include="..\INSTALL" />
-    <None Include="..\Makefile.am" />
-    <None Include="..\NEWS" />
-    <None Include="..\README" />
-    <None Include="..\smartctl.8.in" />
-    <None Include="..\smartd.8.in" />
-    <None Include="..\smartd.conf.5.in" />
-    <None Include="..\smartd.initd.in" />
-    <None Include="..\TODO" />
-    <None Include="..\update-smart-drivedb.in" />
-    <None Include="..\WARNINGS" />
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/os_win32/smartd_vc10.vcxproj.filters b/os_win32/smartd_vc10.vcxproj.filters
deleted file mode 100644 (file)
index 0557738..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup>
-    <Filter Include="os_win32">
-      <UniqueIdentifier>{44bb110e-4d44-4d5e-8186-354210a8d3ba}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="regex">
-      <UniqueIdentifier>{fd3bb1d5-a72e-4f92-84a3-6eac97975ec7}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="getopt">
-      <UniqueIdentifier>{1d1b67d5-219f-4e86-a5ff-9d94f1f751f9}</UniqueIdentifier>
-    </Filter>
-  </ItemGroup>
-  <ItemGroup>
-    <ClCompile Include="daemon_win32.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="hostname_win32.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="syslog_win32.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="wmiquery.cpp">
-      <Filter>os_win32</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regcomp.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regex.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regex_internal.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\regex\regexec.c">
-      <Filter>regex</Filter>
-    </ClCompile>
-    <ClCompile Include="..\getopt\getopt.c">
-      <Filter>getopt</Filter>
-    </ClCompile>
-    <ClCompile Include="..\getopt\getopt1.c">
-      <Filter>getopt</Filter>
-    </ClCompile>
-    <ClCompile Include="..\atacmdnames.cpp" />
-    <ClCompile Include="..\atacmds.cpp" />
-    <ClCompile Include="..\ataprint.cpp" />
-    <ClCompile Include="..\cciss.cpp" />
-    <ClCompile Include="..\dev_ata_cmd_set.cpp" />
-    <ClCompile Include="..\dev_interface.cpp" />
-    <ClCompile Include="..\dev_legacy.cpp" />
-    <ClCompile Include="..\knowndrives.cpp" />
-    <ClCompile Include="..\os_darwin.cpp" />
-    <ClCompile Include="..\os_freebsd.cpp" />
-    <ClCompile Include="..\os_generic.cpp" />
-    <ClCompile Include="..\os_linux.cpp" />
-    <ClCompile Include="..\os_netbsd.cpp" />
-    <ClCompile Include="..\os_openbsd.cpp" />
-    <ClCompile Include="..\os_os2.cpp" />
-    <ClCompile Include="..\os_qnxnto.cpp" />
-    <ClCompile Include="..\os_solaris.cpp" />
-    <ClCompile Include="..\os_win32.cpp" />
-    <ClCompile Include="..\scsiata.cpp" />
-    <ClCompile Include="..\scsicmds.cpp" />
-    <ClCompile Include="..\scsiprint.cpp" />
-    <ClCompile Include="..\smartctl.cpp" />
-    <ClCompile Include="..\smartd.cpp" />
-    <ClCompile Include="..\utility.cpp" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="daemon_win32.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="hostname_win32.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="syslog.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="wbemcli_small.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="wmiquery.h">
-      <Filter>os_win32</Filter>
-    </ClInclude>
-    <ClInclude Include="..\regex\regex.h">
-      <Filter>regex</Filter>
-    </ClInclude>
-    <ClInclude Include="..\regex\regex_internal.h">
-      <Filter>regex</Filter>
-    </ClInclude>
-    <ClInclude Include="..\getopt\getopt.h">
-      <Filter>getopt</Filter>
-    </ClInclude>
-    <ClInclude Include="..\atacmdnames.h" />
-    <ClInclude Include="..\atacmds.h" />
-    <ClInclude Include="..\cissio_freebsd.h" />
-    <ClInclude Include="..\csmisas.h" />
-    <ClInclude Include="..\dev_ata_cmd_set.h" />
-    <ClInclude Include="..\dev_interface.h" />
-    <ClInclude Include="..\dev_tunnelled.h" />
-    <ClInclude Include="..\drivedb.h" />
-    <ClInclude Include="..\int64.h" />
-    <ClInclude Include="..\knowndrives.h" />
-    <ClInclude Include="..\scsicmds.h" />
-    <ClInclude Include="..\utility.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <None Include="installer.nsi">
-      <Filter>os_win32</Filter>
-    </None>
-    <None Include="update-smart-drivedb.nsi">
-      <Filter>os_win32</Filter>
-    </None>
-    <None Include="..\AUTHORS" />
-    <None Include="..\autogen.sh" />
-    <None Include="..\CHANGELOG" />
-    <None Include="..\config.h.in" />
-    <None Include="..\configure.in" />
-    <None Include="..\do_release" />
-    <None Include="..\Doxyfile" />
-    <None Include="..\INSTALL" />
-    <None Include="..\Makefile.am" />
-    <None Include="..\NEWS" />
-    <None Include="..\README" />
-    <None Include="..\smartctl.8.in" />
-    <None Include="..\smartd.8.in" />
-    <None Include="..\smartd.conf.5.in" />
-    <None Include="..\smartd.initd.in" />
-    <None Include="..\TODO" />
-    <None Include="..\update-smart-drivedb.in" />
-    <None Include="..\WARNINGS" />
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuildStep Include="..\ataprint.h" />
-    <CustomBuildStep Include="..\cciss.h" />
-    <CustomBuildStep Include="..\megaraid.h" />
-    <CustomBuildStep Include="..\os_darwin.h" />
-    <CustomBuildStep Include="..\os_freebsd.h" />
-    <CustomBuildStep Include="..\os_generic.h" />
-    <CustomBuildStep Include="..\os_linux.h" />
-    <CustomBuildStep Include="..\os_netbsd.h" />
-    <CustomBuildStep Include="..\os_openbsd.h" />
-    <CustomBuildStep Include="..\os_os2.h" />
-    <CustomBuildStep Include="..\os_qnxnto.h" />
-    <CustomBuildStep Include="..\os_solaris.h" />
-    <CustomBuildStep Include="..\scsiprint.h" />
-    <CustomBuildStep Include="..\smartctl.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuild Include="config_vc10.h" />
-    <CustomBuild Include="svnversion_vc10.h" />
-  </ItemGroup>
-</Project>
\ No newline at end of file
diff --git a/os_win32/smartd_warning.cmd b/os_win32/smartd_warning.cmd
new file mode 100644 (file)
index 0000000..a0eaa84
--- /dev/null
@@ -0,0 +1,159 @@
+@echo off
+::
+:: smartd warning script
+::
+:: Copyright (C) 2012-13 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: smartd_warning.cmd 3810 2013-04-18 20:08:39Z chrfranke $
+::
+
+set err=
+
+:: Parse options
+set dryrun=
+if "%1" == "--dryrun" (
+  set dryrun=t
+  shift
+)
+
+if not "%1" == "" (
+  echo smartd warning message script
+  echo.
+  echo Usage:
+  echo set SMARTD_MAILER='Path to external script, empty for "blat"'
+  echo set SMARTD_ADDRESS='Space separated mail adresses, empty if none'
+  echo set SMARTD_MESSAGE='Error Message'
+  echo set SMARTD_FAILTYPE='Type of failure, "EMailTest" for tests'
+  echo set SMARTD_TFIRST='Date of first message sent, empty if none'
+  echo :: set SMARTD_TFIRSTEPOCH='time_t format of above'
+  echo set SMARTD_PREVCNT='Number of previous messages, 0 if none'
+  echo set SMARTD_NEXTDAYS='Number of days until next message, empty if none'
+  echo set SMARTD_DEVICEINFO='Device identify information'
+  echo :: set SMARTD_DEVICE='Device name'
+  echo :: set SMARTD_DEVICESTRING='Annotated device name'
+  echo :: set SMARTD_DEVICETYPE='Device type from -d directive, "auto" if none'
+
+  echo smartd_warning.cmd [--dryrun]
+  goto EOF
+)
+
+if "%SMARTD_ADDRESS%%SMARTD_MAILER%" == "" (
+  echo smartd_warning.cmd: SMARTD_ADDRESS or SMARTD_MAILER must be set
+  goto EOF
+)
+
+:: USERDNSDOMAIN may be unset if running as service
+if "%USERDNSDOMAIN%" == "" (
+  for /f "delims== tokens=2 usebackq" %%d in (`WMIC PATH Win32_Computersystem WHERE "PartOfDomain=TRUE" GET Domain /VALUE 2^>nul ^| find "Domain=" 2^>nul`) do set USERDNSDOMAIN=%%~d
+)
+
+:: Format subject
+set SMARTD_SUBJECT=SMART error (%SMARTD_FAILTYPE%) detected on host: %COMPUTERNAME%
+
+:: Temp file for message
+if not "%TMP%" == "" set SMARTD_FULLMSGFILE=%TMP%\smartd_warning-%DATE%-%RANDOM%.txt
+if     "%TMP%" == "" set SMARTD_FULLMSGFILE=smartd_warning-%DATE%-%RANDOM%.txt
+
+:: Format message
+(
+  echo This message was generated by the smartd service running on:
+  echo.
+  echo.   host name:  %COMPUTERNAME%
+  if not "%USERDNSDOMAIN%" == "" echo.   DNS domain: %USERDNSDOMAIN%
+  if     "%USERDNSDOMAIN%" == "" echo.   DNS domain: [Empty]
+  if not "%USERDOMAIN%"    == "" echo.   Win domain: %USERDOMAIN%
+  echo.
+  echo The following warning/error was logged by the smartd service:
+  echo.
+  :: SMARTD_MESSAGE and SMARTD_DEVICEINFO may contain parentheses
+  for %%m in ("%SMARTD_MESSAGE%") do echo.%%~m
+  echo.
+  echo Device info:
+  for %%m in ("%SMARTD_DEVICEINFO%") do echo.%%~m
+  set m=
+  echo.
+  echo For details see the event log or log file of smartd.
+  if not "%SMARTD_FAILTYPE%" == "EmailTest" (
+    echo.
+    echo You can also use the smartctl utility for further investigation.
+    if not "%SMARTD_PREVCNT%" == "0" echo The original message about this issue was sent at %SMARTD_TFIRST%
+    if "%SMARTD_NEXTDAYS%" == "" (
+      echo No additional messages about this problem will be sent.
+    ) else ( if "%SMARTD_NEXTDAYS%" == "1" (
+      echo Another message will be sent in 24 hours if the problem persists.
+    ) else (
+      echo Another message will be sent in %SMARTD_NEXTDAYS% days if the problem persists.
+    ))
+  )
+) > "%SMARTD_FULLMSGFILE%"
+
+if not "%dryrun%" == "" (
+  echo %SMARTD_FULLMSGFILE%:
+  type "%SMARTD_FULLMSGFILE%"
+  echo --EOF--
+)
+
+:: Check first address
+set first=
+for /F "tokens=1*" %%a in ("%SMARTD_ADDRESS%") do (set first=%%a)
+set wtssend=
+if "%first%" == "console"   set wtssend=-c
+if "%first%" == "active"    set wtssend=-a
+if "%first%" == "connected" set wtssend=-s
+set first=
+
+if not "%wtssend%" == "" (
+  :: Show Message box(es) via WTSSendMessage()
+  if not "%dryrun%" == "" (
+    echo call wtssendmsg %wtssend% "%SMARTD_SUBJECT%" - ^< "%SMARTD_FULLMSGFILE%"
+  ) else (
+    call wtssendmsg %wtssend% "%SMARTD_SUBJECT%" - < "%SMARTD_FULLMSGFILE%"
+    if errorlevel 1 set err=t
+  )
+  :: Remove first address
+  for /F "tokens=1*" %%a in ("%SMARTD_ADDRESS%") do (set SMARTD_ADDRESS=%%b)
+)
+set wtssend=
+
+:: Make comma separated address list
+set SMARTD_ADDRCSV=
+if not "%SMARTD_ADDRESS%" == "" set SMARTD_ADDRCSV=%SMARTD_ADDRESS: =,%
+
+:: Use blat mailer by default
+if not "%SMARTD_ADDRESS%" == "" if "%SMARTD_MAILER%" == "" set SMARTD_MAILER=blat
+
+:: Send mail or run command
+if not "%SMARTD_ADDRCSV%" == "" (
+
+  :: Send mail
+  if not "%dryrun%" == "" (
+    echo call "%SMARTD_MAILER%" - -q -subject "%SMARTD_SUBJECT%" -to "%SMARTD_ADDRCSV%" ^< "%SMARTD_FULLMSGFILE%"
+  ) else (
+    call "%SMARTD_MAILER%" - -q -subject "%SMARTD_SUBJECT%" -to "%SMARTD_ADDRCSV%" < "%SMARTD_FULLMSGFILE%"
+    if errorlevel 1 set err=t
+  )
+
+) else ( if not "%SMARTD_MAILER%" == "" (
+
+  :: Run command
+  if not "%dryrun%" == "" (
+    echo call "%SMARTD_MAILER%" ^<nul
+  ) else (
+    call "%SMARTD_MAILER%" <nul
+    if errorlevel 1 set err=t
+  )
+
+))
+
+del "%SMARTD_FULLMSGFILE%" >nul 2>nul
+
+:EOF
+if not "%err%" == "" goto ERROR 2>nul
diff --git a/os_win32/smartmontools_vc10.sln b/os_win32/smartmontools_vc10.sln
deleted file mode 100644 (file)
index 0cc69fe..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 11.00
-# Visual C++ Express 2010
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smartctl", "smartctl_vc10.vcxproj", "{3AFEDCDD-D289-4543-A91D-EFBA6C710247}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smartd", "smartd_vc10.vcxproj", "{C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "syslogevt", "syslogevt_vc10.vcxproj", "{FAB7557B-86EA-405D-B49D-33AB3F4D3E33}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runcmd", "runcmd_vc10.vcxproj", "{11A4B619-D97B-499F-AF17-CF9F80BF70E8}"
-EndProject
-Global
-       GlobalSection(SolutionConfigurationPlatforms) = preSolution
-               Debug|Win32 = Debug|Win32
-               Release|Win32 = Release|Win32
-       EndGlobalSection
-       GlobalSection(ProjectConfigurationPlatforms) = postSolution
-               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Debug|Win32.ActiveCfg = Debug|Win32
-               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Debug|Win32.Build.0 = Debug|Win32
-               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Release|Win32.ActiveCfg = Release|Win32
-               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Release|Win32.Build.0 = Release|Win32
-               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Debug|Win32.ActiveCfg = Debug|Win32
-               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Debug|Win32.Build.0 = Debug|Win32
-               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Release|Win32.ActiveCfg = Release|Win32
-               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Release|Win32.Build.0 = Release|Win32
-               {FAB7557B-86EA-405D-B49D-33AB3F4D3E33}.Debug|Win32.ActiveCfg = Debug|Win32
-               {FAB7557B-86EA-405D-B49D-33AB3F4D3E33}.Debug|Win32.Build.0 = Debug|Win32
-               {FAB7557B-86EA-405D-B49D-33AB3F4D3E33}.Release|Win32.ActiveCfg = Release|Win32
-               {FAB7557B-86EA-405D-B49D-33AB3F4D3E33}.Release|Win32.Build.0 = Release|Win32
-               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Debug|Win32.ActiveCfg = Debug|Win32
-               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Debug|Win32.Build.0 = Debug|Win32
-               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Release|Win32.ActiveCfg = Release|Win32
-               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Release|Win32.Build.0 = Release|Win32
-       EndGlobalSection
-       GlobalSection(SolutionProperties) = preSolution
-               HideSolutionNode = FALSE
-       EndGlobalSection
-EndGlobal
index 6d1e64680aebe534bbb5a47914245c1289378693..3061d07705b7b32d920f8d800f438d310572b0ad 100644 (file)
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  */
 
 #ifndef SYSLOG_H
 #define SYSLOG_H
 
-#define SYSLOG_H_CVSID "$Id: syslog.h,v 1.6 2008/03/04 22:09:48 ballen4705 Exp $\n"
+#define SYSLOG_H_CVSID "$Id: syslog.h 3728 2012-12-13 17:57:50Z chrfranke $\n"
 
 #include <stdarg.h>
 
index 3099edfd7bdf82fc20f3cbbb5fcfd2fafa2a4e7b..02fa4de237fe964838c24d9036f8ee43608aad8c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2004-8 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2004-12 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
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  */
 
 // Win32 Emulation of syslog() for smartd
 // Writes to windows event log on NT4/2000/XP
 // (Register syslogevt.exe as event message file)
-// Writes to file "<ident>.log" on 9x/ME.
 // If facility is set to LOG_LOCAL[0-7], log is written to
 // file "<ident>.log", stdout, stderr, "<ident>[1-5].log".
 
@@ -35,8 +33,8 @@
 #define WIN32_LEAN_AND_MEAN
 #include <windows.h> // RegisterEventSourceA(), ReportEventA(), ...
 
-const char *syslog_win32_c_cvsid = "$Id: syslog_win32.cpp,v 1.8 2008/03/04 22:09:48 ballen4705 Exp $"
-SYSLOG_H_CVSID;
+const char *syslog_win32_cpp_cvsid = "$Id: syslog_win32.cpp 3575 2012-07-19 21:32:56Z chrfranke $"
+  SYSLOG_H_CVSID;
 
 #ifdef _MSC_VER
 // MSVC
@@ -350,12 +348,8 @@ void openlog(const char *ident, int logopt, int facility)
                // Cannot open => Use logfile
                long err = GetLastError();
                strcat(strcpy(sl_logpath, sl_ident), ".log");
-               if (GetVersion() & 0x80000000)
-                       fprintf(stderr, "%s: No event log on Win9x/ME, writing to %s\n",
-                               sl_ident, sl_logpath);
-               else
-                       fprintf(stderr, "%s: Cannot register event source (Error=%ld), writing to %s\n",
-                               sl_ident, err, sl_logpath);
+               fprintf(stderr, "%s: Cannot register event source (Error=%ld), writing to %s\n",
+                       sl_ident, err, sl_logpath);
        }
        else {
                // Start event log thread
diff --git a/os_win32/syslogevt.c b/os_win32/syslogevt.c
deleted file mode 100644 (file)
index 08019fe..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * os_win32/syslogevt.c
- *
- * Home page of code is: http://smartmontools.sourceforge.net
- *
- * Copyright (C) 2004-10 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, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-static char rcsid[] = "$Id: syslogevt.c 3257 2011-02-14 22:19:42Z manfred99 $";
-
-#include <stdio.h>
-#include <string.h>
-#include <process.h>
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-#include "syslogevt.h"
-// Compile time check for Message Ids, see also syslog_win32.cpp
-typedef assert_msg_syslog   [MSG_SYSLOG    ==  0 ? 1 : -1];
-typedef assert_msg_syslog_01[MSG_SYSLOG_01 ==  1 ? 1 : -1];
-typedef assert_msg_syslog_10[MSG_SYSLOG_10 == 10 ? 1 : -1];
-
-
-static int usage()
-{
-       puts(
-               "syslogevt $Revision: 3257 $ Copyright (C) 2004-10 Christian Franke\n"
-               "Home page is http://smartmontools.sourceforge.net/\n"
-               "\n"
-               "Usage: syslogevt [-ru] name [ident ...]\n"
-               "\n"
-               "Creates registry files \"name-r.reg\" and \"name-u.reg\" to (un)register\n"
-               "this program as an event message file for message source(s) \"ident\".\n"
-               "If \"ident\" is ommited, \"name\" is used. Options:\n"
-               "\n"
-               "    -r    run \"regedit name-r.reg\" after creating files\n"
-               "    -u    run \"regedit name-u.reg\" after creating files\n"
-               "\n"
-               "Examples:\n"
-               "\n"
-               "syslogevt smartd                     (Create smartd-r.reg and smartd-u.reg)\n"
-               "regedit smartd-r.reg           (Register syslogevt.exe for smartd messages)\n"
-               "\n"
-               "syslogevt -r smartd                             (Same as above in one step)\n"
-               "\n"
-               "regedit smartd-u.reg                                (Undo the registration)\n"
-               "\n"
-               "CAUTION: A registry entry of an existing event source with the same \"ident\"\n"
-               "         will be overwritten by regedit without notice."
-       );
-       return 1;
-}
-
-main(int argc, char ** argv)
-{
-       int regedit, a1, ai;
-       char name1[30+1], name2[30+1], mypath[MAX_PATH+1];
-       const char * ident;
-       FILE * f1, * f2;
-
-       if (argc < 2)
-               return usage();
-
-       a1 = 1;
-       regedit = 0;
-       if (!strcmp(argv[a1], "-r")) {
-               regedit = 1; a1++;
-       }
-       else if (!strcmp(argv[a1], "-u")) {
-               regedit = -1; a1++;
-       }
-
-       for (ai = a1; ai < argc; ai++) {
-               ident = argv[ai];
-               if (!(ident[0] && strlen(ident) < sizeof(name1)-10
-                         && strcspn(ident, "-.:/\\") == strlen(ident) )) {
-                       return usage();
-               }
-       }
-
-       if (!GetModuleFileName(NULL, mypath, sizeof(mypath)-1)) {
-               fputs("GetModuleFileName failed\n", stderr);
-               return 1;
-       }
-
-       ident = argv[a1];
-       strcpy(name1, ident); strcat(name1, "-r.reg");
-       strcpy(name2, ident); strcat(name2, "-u.reg");
-
-       if (!(f1 = fopen(name1, "w"))) {
-               perror(name1); return 1;
-       }
-       if (!(f2 = fopen(name2, "w"))) {
-               perror(name2); fclose(f1); unlink(name1); return 1;
-       }
-
-       fputs("REGEDIT4\n\n", f1);
-       fputs("REGEDIT4\n\n", f2);
-
-       for (ai = (argc > a1+1 ? a1+1 : a1); ai < argc; ai++) {
-               int i;
-               ident = argv[ai];
-               fputs("[HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\", f1);
-               fputs(ident, f1); fputs("]\n\"EventMessageFile\"=\"", f1);
-               for (i = 0; mypath[i]; i++) {
-                       if (mypath[i] == '\\')
-                               fputc('\\', f1);
-                       fputc(mypath[i], f1);
-               }
-               fputs("\"\n\"TypesSupported\"=dword:00000007\n\n", f1);
-
-               fputs("[-HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Eventlog\\Application\\", f2);
-               fputs(ident, f2); fputs("]\n\n", f2);
-       }
-
-       fclose(f1);
-       fclose(f2);
-
-       if (GetVersion() & 0x80000000) {
-               puts("Warning: Event log not supported on Win9x/ME\n");
-               if (regedit)
-                       return 1;
-       }
-
-       if (regedit) {
-               if (spawnlp(P_WAIT, "regedit", "regedit", (regedit > 0 ? name1 : name2), (const char *)0) == -1) {
-                       fputs("regedit: cannot execute\n", stderr);
-                       return 1;
-               }
-       }
-       else {
-               fputs("Files generated. Use\n\n    regedit ", stdout);
-               puts(name1);
-               fputs("\nto register event message file, and\n\n    regedit ", stdout);
-               puts(name2);
-               fputs("\nto remove registration later.\n\n"
-                         "Do not remove this program when registered.\n", stdout);
-       }
-
-       return 0;
-}
index c477ec668f9f83528ba7fae335bcfb3194744d83..c6d3ac6a0e52e771c0c859bac10dd66cb5511698 100644 (file)
 ; * any later version.
 ; *
 ; * You should have received a copy of the GNU General Public License
-; * (for example COPYING); if not, write to the Free
-; * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+; * (for example COPYING); if not, write to the Free Software Foundation,
+; * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 ; *
 ; */
 ;
-;// $Id: syslogevt.mc 3166 2010-09-24 19:43:31Z chrfranke $
+;// $Id: syslogevt.mc 3727 2012-12-13 17:23:06Z samm2 $
 ;
 ;// Use message compiler "mc" or "windmc" to generate
 ;//   syslogevt.rc, syslogevt.h, msg00001.bin
diff --git a/os_win32/syslogevt_vc10.vcxproj b/os_win32/syslogevt_vc10.vcxproj
deleted file mode 100644 (file)
index 8654915..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
-  <ItemGroup Label="ProjectConfigurations">
-    <ProjectConfiguration Include="Debug|Win32">
-      <Configuration>Debug</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-    <ProjectConfiguration Include="Release|Win32">
-      <Configuration>Release</Configuration>
-      <Platform>Win32</Platform>
-    </ProjectConfiguration>
-  </ItemGroup>
-  <PropertyGroup Label="Globals">
-    <ProjectGuid>{FAB7557B-86EA-405D-B49D-33AB3F4D3E33}</ProjectGuid>
-    <RootNamespace>syslogevt</RootNamespace>
-    <Keyword>Win32Proj</Keyword>
-    <ProjectName>syslogevt</ProjectName>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-    <WholeProgramOptimization>true</WholeProgramOptimization>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
-    <ConfigurationType>Application</ConfigurationType>
-    <CharacterSet>MultiByte</CharacterSet>
-  </PropertyGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
-  <ImportGroup Label="ExtensionSettings">
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
-  </ImportGroup>
-  <PropertyGroup Label="UserMacros" />
-  <PropertyGroup>
-    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">syslogevt_vc10.d\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">syslogevt_vc10.d\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
-    <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\</OutDir>
-    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">syslogevt_vc10.r\</IntDir>
-    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <ClCompile>
-      <Optimization>Disabled</Optimization>
-      <PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <MinimalRebuild>true</MinimalRebuild>
-      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
-      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
-    </ClCompile>
-    <Link>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <SubSystem>Console</SubSystem>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <ClCompile>
-      <PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
-      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
-      <PrecompiledHeader>
-      </PrecompiledHeader>
-      <WarningLevel>Level3</WarningLevel>
-      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
-    </ClCompile>
-    <Link>
-      <OutputFile>syslogevt.exe</OutputFile>
-      <GenerateDebugInformation>true</GenerateDebugInformation>
-      <ProgramDatabaseFile>$(IntDir)$(TargetName).pdb</ProgramDatabaseFile>
-      <SubSystem>Console</SubSystem>
-      <OptimizeReferences>true</OptimizeReferences>
-      <EnableCOMDATFolding>true</EnableCOMDATFolding>
-      <TargetMachine>MachineX86</TargetMachine>
-    </Link>
-  </ItemDefinitionGroup>
-  <ItemGroup>
-    <ClCompile Include="syslogevt.c" />
-  </ItemGroup>
-  <ItemGroup>
-    <CustomBuild Include="syslogevt.mc">
-      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc -r $(IntDir) syslogevt.mc</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc -r $(IntDir) syslogevt.mc
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)syslogevt.rc;$(IntDir)msg00001.bin;syslogevt.h;%(Outputs)</Outputs>
-      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc -r $(IntDir) syslogevt.mc</Message>
-      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc -r $(IntDir) syslogevt.mc
-</Command>
-      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)syslogevt.rc;$(IntDir)msg00001.bin;syslogevt.h;%(Outputs)</Outputs>
-    </CustomBuild>
-  </ItemGroup>
-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
-  <ImportGroup Label="ExtensionTargets">
-  </ImportGroup>
-</Project>
\ No newline at end of file
diff --git a/os_win32/vc10/runcmd.vcxproj b/os_win32/vc10/runcmd.vcxproj
new file mode 100644 (file)
index 0000000..36a294e
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{11A4B619-D97B-499F-AF17-CF9F80BF70E8}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>runcmd</RootNamespace>
+    <ProjectName>runcmd</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName).tmp\</IntDir>
+    <TargetName>$(ProjectName)u</TargetName>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName).tmp\</IntDir>
+    <TargetName>$(ProjectName)u</TargetName>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\runcmd.c" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/os_win32/vc10/smartctl.vcxproj b/os_win32/vc10/smartctl.vcxproj
new file mode 100644 (file)
index 0000000..20e0b18
--- /dev/null
@@ -0,0 +1,291 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{3AFEDCDD-D289-4543-A91D-EFBA6C710247}</ProjectGuid>
+    <RootNamespace>smartctl</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectName>smartctl</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\$(ProjectName).tmp\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\$(ProjectName).tmp\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..\..\getopt;..\..\regex;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_DEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..\..\getopt;..\..\regex;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>NDEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\ataidentify.cpp" />
+    <ClCompile Include="..\..\dev_areca.cpp" />
+    <ClCompile Include="..\daemon_win32.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\syslog_win32.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\wmiquery.cpp" />
+    <ClCompile Include="..\..\regex\regcomp.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regex.c" />
+    <ClCompile Include="..\..\regex\regex_internal.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regexec.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\getopt\getopt.c" />
+    <ClCompile Include="..\..\getopt\getopt1.c" />
+    <ClCompile Include="..\..\atacmdnames.cpp" />
+    <ClCompile Include="..\..\atacmds.cpp" />
+    <ClCompile Include="..\..\ataprint.cpp" />
+    <ClCompile Include="..\..\cciss.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\dev_ata_cmd_set.cpp" />
+    <ClCompile Include="..\..\dev_interface.cpp" />
+    <ClCompile Include="..\..\dev_legacy.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\knowndrives.cpp" />
+    <ClCompile Include="..\..\os_darwin.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_freebsd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_generic.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_linux.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_netbsd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_openbsd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_os2.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_qnxnto.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_solaris.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_win32.cpp" />
+    <ClCompile Include="..\..\scsiata.cpp" />
+    <ClCompile Include="..\..\scsicmds.cpp" />
+    <ClCompile Include="..\..\scsiprint.cpp" />
+    <ClCompile Include="..\..\smartctl.cpp" />
+    <ClCompile Include="..\..\smartd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\utility.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\ataidentify.h" />
+    <ClInclude Include="..\..\dev_areca.h" />
+    <ClInclude Include="config.h" />
+    <ClInclude Include="svnversion.h" />
+    <CustomBuildStep Include="..\daemon_win32.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\syslog.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <ClInclude Include="..\wbemcli_small.h" />
+    <ClInclude Include="..\wmiquery.h" />
+    <ClInclude Include="..\..\regex\regex.h" />
+    <ClInclude Include="..\..\regex\regex_internal.h" />
+    <ClInclude Include="..\..\getopt\getopt.h" />
+    <ClInclude Include="..\..\atacmdnames.h" />
+    <ClInclude Include="..\..\atacmds.h" />
+    <ClInclude Include="..\..\ataprint.h" />
+    <CustomBuildStep Include="..\..\cciss.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <ClInclude Include="..\..\cissio_freebsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClInclude>
+    <ClInclude Include="..\..\csmisas.h" />
+    <ClInclude Include="..\..\dev_ata_cmd_set.h" />
+    <ClInclude Include="..\..\dev_interface.h" />
+    <ClInclude Include="..\..\dev_tunnelled.h" />
+    <ClInclude Include="..\..\drivedb.h" />
+    <ClInclude Include="..\..\int64.h" />
+    <ClInclude Include="..\..\knowndrives.h" />
+    <CustomBuildStep Include="..\..\megaraid.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_darwin.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_freebsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_generic.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_linux.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_netbsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_openbsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_os2.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_qnxnto.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_solaris.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <ClInclude Include="..\..\scsicmds.h" />
+    <ClInclude Include="..\..\scsiprint.h" />
+    <ClInclude Include="..\..\smartctl.h" />
+    <ClInclude Include="..\..\utility.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\..\smartd_warning.sh.in" />
+    <None Include="..\installer.nsi" />
+    <None Include="..\smartctl_res.rc.in" />
+    <None Include="..\smartd_res.rc.in" />
+    <None Include="..\smartd_warning.cmd" />
+    <None Include="..\syslogevt.mc" />
+    <None Include="..\update-smart-drivedb.nsi" />
+    <None Include="..\..\AUTHORS" />
+    <None Include="..\..\autogen.sh" />
+    <None Include="..\..\ChangeLog" />
+    <None Include="..\..\config.h.in" />
+    <None Include="..\..\configure.ac" />
+    <None Include="..\..\do_release" />
+    <None Include="..\..\Doxyfile" />
+    <None Include="..\..\INSTALL" />
+    <None Include="..\..\Makefile.am" />
+    <None Include="..\..\NEWS" />
+    <None Include="..\..\README" />
+    <None Include="..\..\smartctl.8.in" />
+    <None Include="..\..\smartd.8.in" />
+    <None Include="..\..\smartd.conf.5.in" />
+    <None Include="..\..\smartd.initd.in" />
+    <None Include="..\..\TODO" />
+    <None Include="..\..\update-smart-drivedb.in" />
+    <None Include="..\..\WARNINGS" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="smartctl_res.rc" />
+    <ResourceCompile Include="smartd_res.rc">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ResourceCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/os_win32/vc10/smartctl.vcxproj.filters b/os_win32/vc10/smartctl.vcxproj.filters
new file mode 100644 (file)
index 0000000..be8a021
--- /dev/null
@@ -0,0 +1,171 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="os_win32">
+      <UniqueIdentifier>{9321e988-dd03-496d-9933-7c8b235a46bf}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="regex">
+      <UniqueIdentifier>{bfbfd4ea-fae3-45ec-9cfb-c5424218c47c}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="getopt">
+      <UniqueIdentifier>{8ff0bf5f-c96e-45c3-bcb4-7450cecfa0d4}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\daemon_win32.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
+    <ClCompile Include="..\syslog_win32.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
+    <ClCompile Include="..\wmiquery.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regcomp.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regex.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regex_internal.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regexec.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\getopt\getopt.c">
+      <Filter>getopt</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\getopt\getopt1.c">
+      <Filter>getopt</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\atacmdnames.cpp" />
+    <ClCompile Include="..\..\atacmds.cpp" />
+    <ClCompile Include="..\..\ataprint.cpp" />
+    <ClCompile Include="..\..\cciss.cpp" />
+    <ClCompile Include="..\..\dev_ata_cmd_set.cpp" />
+    <ClCompile Include="..\..\dev_interface.cpp" />
+    <ClCompile Include="..\..\dev_legacy.cpp" />
+    <ClCompile Include="..\..\knowndrives.cpp" />
+    <ClCompile Include="..\..\os_darwin.cpp" />
+    <ClCompile Include="..\..\os_freebsd.cpp" />
+    <ClCompile Include="..\..\os_generic.cpp" />
+    <ClCompile Include="..\..\os_linux.cpp" />
+    <ClCompile Include="..\..\os_netbsd.cpp" />
+    <ClCompile Include="..\..\os_openbsd.cpp" />
+    <ClCompile Include="..\..\os_os2.cpp" />
+    <ClCompile Include="..\..\os_qnxnto.cpp" />
+    <ClCompile Include="..\..\os_solaris.cpp" />
+    <ClCompile Include="..\..\os_win32.cpp" />
+    <ClCompile Include="..\..\scsiata.cpp" />
+    <ClCompile Include="..\..\scsicmds.cpp" />
+    <ClCompile Include="..\..\scsiprint.cpp" />
+    <ClCompile Include="..\..\smartctl.cpp" />
+    <ClCompile Include="..\..\smartd.cpp" />
+    <ClCompile Include="..\..\utility.cpp" />
+    <ClCompile Include="..\..\ataidentify.cpp" />
+    <ClCompile Include="..\..\dev_areca.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\wbemcli_small.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
+    <ClInclude Include="..\wmiquery.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\regex\regex.h">
+      <Filter>regex</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\regex\regex_internal.h">
+      <Filter>regex</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\getopt\getopt.h">
+      <Filter>getopt</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\atacmdnames.h" />
+    <ClInclude Include="..\..\atacmds.h" />
+    <ClInclude Include="..\..\ataprint.h" />
+    <ClInclude Include="..\..\cissio_freebsd.h" />
+    <ClInclude Include="..\..\csmisas.h" />
+    <ClInclude Include="..\..\dev_ata_cmd_set.h" />
+    <ClInclude Include="..\..\dev_interface.h" />
+    <ClInclude Include="..\..\dev_tunnelled.h" />
+    <ClInclude Include="..\..\drivedb.h" />
+    <ClInclude Include="..\..\int64.h" />
+    <ClInclude Include="..\..\knowndrives.h" />
+    <ClInclude Include="..\..\scsicmds.h" />
+    <ClInclude Include="..\..\scsiprint.h" />
+    <ClInclude Include="..\..\smartctl.h" />
+    <ClInclude Include="..\..\utility.h" />
+    <ClInclude Include="..\..\ataidentify.h" />
+    <ClInclude Include="..\..\dev_areca.h" />
+    <ClInclude Include="config.h" />
+    <ClInclude Include="svnversion.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\installer.nsi">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\update-smart-drivedb.nsi">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\..\AUTHORS" />
+    <None Include="..\..\autogen.sh" />
+    <None Include="..\..\ChangeLog" />
+    <None Include="..\..\config.h.in" />
+    <None Include="..\..\configure.ac" />
+    <None Include="..\..\do_release" />
+    <None Include="..\..\Doxyfile" />
+    <None Include="..\..\INSTALL" />
+    <None Include="..\..\Makefile.am" />
+    <None Include="..\..\NEWS" />
+    <None Include="..\..\README" />
+    <None Include="..\..\smartctl.8.in" />
+    <None Include="..\..\smartd.8.in" />
+    <None Include="..\..\smartd.conf.5.in" />
+    <None Include="..\..\smartd.initd.in" />
+    <None Include="..\..\TODO" />
+    <None Include="..\..\update-smart-drivedb.in" />
+    <None Include="..\..\WARNINGS" />
+    <None Include="..\smartd_warning.cmd">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\..\smartd_warning.sh.in" />
+    <None Include="..\smartctl_res.rc.in">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\smartd_res.rc.in">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\syslogevt.mc">
+      <Filter>os_win32</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <CustomBuildStep Include="..\daemon_win32.h">
+      <Filter>os_win32</Filter>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\syslog.h">
+      <Filter>os_win32</Filter>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\cciss.h" />
+    <CustomBuildStep Include="..\..\megaraid.h" />
+    <CustomBuildStep Include="..\..\os_darwin.h" />
+    <CustomBuildStep Include="..\..\os_freebsd.h" />
+    <CustomBuildStep Include="..\..\os_generic.h" />
+    <CustomBuildStep Include="..\..\os_linux.h" />
+    <CustomBuildStep Include="..\..\os_netbsd.h" />
+    <CustomBuildStep Include="..\..\os_openbsd.h" />
+    <CustomBuildStep Include="..\..\os_os2.h" />
+    <CustomBuildStep Include="..\..\os_qnxnto.h" />
+    <CustomBuildStep Include="..\..\os_solaris.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="smartctl_res.rc">
+      <Filter>os_win32</Filter>
+    </ResourceCompile>
+    <ResourceCompile Include="smartd_res.rc">
+      <Filter>os_win32</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/os_win32/vc10/smartd.vcxproj b/os_win32/vc10/smartd.vcxproj
new file mode 100644 (file)
index 0000000..75304c7
--- /dev/null
@@ -0,0 +1,311 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}</ProjectGuid>
+    <RootNamespace>smartd</RootNamespace>
+    <Keyword>Win32Proj</Keyword>
+    <ProjectName>smartd</ProjectName>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\$(ProjectName).tmp\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+    <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\$(ProjectName).tmp\</IntDir>
+    <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <Optimization>Disabled</Optimization>
+      <AdditionalIncludeDirectories>.;..;..\..\getopt;..\..\regex;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>_DEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <MinimalRebuild>true</MinimalRebuild>
+      <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+      <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>.;..;..\..\getopt;..\..\regex;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>NDEBUG;HAVE_CONFIG_H;_USE_32BIT_TIME_T;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+      <DisableSpecificWarnings>4250</DisableSpecificWarnings>
+    </ClCompile>
+    <Link>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <SubSystem>Console</SubSystem>
+      <OptimizeReferences>true</OptimizeReferences>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <TargetMachine>MachineX86</TargetMachine>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\ataidentify.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\dev_areca.cpp" />
+    <ClCompile Include="..\daemon_win32.cpp" />
+    <ClCompile Include="..\syslog_win32.cpp" />
+    <ClCompile Include="..\wmiquery.cpp" />
+    <ClCompile Include="..\..\regex\regcomp.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regex.c" />
+    <ClCompile Include="..\..\regex\regex_internal.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regexec.c">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\getopt\getopt.c" />
+    <ClCompile Include="..\..\getopt\getopt1.c" />
+    <ClCompile Include="..\..\atacmdnames.cpp" />
+    <ClCompile Include="..\..\atacmds.cpp" />
+    <ClCompile Include="..\..\ataprint.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\cciss.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\dev_ata_cmd_set.cpp" />
+    <ClCompile Include="..\..\dev_interface.cpp" />
+    <ClCompile Include="..\..\dev_legacy.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\knowndrives.cpp" />
+    <ClCompile Include="..\..\os_darwin.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_freebsd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_generic.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_linux.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_netbsd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_openbsd.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_os2.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_qnxnto.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_solaris.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\os_win32.cpp" />
+    <ClCompile Include="..\..\scsiata.cpp" />
+    <ClCompile Include="..\..\scsicmds.cpp" />
+    <ClCompile Include="..\..\scsiprint.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\smartctl.cpp">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClCompile>
+    <ClCompile Include="..\..\smartd.cpp" />
+    <ClCompile Include="..\..\utility.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\ataidentify.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClInclude>
+    <ClInclude Include="..\..\dev_areca.h" />
+    <ClInclude Include="..\daemon_win32.h" />
+    <ClInclude Include="..\syslog.h" />
+    <ClInclude Include="..\wbemcli_small.h" />
+    <ClInclude Include="..\wmiquery.h" />
+    <ClInclude Include="..\..\regex\regex.h" />
+    <ClInclude Include="..\..\regex\regex_internal.h" />
+    <ClInclude Include="..\..\getopt\getopt.h" />
+    <ClInclude Include="..\..\atacmdnames.h" />
+    <ClInclude Include="..\..\atacmds.h" />
+    <ClInclude Include="config.h" />
+    <ClInclude Include="svnversion.h" />
+    <CustomBuildStep Include="..\..\ataprint.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\cciss.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <ClInclude Include="..\..\cissio_freebsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ClInclude>
+    <ClInclude Include="..\..\csmisas.h" />
+    <ClInclude Include="..\..\dev_ata_cmd_set.h" />
+    <ClInclude Include="..\..\dev_interface.h" />
+    <ClInclude Include="..\..\dev_tunnelled.h" />
+    <ClInclude Include="..\..\drivedb.h" />
+    <ClInclude Include="..\..\int64.h" />
+    <ClInclude Include="..\..\knowndrives.h" />
+    <CustomBuildStep Include="..\..\megaraid.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_darwin.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_freebsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_generic.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_linux.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_netbsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_openbsd.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_os2.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_qnxnto.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\os_solaris.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <ClInclude Include="..\..\scsicmds.h" />
+    <CustomBuildStep Include="..\..\scsiprint.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <CustomBuildStep Include="..\..\smartctl.h">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </CustomBuildStep>
+    <ClInclude Include="..\..\utility.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\..\smartd_warning.sh.in" />
+    <None Include="..\installer.nsi" />
+    <None Include="..\smartctl_res.rc.in" />
+    <None Include="..\smartd_res.rc.in" />
+    <None Include="..\smartd_warning.cmd" />
+    <CustomBuild Include="..\syslogevt.mc">
+      <FileType>Document</FileType>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc -r $(IntDir) ..\syslogevt.mc</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">mc -r $(IntDir) ..\syslogevt.mc</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)syslogevt.rc;$(IntDir)msg00001.bin;syslogevt.h;%(Outputs)</Outputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc -r $(IntDir) ..\syslogevt.mc</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">mc -r $(IntDir) ..\syslogevt.mc</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)syslogevt.rc;$(IntDir)msg00001.bin;syslogevt.h;%(Outputs)</Outputs>
+    </CustomBuild>
+    <None Include="..\update-smart-drivedb.nsi" />
+    <None Include="..\..\AUTHORS" />
+    <None Include="..\..\autogen.sh" />
+    <None Include="..\..\ChangeLog" />
+    <None Include="..\..\config.h.in" />
+    <None Include="..\..\configure.ac" />
+    <None Include="..\..\do_release" />
+    <None Include="..\..\Doxyfile" />
+    <None Include="..\..\INSTALL" />
+    <None Include="..\..\Makefile.am" />
+    <None Include="..\..\NEWS" />
+    <None Include="..\..\README" />
+    <None Include="..\..\smartctl.8.in" />
+    <None Include="..\..\smartd.8.in" />
+    <None Include="..\..\smartd.conf.5.in" />
+    <None Include="..\..\smartd.initd.in" />
+    <None Include="..\..\TODO" />
+    <None Include="..\..\update-smart-drivedb.in" />
+    <None Include="..\..\WARNINGS" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="smartctl_res.rc">
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
+    </ResourceCompile>
+    <ResourceCompile Include="smartd_res.rc">
+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)</AdditionalIncludeDirectories>
+      <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(IntDir)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
diff --git a/os_win32/vc10/smartd.vcxproj.filters b/os_win32/vc10/smartd.vcxproj.filters
new file mode 100644 (file)
index 0000000..910d829
--- /dev/null
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="os_win32">
+      <UniqueIdentifier>{44bb110e-4d44-4d5e-8186-354210a8d3ba}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="regex">
+      <UniqueIdentifier>{fd3bb1d5-a72e-4f92-84a3-6eac97975ec7}</UniqueIdentifier>
+    </Filter>
+    <Filter Include="getopt">
+      <UniqueIdentifier>{1d1b67d5-219f-4e86-a5ff-9d94f1f751f9}</UniqueIdentifier>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\daemon_win32.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
+    <ClCompile Include="..\syslog_win32.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
+    <ClCompile Include="..\wmiquery.cpp">
+      <Filter>os_win32</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regcomp.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regex.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regex_internal.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\regex\regexec.c">
+      <Filter>regex</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\getopt\getopt.c">
+      <Filter>getopt</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\getopt\getopt1.c">
+      <Filter>getopt</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\atacmdnames.cpp" />
+    <ClCompile Include="..\..\atacmds.cpp" />
+    <ClCompile Include="..\..\ataprint.cpp" />
+    <ClCompile Include="..\..\cciss.cpp" />
+    <ClCompile Include="..\..\dev_ata_cmd_set.cpp" />
+    <ClCompile Include="..\..\dev_interface.cpp" />
+    <ClCompile Include="..\..\dev_legacy.cpp" />
+    <ClCompile Include="..\..\knowndrives.cpp" />
+    <ClCompile Include="..\..\os_darwin.cpp" />
+    <ClCompile Include="..\..\os_freebsd.cpp" />
+    <ClCompile Include="..\..\os_generic.cpp" />
+    <ClCompile Include="..\..\os_linux.cpp" />
+    <ClCompile Include="..\..\os_netbsd.cpp" />
+    <ClCompile Include="..\..\os_openbsd.cpp" />
+    <ClCompile Include="..\..\os_os2.cpp" />
+    <ClCompile Include="..\..\os_qnxnto.cpp" />
+    <ClCompile Include="..\..\os_solaris.cpp" />
+    <ClCompile Include="..\..\os_win32.cpp" />
+    <ClCompile Include="..\..\scsiata.cpp" />
+    <ClCompile Include="..\..\scsicmds.cpp" />
+    <ClCompile Include="..\..\scsiprint.cpp" />
+    <ClCompile Include="..\..\smartctl.cpp" />
+    <ClCompile Include="..\..\smartd.cpp" />
+    <ClCompile Include="..\..\utility.cpp" />
+    <ClCompile Include="..\..\ataidentify.cpp" />
+    <ClCompile Include="..\..\dev_areca.cpp" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\daemon_win32.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
+    <ClInclude Include="..\syslog.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
+    <ClInclude Include="..\wbemcli_small.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
+    <ClInclude Include="..\wmiquery.h">
+      <Filter>os_win32</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\regex\regex.h">
+      <Filter>regex</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\regex\regex_internal.h">
+      <Filter>regex</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\getopt\getopt.h">
+      <Filter>getopt</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\atacmdnames.h" />
+    <ClInclude Include="..\..\atacmds.h" />
+    <ClInclude Include="..\..\cissio_freebsd.h" />
+    <ClInclude Include="..\..\csmisas.h" />
+    <ClInclude Include="..\..\dev_ata_cmd_set.h" />
+    <ClInclude Include="..\..\dev_interface.h" />
+    <ClInclude Include="..\..\dev_tunnelled.h" />
+    <ClInclude Include="..\..\drivedb.h" />
+    <ClInclude Include="..\..\int64.h" />
+    <ClInclude Include="..\..\knowndrives.h" />
+    <ClInclude Include="..\..\scsicmds.h" />
+    <ClInclude Include="..\..\utility.h" />
+    <ClInclude Include="..\..\ataidentify.h" />
+    <ClInclude Include="..\..\dev_areca.h" />
+    <ClInclude Include="config.h" />
+    <ClInclude Include="svnversion.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\installer.nsi">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\update-smart-drivedb.nsi">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\..\AUTHORS" />
+    <None Include="..\..\autogen.sh" />
+    <None Include="..\..\ChangeLog" />
+    <None Include="..\..\config.h.in" />
+    <None Include="..\..\configure.ac" />
+    <None Include="..\..\do_release" />
+    <None Include="..\..\Doxyfile" />
+    <None Include="..\..\INSTALL" />
+    <None Include="..\..\Makefile.am" />
+    <None Include="..\..\NEWS" />
+    <None Include="..\..\README" />
+    <None Include="..\..\smartctl.8.in" />
+    <None Include="..\..\smartd.8.in" />
+    <None Include="..\..\smartd.conf.5.in" />
+    <None Include="..\..\smartd.initd.in" />
+    <None Include="..\..\TODO" />
+    <None Include="..\..\update-smart-drivedb.in" />
+    <None Include="..\..\WARNINGS" />
+    <None Include="..\smartd_warning.cmd">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\..\smartd_warning.sh.in" />
+    <None Include="..\smartctl_res.rc.in">
+      <Filter>os_win32</Filter>
+    </None>
+    <None Include="..\smartd_res.rc.in">
+      <Filter>os_win32</Filter>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <CustomBuildStep Include="..\..\ataprint.h" />
+    <CustomBuildStep Include="..\..\cciss.h" />
+    <CustomBuildStep Include="..\..\megaraid.h" />
+    <CustomBuildStep Include="..\..\os_darwin.h" />
+    <CustomBuildStep Include="..\..\os_freebsd.h" />
+    <CustomBuildStep Include="..\..\os_generic.h" />
+    <CustomBuildStep Include="..\..\os_linux.h" />
+    <CustomBuildStep Include="..\..\os_netbsd.h" />
+    <CustomBuildStep Include="..\..\os_openbsd.h" />
+    <CustomBuildStep Include="..\..\os_os2.h" />
+    <CustomBuildStep Include="..\..\os_qnxnto.h" />
+    <CustomBuildStep Include="..\..\os_solaris.h" />
+    <CustomBuildStep Include="..\..\scsiprint.h" />
+    <CustomBuildStep Include="..\..\smartctl.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="smartctl_res.rc">
+      <Filter>os_win32</Filter>
+    </ResourceCompile>
+    <ResourceCompile Include="smartd_res.rc">
+      <Filter>os_win32</Filter>
+    </ResourceCompile>
+  </ItemGroup>
+  <ItemGroup>
+    <CustomBuild Include="..\syslogevt.mc">
+      <Filter>os_win32</Filter>
+    </CustomBuild>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/os_win32/vc10/smartmontools.sln b/os_win32/vc10/smartmontools.sln
new file mode 100644 (file)
index 0000000..c6530b4
--- /dev/null
@@ -0,0 +1,38 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C++ Express 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smartctl", "smartctl.vcxproj", "{3AFEDCDD-D289-4543-A91D-EFBA6C710247}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "smartd", "smartd.vcxproj", "{C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "runcmd", "runcmd.vcxproj", "{11A4B619-D97B-499F-AF17-CF9F80BF70E8}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wtssendmsg", "wtssendmsg.vcxproj", "{0B6B7D19-07AE-41DD-B70E-2F74362A4EC0}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Debug|Win32 = Debug|Win32
+               Release|Win32 = Release|Win32
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Debug|Win32.ActiveCfg = Debug|Win32
+               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Debug|Win32.Build.0 = Debug|Win32
+               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Release|Win32.ActiveCfg = Release|Win32
+               {3AFEDCDD-D289-4543-A91D-EFBA6C710247}.Release|Win32.Build.0 = Release|Win32
+               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Debug|Win32.ActiveCfg = Debug|Win32
+               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Debug|Win32.Build.0 = Debug|Win32
+               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Release|Win32.ActiveCfg = Release|Win32
+               {C0762191-C2AC-40B6-A2EB-F1658BBDC4C6}.Release|Win32.Build.0 = Release|Win32
+               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Debug|Win32.ActiveCfg = Debug|Win32
+               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Debug|Win32.Build.0 = Debug|Win32
+               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Release|Win32.ActiveCfg = Release|Win32
+               {11A4B619-D97B-499F-AF17-CF9F80BF70E8}.Release|Win32.Build.0 = Release|Win32
+               {0B6B7D19-07AE-41DD-B70E-2F74362A4EC0}.Debug|Win32.ActiveCfg = Debug|Win32
+               {0B6B7D19-07AE-41DD-B70E-2F74362A4EC0}.Debug|Win32.Build.0 = Debug|Win32
+               {0B6B7D19-07AE-41DD-B70E-2F74362A4EC0}.Release|Win32.ActiveCfg = Release|Win32
+               {0B6B7D19-07AE-41DD-B70E-2F74362A4EC0}.Release|Win32.Build.0 = Release|Win32
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/os_win32/vc10/wtssendmsg.vcxproj b/os_win32/vc10/wtssendmsg.vcxproj
new file mode 100644 (file)
index 0000000..92e143a
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\wtssendmsg.c" />
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{0B6B7D19-07AE-41DD-B70E-2F74362A4EC0}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>wtssendmsg</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>Application</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName).tmp\</IntDir>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IntDir>$(Configuration)\$(ProjectName).tmp\</IntDir>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>_DEBUG;_CRT_NONSTDC_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>NDEBUG;_CRT_NONSTDC_NO_WARNINGS;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Console</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>wtsapi32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+  </ItemDefinitionGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
\ No newline at end of file
index 5181f92df30e14a84a7322631e2034688fc12fa0..ade992d4ebf4e8b3d3679022910589d8d738da1b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Home page of code is: http://smartmontools.sourceforge.net
  *
- * Copyright (C) 2011 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2011-13 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
@@ -23,7 +23,7 @@
 
 #include <stdio.h>
 
-const char * wmiquery_cpp_cvsid = "$Id: wmiquery.cpp 3243 2011-01-19 20:03:47Z chrfranke $"
+const char * wmiquery_cpp_cvsid = "$Id: wmiquery.cpp 3802 2013-03-24 18:36:21Z chrfranke $"
   WMIQUERY_H_CVSID;
 
 
@@ -67,7 +67,7 @@ std::string wbem_object::get_str(const char * name) /*const*/
     return s;
 
   VARIANT var; VariantInit(&var);
-  if (m_intf->Get(com_bstr(name), 0L, &var, (CIMTYPE*)0, (long*)0) /* != WBEM_S_NO_ERROR */)
+  if (m_intf->Get(com_bstr(name), 0L, &var, (CIMTYPE*)0, (LPLONG)0) /* != WBEM_S_NO_ERROR */)
     return s;
 
   if (var.vt == VT_BSTR)
diff --git a/os_win32/wtssendmsg.c b/os_win32/wtssendmsg.c
new file mode 100644 (file)
index 0000000..3298dfc
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * WTSSendMessage() command line tool
+ *
+ * Home page of code is: http://smartmontools.sourceforge.net
+ *
+ * Copyright (C) 2012 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/>.
+ *
+ */
+
+#define WINVER 0x0500
+#define _WIN32_WINNT WINVER
+
+char svnid[] = "$Id: wtssendmsg.c 3714 2012-11-24 16:34:47Z chrfranke $";
+
+#include <stdio.h>
+#include <string.h>
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <wtsapi32.h>
+
+
+static int usage()
+{
+  printf("wtssendmsg $Revision: 3714 $ - Display a message box on client desktops\n"
+         "Copyright (C) 2012 Christian Franke, smartmontools.org\n\n"
+         "Usage: wtssendmsg [-cas] [-v] [\"Caption\"] \"Message\"|-\n"
+         "       wtssendmsg -v\n\n"
+         "  -c    Console session [default]\n"
+         "  -a    Active sessions\n"
+         "  -s    Connected sessions\n"
+         "  -v    List sessions\n"
+  );
+  return 1;
+}
+
+int main(int argc, const char **argv)
+{
+  int mode = 0, verbose = 0, status = 0, i;
+  const char * message = 0, * caption = "";
+  char msgbuf[1024];
+  WTS_SESSION_INFOA * sessions; DWORD count;
+
+  for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1]; i++) {
+    int j;
+    for (j = 1; argv[i][j]; j++)
+      switch (argv[i][j]) {
+      case 'c': mode = 0; break;
+      case 'a': mode = 1; break;
+      case 's': mode = 2; break;
+      case 'v': verbose = 1; break;
+      default: return usage();
+    }
+  }
+
+  if (i < argc) {
+    if (i+1 < argc)
+      caption = argv[i++];
+
+    message = argv[i++];
+    if (i < argc)
+      return usage();
+
+    if (!strcmp(message, "-")) {
+      // Read message from stdin
+      i = fread(msgbuf, 1, sizeof(msgbuf)-1, stdin);
+      if (i < 0) {
+        perror("stdin");
+        return 1;
+      }
+      msgbuf[i] = 0;
+      message = msgbuf;
+    }
+  }
+  else {
+      if (!verbose)
+        return usage();
+  }
+
+  // Get session list
+  if (!WTSEnumerateSessionsA(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessions, &count)) {
+    fprintf(stderr, "WTSEnumerateSessions() failed\n");
+    return 1;
+  }
+
+  for (i = 0; i < (int)count; i++) {
+
+    if (verbose) {
+      printf("Session %d (\"%s\", State=%d)%s",
+             i, sessions[i].pWinStationName, sessions[i].State,
+             (!message ? "\n" : ": "));
+      if (!message)
+        continue; // List sessions only
+      fflush(stdout);
+    }
+
+    if (   !strcmpi(sessions[i].pWinStationName, "Console")
+        || (mode >= 1 && sessions[i].State == WTSActive)
+        || (mode >= 2 && sessions[i].State == WTSConnected)) {
+
+      // Send Message, don't wait for OK button
+      DWORD result;
+      if (WTSSendMessageA(WTS_CURRENT_SERVER_HANDLE, sessions[i].SessionId,
+          (char *)caption, strlen(caption),
+          (char *)message, strlen(message),
+          MB_OK|MB_ICONEXCLAMATION, 0 /*Timeout*/,
+          &result, FALSE /*!Wait*/)) {
+        if (verbose)
+          printf("message sent\n");
+      }
+      else {
+        status = 1;
+        if (verbose)
+          printf("WTSSendMessage() failed with error=%d\n", (int)GetLastError());
+        else
+          fprintf(stderr, "Session %d (\"%s\", State=%d): WTSSendMessage() failed with error=%d\n",
+                  i, sessions[i].pWinStationName, sessions[i].State, (int)GetLastError());
+      }
+    }
+    else {
+      if (verbose)
+        printf("ignored\n");
+    }
+  }
+
+  WTSFreeMemory(sessions);
+
+  return status;
+}
index f25ecae5fd7a966d0c7235cb7410680e43cca59b..dcb714326d59567a92f0253556e8b92e3c3f4788 100644 (file)
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
                                          int length, reg_syntax_t syntax);
index 98d86e1b8059fe3e061e53f4df02e53acacccf38..521a761282b708116373abd1916314a06264e1b7 100644 (file)
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 #ifdef _LIBC
 /* We have to keep the namespace clean.  */
index 9575857216509503a7a9730b7fa5315336f1a35c..dc96a34b32a68f664a113b37bb59fa0a094b7e32 100644 (file)
@@ -16,8 +16,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 #ifndef _REGEX_H
 #define _REGEX_H 1
index f969c7c89fd3d61a2f0a8096d33d2038bdc945f3..03484d295a1f6e4af4685a96e15355b3e17af422 100644 (file)
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 static void re_string_construct_common (const char *str, int len,
                                        re_string_t *pstr,
index bf84ad6270f5d06ada1cf10e82f8517ebec3a00f..28d300bd4c207c39357db701bbeb25a925a4278a 100644 (file)
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 #ifndef _REGEX_INTERNAL_H
 #define _REGEX_INTERNAL_H 1
index 6ea14a6c480335feb0a1d11c4572a5edc6960c58..3296028b81a934c579f999aa9aa20fe0eb16b626 100644 (file)
@@ -15,8 +15,8 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301 USA.  */
 
 static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
                                     re_string_t *input, int n);
index 7ce6d5e5b058de3b7004aa3f102577a9dce01863..f7b790df1537e6c1a98d177d73a2c716d189a437 100644 (file)
@@ -4,7 +4,7 @@
  * Home page of code is: http://smartmontools.sourceforge.net
  *
  * Copyright (C) 2006-12 Douglas Gilbert <dgilbert@interlog.com>
- * Copyright (C) 2009-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2009-13 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
@@ -12,8 +12,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * The code in this file is based on the SCSI to ATA Translation (SAT)
  * draft found at http://www.t10.org . The original draft used for this
@@ -62,7 +62,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 3519 2012-03-06 20:01:44Z chrfranke $";
+const char * scsiata_cpp_cvsid = "$Id: scsiata.cpp 3741 2013-01-02 17:06:54Z chrfranke $";
 
 /* This is a slightly stretched SCSI sense "descriptor" format header.
    The addition is to allow the 0x70 and 0x71 response codes. The idea
@@ -92,12 +92,6 @@ struct sg_scsi_sense_hdr {
 static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
                                    struct sg_scsi_sense_hdr * sshp);
 
-/* Attempt to find the first SCSI sense data descriptor that matches the
-   given 'desc_type'. If found return pointer to start of sense data
-   descriptor; otherwise (including fixed format sense data) returns NULL. */
-static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
-                                                     int sense_len, int desc_type);
-
 #define SAT_ATA_PASSTHROUGH_12LEN 12
 #define SAT_ATA_PASSTHROUGH_16LEN 16
 
@@ -147,6 +141,8 @@ sat_device::sat_device(smart_interface * intf, scsi_device * scsidev,
     hide_ata(); // Start as SCSI, switch to ATA in autodetect_open()
   else
     hide_scsi(); // ATA always
+  if (strcmp(scsidev->get_dev_type(), "scsi"))
+    set_info().dev_type += strprintf("+%s", scsidev->get_dev_type());
 
   set_info().info_name = strprintf("%s [%sSAT]", scsidev->get_info_name(),
                                    (enable_auto ? "SCSI/" : ""));
@@ -232,10 +228,12 @@ sat_device::~sat_device() throw()
 
 bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
-  if (!ata_cmd_is_ok(in,
-    true, // data_out_support
-    true, // multi_sector_support
-    true) // ata_48bit_support
+  if (!ata_cmd_is_supported(in,
+    ata_device::supports_data_out |
+    ata_device::supports_output_regs |
+    ata_device::supports_multi_sector |
+    ata_device::supports_48bit,
+    "SAT")
   )
     return false;
 
@@ -535,32 +533,6 @@ static int sg_scsi_normalize_sense(const unsigned char * sensep, int sb_len,
 }
 
 
-static const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
-                                                     int sense_len, int desc_type)
-{
-    int add_sen_len, add_len, desc_len, k;
-    const unsigned char * descp;
-
-    if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
-        return NULL;
-    if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
-        return NULL;
-    add_sen_len = (add_sen_len < (sense_len - 8)) ?
-                         add_sen_len : (sense_len - 8);
-    descp = &sensep[8];
-    for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
-        descp += desc_len;
-        add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
-        desc_len = add_len + 2;
-        if (descp[0] == desc_type)
-            return descp;
-        if (add_len < 0) /* short descriptor ?? */
-            break;
-    }
-    return NULL;
-}
-
-
 // Call scsi_pass_through and check sense.
 // TODO: Provide as member function of class scsi_device (?)
 static bool scsi_pass_through_and_check(scsi_device * scsidev,  scsi_cmnd_io * iop,
@@ -925,7 +897,8 @@ class usbjmicron_device
 {
 public:
   usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
-                    const char * req_type, bool ata_48bit_support, int port);
+                    const char * req_type, bool prolific,
+                    bool ata_48bit_support, int port);
 
   virtual ~usbjmicron_device() throw();
 
@@ -936,16 +909,19 @@ public:
 private:
   bool get_registers(unsigned short addr, unsigned char * buf, unsigned short size);
 
+  bool m_prolific;
   bool m_ata_48bit_support;
   int m_port;
 };
 
 
 usbjmicron_device::usbjmicron_device(smart_interface * intf, scsi_device * scsidev,
-                                     const char * req_type, bool ata_48bit_support, int port)
+                                     const char * req_type, bool prolific,
+                                     bool ata_48bit_support, int port)
 : smart_device(intf, scsidev->get_dev_name(), "usbjmicron", req_type),
   tunnelled_device<ata_device, scsi_device>(scsidev),
-  m_ata_48bit_support(ata_48bit_support), m_port(port)
+  m_prolific(prolific), m_ata_48bit_support(ata_48bit_support),
+  m_port(port >= 0 || !prolific ? port : 0)
 {
   set_info().info_name = strprintf("%s [USB JMicron]", scsidev->get_info_name());
 }
@@ -989,24 +965,14 @@ bool usbjmicron_device::open()
 
 bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
-  if (!ata_cmd_is_ok(in,
-    true,  // data_out_support
-    false, // !multi_sector_support
-    m_ata_48bit_support) // limited, see below
+  if (!ata_cmd_is_supported(in,
+    ata_device::supports_data_out |
+    ata_device::supports_smart_status |
+    (m_ata_48bit_support ? ata_device::supports_48bit_hi_null : 0),
+    "JMicron")
   )
     return false;
 
-  bool is_smart_status = (   in.in_regs.command  == ATA_SMART_CMD
-                          && in.in_regs.features == ATA_SMART_STATUS);
-
-  // Support output registers for SMART STATUS
-  if (in.out_needed.is_set() && !is_smart_status)
-    return set_err(ENOSYS, "ATA output registers not supported");
-
-  // Support 48-bit commands with zero high bytes
-  if (in.in_regs.is_real_48bit_cmd())
-    return set_err(ENOSYS, "48-bit ATA commands not fully supported");
-
   if (m_port < 0)
     return set_err(EIO, "Unknown JMicron port");
 
@@ -1016,6 +982,9 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
   bool rwbit = true;
   unsigned char smart_status = 0;
 
+  bool is_smart_status = (   in.in_regs.command  == ATA_SMART_CMD
+                          && in.in_regs.features == ATA_SMART_STATUS);
+
   if (is_smart_status && in.out_needed.is_set()) {
     io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
     io_hdr.dxfer_len = 1;
@@ -1042,7 +1011,7 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
   }
 
   // Build pass through command
-  unsigned char cdb[12];
+  unsigned char cdb[14];
   cdb[ 0] = 0xdf;
   cdb[ 1] = (rwbit ? 0x10 : 0x00);
   cdb[ 2] = 0x00;
@@ -1055,9 +1024,12 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
   cdb[ 9] = in.in_regs.lba_high;
   cdb[10] = in.in_regs.device | (m_port == 0 ? 0xa0 : 0xb0);
   cdb[11] = in.in_regs.command;
+  // Prolific PL3507
+  cdb[12] = 0x06;
+  cdb[13] = 0x7b;
 
   io_hdr.cmnd = cdb;
-  io_hdr.cmnd_len = sizeof(cdb);
+  io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
 
   scsi_device * scsidev = get_tunnel_dev();
   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
@@ -1104,7 +1076,7 @@ bool usbjmicron_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & ou
 bool usbjmicron_device::get_registers(unsigned short addr,
                                       unsigned char * buf, unsigned short size)
 {
-  unsigned char cdb[12];
+  unsigned char cdb[14];
   cdb[ 0] = 0xdf;
   cdb[ 1] = 0x10;
   cdb[ 2] = 0x00;
@@ -1117,6 +1089,9 @@ bool usbjmicron_device::get_registers(unsigned short addr,
   cdb[ 9] = 0x00;
   cdb[10] = 0x00;
   cdb[11] = 0xfd;
+  // Prolific PL3507
+  cdb[12] = 0x06;
+  cdb[13] = 0x7b;
 
   scsi_cmnd_io io_hdr;
   memset(&io_hdr, 0, sizeof(io_hdr));
@@ -1125,6 +1100,7 @@ bool usbjmicron_device::get_registers(unsigned short addr,
   io_hdr.dxferp = buf;
   io_hdr.cmnd = cdb;
   io_hdr.cmnd_len = sizeof(cdb);
+  io_hdr.cmnd_len = (!m_prolific ? 12 : 14);
 
   scsi_device * scsidev = get_tunnel_dev();
   if (!scsi_pass_through_and_check(scsidev, &io_hdr,
@@ -1169,10 +1145,11 @@ usbsunplus_device::~usbsunplus_device() throw()
 
 bool usbsunplus_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
 {
-  if (!ata_cmd_is_ok(in,
-    true,  // data_out_support
-    false, // !multi_sector_support
-    true)  // ata_48bit_support
+  if (!ata_cmd_is_supported(in,
+    ata_device::supports_data_out |
+    ata_device::supports_output_regs |
+    ata_device::supports_48bit,
+    "Sunplus")
   )
     return false;
 
@@ -1325,6 +1302,11 @@ ata_device * smart_interface::get_sat_device(const char * type, scsi_device * sc
 
   else if (!strncmp(type, "usbjmicron", 10)) {
     const char * t = type + 10;
+    bool prolific = false;
+    if (!strncmp(t, ",p", 2)) {
+      t += 2;
+      prolific = true;
+    }
     bool ata_48bit_support = false;
     if (!strncmp(t, ",x", 2)) {
       t += 2;
@@ -1333,10 +1315,10 @@ ata_device * smart_interface::get_sat_device(const char * type, scsi_device * sc
     int port = -1, n = -1;
     if (*t && !(  (sscanf(t, ",%d%n", &port, &n) == 1
                 && n == (int)strlen(t) && 0 <= port && port <= 1))) {
-      set_err(EINVAL, "Option '-d usbmicron[,x],<n>' requires <n> to be 0 or 1");
+      set_err(EINVAL, "Option '-d usbjmicron[,p][,x],<n>' requires <n> to be 0 or 1");
       return 0;
     }
-    return new usbjmicron_device(this, scsidev, type, ata_48bit_support, port);
+    return new usbjmicron_device(this, scsidev, type, prolific, ata_48bit_support, port);
   }
 
   else if (!strcmp(type, "usbsunplus")) {
index 30a935641f4a46e196a046e3bd12a1bb95114534..3adc913f1f543e4999b24dc7a7c9fc7fd8b5d308 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
  *
  * Additional SCSI work:
- * Copyright (C) 2003-10 Douglas Gilbert <dgilbert@interlog.com>
+ * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
  *
  * 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
@@ -15,8 +15,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
 #include "dev_interface.h"
 #include "utility.h"
 
-const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 3302 2011-03-25 23:04:36Z dpgilbert $"
+const char *scsicmds_c_cvsid="$Id: scsicmds.cpp 3807 2013-04-18 17:11:12Z chrfranke $"
   SCSICMDS_H_CVSID;
 
 // Print SCSI debug messages?
 unsigned char scsi_debugmode = 0;
 
+supported_vpd_pages * supported_vpd_pages_p = NULL;
+
+
+supported_vpd_pages::supported_vpd_pages(scsi_device * device) : num_valid(0)
+{
+    unsigned char b[0x1fc];     /* size chosen for old INQUIRY command */
+    int n;
+
+    memset(b, 0, sizeof(b));
+    if (device && (0 == scsiInquiryVpd(device, SCSI_VPD_SUPPORTED_VPD_PAGES,
+                   b, sizeof(b)))) {
+        num_valid = (b[2] << 8) + b[3];
+        n = sizeof(pages);
+        if (num_valid > n)
+            num_valid = n;
+        memcpy(pages, b + 4, num_valid);
+    }
+}
+
+bool
+supported_vpd_pages::is_supported(int vpd_page_num) const
+{
+    /* Supported VPD pages numbers start at offset 4 and should be in
+     * ascending order but don't assume that. */
+    for (int k = 0; k < num_valid; ++k) {
+        if (vpd_page_num == pages[k])
+            return true;
+    }
+    return false;
+}
+
 /* output binary in hex and optionally ascii */
-void dStrHex(const char* str, int len, int no_ascii)
+void
+dStrHex(const char* str, int len, int no_ascii)
 {
     const char* p = str;
     unsigned char c;
@@ -67,11 +98,11 @@ void dStrHex(const char* str, int len, int no_ascii)
     int cpos = cpstart;
     int bpos = bpstart;
     int i, k;
-    
+
     if (len <= 0) return;
     memset(buff,' ',80);
     buff[80]='\0';
-    k = sprintf(buff + 1, "%.2x", a);
+    k = snprintf(buff+1, sizeof(buff)-1, "%.2x", a);
     buff[k + 1] = ' ';
     if (bpos >= ((bpstart + (9 * 3))))
         bpos++;
@@ -82,7 +113,7 @@ void dStrHex(const char* str, int len, int no_ascii)
         bpos += 3;
         if (bpos == (bpstart + (9 * 3)))
             bpos++;
-        sprintf(&buff[bpos], "%.2x", (int)(unsigned char)c);
+        snprintf(buff+bpos, sizeof(buff)-bpos, "%.2x", (int)(unsigned char)c);
         buff[bpos + 2] = ' ';
         if (no_ascii)
             buff[cpos++] = ' ';
@@ -98,7 +129,7 @@ void dStrHex(const char* str, int len, int no_ascii)
             cpos = cpstart;
             a += 16;
             memset(buff,' ',80);
-            k = sprintf(buff + 1, "%.2x", a);
+            k = snprintf(buff+1, sizeof(buff)-1, "%.2x", a);
             buff[k + 1] = ' ';
         }
     }
@@ -133,13 +164,15 @@ static struct scsi_opcode_name opcode_name_arr[] = {
     {READ_CAPACITY_16, "read capacity(16)"},    /* 0x9e,0x10 */
     {REPORT_LUNS, "report luns"},               /* 0xa0 */
     {SAT_ATA_PASSTHROUGH_12, "ata pass-through(12)"}, /* 0xa1 */
+    {READ_DEFECT_12, "read defect list(12)"},   /* 0xb7 */
 };
 
 static const char * vendor_specific = "<vendor specific>";
 
 /* Need to expand to take service action into account. For commands
  * of interest the service action is in the 2nd command byte */
-const char * scsi_get_opcode_name(UINT8 opcode)
+const char *
+scsi_get_opcode_name(UINT8 opcode)
 {
     int k;
     int len = sizeof(opcode_name_arr) / sizeof(opcode_name_arr[0]);
@@ -157,16 +190,16 @@ const char * scsi_get_opcode_name(UINT8 opcode)
     return NULL;
 }
 
-
-void scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf,
-                          struct scsi_sense_disect * out)
+void
+scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf,
+                     struct scsi_sense_disect * out)
 {
     int resp_code;
 
     memset(out, 0, sizeof(struct scsi_sense_disect));
     if (SCSI_STATUS_CHECK_CONDITION == io_buf->scsi_status) {
         resp_code = (io_buf->sensep[0] & 0x7f);
-        out->error_code = resp_code;
+        out->resp_code = resp_code;
         if (resp_code >= 0x72) {
             out->sense_key = (io_buf->sensep[1] & 0xf);
             out->asc = io_buf->sensep[2];
@@ -181,14 +214,15 @@ void scsi_do_sense_disect(const struct scsi_cmnd_io * io_buf,
     }
 }
 
-int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo)
+int
+scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo)
 {
     switch (sinfo->sense_key) {
     case SCSI_SK_NO_SENSE:
     case SCSI_SK_RECOVERED_ERR:
         return SIMPLE_NO_ERROR;
     case SCSI_SK_NOT_READY:
-        if (SCSI_ASC_NO_MEDIUM == sinfo->asc) 
+        if (SCSI_ASC_NO_MEDIUM == sinfo->asc)
             return SIMPLE_ERR_NO_MEDIUM;
         else if (SCSI_ASC_NOT_READY == sinfo->asc) {
             if (0x1 == sinfo->ascq)
@@ -203,7 +237,7 @@ int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo)
     case SCSI_SK_ILLEGAL_REQUEST:
         if (SCSI_ASC_UNKNOWN_OPCODE == sinfo->asc)
             return SIMPLE_ERR_BAD_OPCODE;
-        else if (SCSI_ASC_UNKNOWN_FIELD == sinfo->asc)
+        else if (SCSI_ASC_INVALID_FIELD == sinfo->asc)
             return SIMPLE_ERR_BAD_FIELD;
         else if (SCSI_ASC_UNKNOWN_PARAM == sinfo->asc)
             return SIMPLE_ERR_BAD_PARAM;
@@ -218,34 +252,35 @@ int scsiSimpleSenseFilter(const struct scsi_sense_disect * sinfo)
     }
 }
 
-const char * scsiErrString(int scsiErr)
+const char *
+scsiErrString(int scsiErr)
 {
     if (scsiErr < 0)
         return strerror(-scsiErr);
     switch (scsiErr) {
-        case SIMPLE_NO_ERROR: 
+        case SIMPLE_NO_ERROR:
             return "no error";
-        case SIMPLE_ERR_NOT_READY: 
+        case SIMPLE_ERR_NOT_READY:
             return "device not ready";
-        case SIMPLE_ERR_BAD_OPCODE: 
+        case SIMPLE_ERR_BAD_OPCODE:
             return "unsupported scsi opcode";
-        case SIMPLE_ERR_BAD_FIELD: 
+        case SIMPLE_ERR_BAD_FIELD:
             return "unsupported field in scsi command";
-        case SIMPLE_ERR_BAD_PARAM: 
+        case SIMPLE_ERR_BAD_PARAM:
             return "badly formed scsi parameters";
-        case SIMPLE_ERR_BAD_RESP: 
+        case SIMPLE_ERR_BAD_RESP:
             return "scsi response fails sanity test";
-        case SIMPLE_ERR_NO_MEDIUM: 
+        case SIMPLE_ERR_NO_MEDIUM:
             return "no medium present";
-        case SIMPLE_ERR_BECOMING_READY: 
+        case SIMPLE_ERR_BECOMING_READY:
             return "device will be ready soon";
-        case SIMPLE_ERR_TRY_AGAIN: 
+        case SIMPLE_ERR_TRY_AGAIN:
             return "unit attention reported, try again";
-        case SIMPLE_ERR_MEDIUM_HARDWARE: 
+        case SIMPLE_ERR_MEDIUM_HARDWARE:
             return "medium or hardware error (serious)";
-        case SIMPLE_ERR_UNKNOWN: 
+        case SIMPLE_ERR_UNKNOWN:
             return "unknown error (unexpected sense key)";
-        case SIMPLE_ERR_ABORTED_COMMAND: 
+        case SIMPLE_ERR_ABORTED_COMMAND:
             return "aborted command";
         default:
             return "unknown error";
@@ -261,9 +296,9 @@ const char * scsiErrString(int scsiErr)
  * descriptor; returns -1 if normal end condition and -2 for an abnormal
  * termination. Matches association, designator_type and/or code_set when
  * any of those values are greater than or equal to zero. */
-int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
-                        int page_len, int * off, int m_assoc,
-                        int m_desig_type, int m_code_set)
+int
+scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc, int page_len,
+                     int * off, int m_assoc, int m_desig_type, int m_code_set)
 {
     const unsigned char * ucp;
     int k, c_set, assoc, desig_type;
@@ -290,20 +325,21 @@ int scsi_vpd_dev_id_iter(const unsigned char * initial_desig_desc,
 /* Decode VPD page 0x83 logical unit designator into a string. If both
  * numeric address and SCSI name string present, prefer the former.
  * Returns 0 on success, -1 on error with error string in s. */
-int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
-                         int slen, int * transport)
+int
+scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s, int slen,
+                      int * transport)
 {
     int m, c_set, assoc, desig_type, i_len, naa, off, u, have_scsi_ns;
     const unsigned char * ucp;
     const unsigned char * ip;
-    char * orig_s = s;
+    int si = 0;
 
     if (transport)
-       *transport = -1;
+        *transport = -1;
     if (slen < 32) {
-       if (slen > 0)
-           s[0] = '\0';
-       return -1;
+        if (slen > 0)
+            s[0] = '\0';
+        return -1;
     }
     have_scsi_ns = 0;
     s[0] = '\0';
@@ -312,14 +348,14 @@ int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
         ucp = b + off;
         i_len = ucp[3];
         if ((off + i_len + 4) > blen) {
-           s += sprintf(s, "error: designator length");
-           return -1;
+            snprintf(s+si, slen-si, "error: designator length");
+            return -1;
         }
         assoc = ((ucp[1] >> 4) & 0x3);
-       if (transport && assoc && (ucp[1] & 0x80) && (*transport < 0))
-           *transport = (ucp[0] >> 4) & 0xf;
-       if (0 != assoc)
-           continue;
+        if (transport && assoc && (ucp[1] & 0x80) && (*transport < 0))
+            *transport = (ucp[0] >> 4) & 0xf;
+        if (0 != assoc)
+            continue;
         ip = ucp + 4;
         c_set = (ucp[0] & 0xf);
         desig_type = (ucp[1] & 0xf);
@@ -330,52 +366,52 @@ int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
             break;
         case 2: /* EUI-64 based */
             if ((8 != i_len) && (12 != i_len) && (16 != i_len)) {
-               s += sprintf(s, "error: EUI-64 length");
-               return -1;
-           }
-           if (have_scsi_ns)
-               s = orig_s;
-            s += sprintf(s, "0x");
+                snprintf(s+si, slen-si, "error: EUI-64 length");
+                return -1;
+            }
+            if (have_scsi_ns)
+                si = 0;
+            si += snprintf(s+si, slen-si, "0x");
             for (m = 0; m < i_len; ++m)
-                s += sprintf(s, "%02x", (unsigned int)ip[m]);
+                si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             break;
         case 3: /* NAA */
             if (1 != c_set) {
-               s += sprintf(s, "error: NAA bad code_set");
-               return -1;
-           }
+                snprintf(s+si, slen-si, "error: NAA bad code_set");
+                return -1;
+            }
             naa = (ip[0] >> 4) & 0xff;
             if ((naa < 2) || (naa > 6) || (4 == naa)) {
-               s += sprintf(s, "error: unexpected NAA");
-               return -1;
+                snprintf(s+si, slen-si, "error: unexpected NAA");
+                return -1;
             }
-           if (have_scsi_ns)
-               s = orig_s;
+            if (have_scsi_ns)
+                si = 0;
             if (2 == naa) {             /* NAA IEEE Extended */
                 if (8 != i_len) {
-                   s += sprintf(s, "error: NAA 2 length");
-                   return -1;
+                    snprintf(s+si, slen-si, "error: NAA 2 length");
+                    return -1;
                 }
-                s += sprintf(s, "0x");
+                si += snprintf(s+si, slen-si, "0x");
                 for (m = 0; m < 8; ++m)
-                    s += sprintf(s, "%02x", (unsigned int)ip[m]);
+                    si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             } else if ((3 == naa ) || (5 == naa)) {
                 /* NAA=3 Locally assigned; NAA=5 IEEE Registered */
                 if (8 != i_len) {
-                   s += sprintf(s, "error: NAA 3 or 5 length");
-                   return -1;
+                    snprintf(s+si, slen-si, "error: NAA 3 or 5 length");
+                    return -1;
                 }
-                s += sprintf(s, "0x");
+                si += snprintf(s+si, slen-si, "0x");
                 for (m = 0; m < 8; ++m)
-                    s += sprintf(s, "%02x", (unsigned int)ip[m]);
+                    si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             } else if (6 == naa) {      /* NAA IEEE Registered extended */
                 if (16 != i_len) {
-                   s += sprintf(s, "error: NAA 6 length");
-                   return -1;
+                    snprintf(s+si, slen-si, "error: NAA 6 length");
+                    return -1;
                 }
-                s += sprintf(s, "0x");
+                si += snprintf(s+si, slen-si, "0x");
                 for (m = 0; m < 16; ++m)
-                    s += sprintf(s, "%02x", (unsigned int)ip[m]);
+                    si += snprintf(s+si, slen-si, "%02x", (unsigned int)ip[m]);
             }
             break;
         case 4: /* Relative target port */
@@ -385,22 +421,22 @@ int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
             break;
         case 8: /* SCSI name string */
             if (3 != c_set) {
-               s += sprintf(s, "error: SCSI name string");
-               return -1;
+                snprintf(s+si, slen-si, "error: SCSI name string");
+                return -1;
             }
             /* does %s print out UTF-8 ok?? */
-           if (orig_s == s) {
-                s += sprintf(s, "%s", (const char *)ip);
-               ++have_scsi_ns;
-           }
+            if (si == 0) {
+                si += snprintf(s+si, slen-si, "%s", (const char *)ip);
+                ++have_scsi_ns;
+            }
             break;
         default: /* reserved */
             break;
         }
     }
     if (-2 == u) {
-        s += sprintf(s, "error: bad structure");
-       return -1;
+        snprintf(s+si, slen-si, "error: bad structure");
+        return -1;
     }
     return 0;
 }
@@ -412,11 +448,12 @@ int scsi_decode_lu_dev_id(const unsigned char * b, int blen, char * s,
    If known_resp_len > 0 then a single fetch is done for this response
    length. If known_resp_len == 0 then twin fetches are performed, the
    first to deduce the response length, then send the same command again
-   requesting the deduced response length. This protects certain fragile 
+   requesting the deduced response length. This protects certain fragile
    HBAs. The twin fetch technique should not be used with the TapeAlert
    log page since it clears its state flags after each fetch. */
-int scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
-                 int bufLen, int known_resp_len)
+int
+scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
+             int bufLen, int known_resp_len)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -468,7 +505,7 @@ int scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
             pageLen = 252; /* some IBM tape drives don't like double fetch */
         /* some SCSI HBA don't like "odd" length transfers */
         if (pageLen % 2)
-            pageLen += 1;   
+            pageLen += 1;
         if (pageLen > bufLen)
             pageLen = bufLen;
     }
@@ -507,8 +544,9 @@ int scsiLogSense(scsi_device * device, int pagenum, int subpagenum, UINT8 *pBuf,
  * Returns 0 if ok, 1 if NOT READY, 2 if command not supported, * 3 if
  * field in command not supported, * 4 if bad parameter to command or
  * returns negated errno. SPC-4 sections 6.5 and 7.2 (rev 20) */
-int scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
-                  int subpagenum, UINT8 *pBuf, int bufLen)
+int
+scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
+              int subpagenum, UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -540,10 +578,11 @@ int scsiLogSelect(scsi_device * device, int pcr, int sp, int pc, int pagenum,
 
 /* Send MODE SENSE (6 byte) command. Returns 0 if ok, 1 if NOT READY,
  * 2 if command not supported (then MODE SENSE(10) should be supported),
- * 3 if field in command not supported or returns negated errno. 
+ * 3 if field in command not supported or returns negated errno.
  * SPC-3 sections 6.9 and 7.4 (rev 22a) [mode subpage==0] */
-int scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
-                  UINT8 *pBuf, int bufLen)
+int
+scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
+              UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -594,10 +633,11 @@ int scsiModeSense(scsi_device * device, int pagenum, int subpagenum, int pc,
  * from a corresponding 6 byte MODE SENSE command. Such a response should
  * have a 4 byte header followed by 0 or more 8 byte block descriptors
  * (normally 1) and then 1 mode page. Returns 0 if ok, 1 if NOT READY,
- * 2 if command not supported (then MODE SELECT(10) may be supported), 
+ * 2 if command not supported (then MODE SELECT(10) may be supported),
  * 3 if field in command not supported, 4 if bad parameter to command
  * or returns negated errno. SPC-3 sections 6.7 and 7.4 (rev 22a) */
-int scsiModeSelect(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
+int
+scsiModeSelect(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -634,12 +674,13 @@ int scsiModeSelect(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
     return scsiSimpleSenseFilter(&sinfo);
 }
 
-/* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command 
+/* MODE SENSE (10 byte). Returns 0 if ok, 1 if NOT READY, 2 if command
  * not supported (then MODE SENSE(6) might be supported), 3 if field in
- * command not supported or returns negated errno.  
+ * command not supported or returns negated errno.
  * SPC-3 sections 6.10 and 7.4 (rev 22a) [mode subpage==0] */
-int scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
-                    UINT8 *pBuf, int bufLen)
+int
+scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
+                UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -688,11 +729,12 @@ int scsiModeSense10(scsi_device * device, int pagenum, int subpagenum, int pc,
 /* Sends a 10 byte MODE SELECT command. Assumes given pBuf is the response
  * from a corresponding 10 byte MODE SENSE command. Such a response should
  * have a 8 byte header followed by 0 or more 8 byte block descriptors
- * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if 
+ * (normally 1) and then 1 mode page. Returns 0 if ok, 1 NOT REAFY, 2 if
  * command not supported (then MODE SELECT(6) may be supported), 3 if field
  * in command not supported, 4 if bad parameter to command or returns
  * negated errno. SPC-3 sections 6.8 and 7.4 (rev 22a) */
-int scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
+int
+scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -707,7 +749,7 @@ int scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
     hdr_plus_1_pg = pg_offset + pg_len;
     if (hdr_plus_1_pg > bufLen)
         return -EINVAL;
-    pBuf[0] = 0;    
+    pBuf[0] = 0;
     pBuf[1] = 0; /* Length of returned mode sense data reserved for SELECT */
     pBuf[pg_offset] &= 0x7f;    /* Mask out PS bit from byte 0 of page data */
     memset(&io_hdr, 0, sizeof(io_hdr));
@@ -733,14 +775,15 @@ int scsiModeSelect10(scsi_device * device, int sp, UINT8 *pBuf, int bufLen)
 /* Standard INQUIRY returns 0 for ok, anything else is a major problem.
  * bufLen should be 36 for unsafe devices (like USB mass storage stuff)
  * otherwise they can lock up! SPC-3 sections 6.4 and 7.6 (rev 22a) */
-int scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen)
+int
+scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen)
 {
     struct scsi_sense_disect sinfo;
     struct scsi_cmnd_io io_hdr;
     UINT8 cdb[6];
     UINT8 sense[32];
 
-    if ((bufLen < 0) || (bufLen > 255))
+    if ((bufLen < 0) || (bufLen > 1023))
         return -EINVAL;
     memset(&io_hdr, 0, sizeof(io_hdr));
     memset(cdb, 0, sizeof(cdb));
@@ -748,7 +791,8 @@ int scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen)
     io_hdr.dxfer_len = bufLen;
     io_hdr.dxferp = pBuf;
     cdb[0] = INQUIRY;
-    cdb[4] = bufLen;
+    cdb[3] = (bufLen >> 8) & 0xff;
+    cdb[4] = (bufLen & 0xff);
     io_hdr.cmnd = cdb;
     io_hdr.cmnd_len = sizeof(cdb);
     io_hdr.sensep = sense;
@@ -762,10 +806,11 @@ int scsiStdInquiry(scsi_device * device, UINT8 *pBuf, int bufLen)
 }
 
 /* INQUIRY to fetch Vital Page Data.  Returns 0 if ok, 1 if NOT READY
- * (unlikely), 2 if command not supported, 3 if field in command not 
+ * (unlikely), 2 if command not supported, 3 if field in command not
  * supported, 5 if response indicates that EVPD bit ignored or returns
  * negated errno. SPC-3 section 6.4 and 7.6 (rev 22a) */
-int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen)
+int
+scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -773,8 +818,15 @@ int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen)
     UINT8 sense[32];
     int res;
 
-    if ((bufLen < 0) || (bufLen > 255))
+    /* Assume SCSI_VPD_SUPPORTED_VPD_PAGES is first VPD page fetched */
+    if ((SCSI_VPD_SUPPORTED_VPD_PAGES != vpd_page) &&
+        supported_vpd_pages_p &&
+        (! supported_vpd_pages_p->is_supported(vpd_page)))
+        return 3;
+
+    if ((bufLen < 0) || (bufLen > 1023))
         return -EINVAL;
+try_again:
     memset(&io_hdr, 0, sizeof(io_hdr));
     memset(cdb, 0, sizeof(cdb));
     if (bufLen > 1)
@@ -785,7 +837,8 @@ int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen)
     cdb[0] = INQUIRY;
     cdb[1] = 0x1;       /* set EVPD bit (enable Vital Product Data) */
     cdb[2] = vpd_page;
-    cdb[4] = bufLen;
+    cdb[3] = (bufLen >> 8) & 0xff;
+    cdb[4] = (bufLen & 0xff);
     io_hdr.cmnd = cdb;
     io_hdr.cmnd_len = sizeof(cdb);
     io_hdr.sensep = sense;
@@ -795,6 +848,14 @@ int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen)
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
+    if ((SCSI_STATUS_CHECK_CONDITION == io_hdr.scsi_status) &&
+        (SCSI_SK_ILLEGAL_REQUEST == sinfo.sense_key) &&
+        (SCSI_ASC_INVALID_FIELD == sinfo.asc) &&
+        (cdb[3] > 0)) {
+        bufLen &= 0xff; /* make sure cdb[3] is 0 next time around */
+        goto try_again;
+    }
+
     if ((res = scsiSimpleSenseFilter(&sinfo)))
         return res;
     /* Guard against devices that ignore EVPD bit and do standard INQUIRY */
@@ -810,14 +871,15 @@ int scsiInquiryVpd(scsi_device * device, int vpd_page, UINT8 *pBuf, int bufLen)
 
 /* REQUEST SENSE command. Returns 0 if ok, anything else major problem.
  * SPC-3 section 6.27 (rev 22a) */
-int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info)
+int
+scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info)
 {
     struct scsi_cmnd_io io_hdr;
     UINT8 cdb[6];
     UINT8 sense[32];
     UINT8 buff[18];
     int len;
-    UINT8 ecode;
+    UINT8 resp_code;
 
     memset(&io_hdr, 0, sizeof(io_hdr));
     memset(cdb, 0, sizeof(cdb));
@@ -835,18 +897,54 @@ int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     if (sense_info) {
-        ecode = buff[0] & 0x7f;
-        sense_info->error_code = ecode;
+        resp_code = buff[0] & 0x7f;
+        sense_info->resp_code = resp_code;
         sense_info->sense_key = buff[2] & 0xf;
         sense_info->asc = 0;
         sense_info->ascq = 0;
-        if ((0x70 == ecode) || (0x71 == ecode)) {
+        if ((0x70 == resp_code) || (0x71 == resp_code)) {
             len = buff[7] + 8;
             if (len > 13) {
                 sense_info->asc = buff[12];
                 sense_info->ascq = buff[13];
             }
         }
+    // fill progrss indicator, if available
+    sense_info->progress = -1;
+    switch (resp_code) {
+      const unsigned char * ucp;
+      int sk, sk_pr;
+      case 0x70:
+      case 0x71:
+          sk = (buff[2] & 0xf);
+          if ((sizeof(buff) < 18) ||
+              ((SCSI_SK_NO_SENSE != sk) && (SCSI_SK_NOT_READY != sk))) {
+              break;
+          }
+          if (buff[15] & 0x80) {        /* SKSV bit set */
+              sense_info->progress = (buff[16] << 8) + buff[17];
+              break;
+          } else {
+              break;
+          }
+      case 0x72:
+      case 0x73:
+          /* sense key specific progress (0x2) or progress descriptor (0xa) */
+          sk = (buff[1] & 0xf);
+          sk_pr = (SCSI_SK_NO_SENSE == sk) || (SCSI_SK_NOT_READY == sk);
+          if (sk_pr && ((ucp = sg_scsi_sense_desc_find(buff, sizeof(buff), 2))) &&
+              (0x6 == ucp[1]) && (0x80 & ucp[4])) {
+              sense_info->progress = (ucp[5] << 8) + ucp[6];
+              break;
+          } else if (((ucp = sg_scsi_sense_desc_find(buff, sizeof(buff), 0xa))) &&
+                     ((0x6 == ucp[1]))) {
+              sense_info->progress = (ucp[6] << 8) + ucp[7];
+              break;
+          } else
+              break;
+      default:
+          return 0;
+      }
     }
     return 0;
 }
@@ -854,7 +952,9 @@ int scsiRequestSense(scsi_device * device, struct scsi_sense_disect * sense_info
 /* SEND DIAGNOSTIC command.  Returns 0 if ok, 1 if NOT READY, 2 if command
  * not supported, 3 if field in command not supported or returns negated
  * errno. SPC-3 section 6.28 (rev 22a) */
-int scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf, int bufLen)
+int
+scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf,
+                   int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -881,7 +981,7 @@ int scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf, int
     io_hdr.max_sense_len = sizeof(sense);
     /* worst case is an extended foreground self test on a big disk */
     io_hdr.timeout = SCSI_TIMEOUT_SELF_TEST;
-    
+
     if (!device->scsi_pass_through(&io_hdr))
       return -device->get_errno();
     scsi_do_sense_disect(&io_hdr, &sinfo);
@@ -891,7 +991,8 @@ int scsiSendDiagnostic(scsi_device * device, int functioncode, UINT8 *pBuf, int
 /* RECEIVE DIAGNOSTIC command. Returns 0 if ok, 1 if NOT READY, 2 if
  * command not supported, 3 if field in command not supported or returns
  * negated errno. SPC-3 section 6.18 (rev 22a) */
-int scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBuf,
+int
+scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBuf,
                       int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
@@ -922,7 +1023,8 @@ int scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBu
 }
 
 /* TEST UNIT READY command. SPC-3 section 6.33 (rev 22a) */
-static int _testunitready(scsi_device * device, struct scsi_sense_disect * sinfo)
+static int
+_testunitready(scsi_device * device, struct scsi_sense_disect * sinfo)
 {
     struct scsi_cmnd_io io_hdr;
     UINT8 cdb[6];
@@ -948,7 +1050,8 @@ static int _testunitready(scsi_device * device, struct scsi_sense_disect * sinfo
 
 /* Returns 0 for device responds and media ready, 1 for device responds and
    media not ready, or returns a negated errno value */
-int scsiTestUnitReady(scsi_device * device)
+int
+scsiTestUnitReady(scsi_device * device)
 {
     struct scsi_sense_disect sinfo;
     int status;
@@ -959,7 +1062,7 @@ int scsiTestUnitReady(scsi_device * device)
     status = scsiSimpleSenseFilter(&sinfo);
     if (SIMPLE_ERR_TRY_AGAIN == status) {
         /* power on reset, media changed, ok ... try again */
-        status = _testunitready(device, &sinfo);        
+        status = _testunitready(device, &sinfo);
         if (0 != status)
             return status;
         status = scsiSimpleSenseFilter(&sinfo);
@@ -970,8 +1073,9 @@ int scsiTestUnitReady(scsi_device * device)
 /* READ DEFECT (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
  * command not supported, 3 if field in command not supported or returns
  * negated errno. SBC-2 section 5.12 (rev 16) */
-int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format,
-                     UINT8 *pBuf, int bufLen)
+int
+scsiReadDefect10(scsi_device * device, int req_plist, int req_glist,
+                 int dl_format, UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -1000,11 +1104,52 @@ int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_
     return scsiSimpleSenseFilter(&sinfo);
 }
 
+/* READ DEFECT (12) command. Returns 0 if ok, 1 if NOT READY, 2 if
+ * command not supported, 3 if field in command not supported or returns
+ * negated errno. SBC-3 section 5.18 (rev 35; vale Mark Evans) */
+int
+scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
+                 int dl_format, int addrDescIndex, UINT8 *pBuf, int bufLen)
+{
+    struct scsi_cmnd_io io_hdr;
+    struct scsi_sense_disect sinfo;
+    UINT8 cdb[12];
+    UINT8 sense[32];
+
+    memset(&io_hdr, 0, sizeof(io_hdr));
+    memset(cdb, 0, sizeof(cdb));
+    io_hdr.dxfer_dir = DXFER_FROM_DEVICE;
+    io_hdr.dxfer_len = bufLen;
+    io_hdr.dxferp = pBuf;
+    cdb[0] = READ_DEFECT_12;
+    cdb[1] = (unsigned char)(((req_plist << 4) & 0x10) |
+               ((req_glist << 3) & 0x8) | (dl_format & 0x7));
+    cdb[2] = (addrDescIndex >> 24) & 0xff;
+    cdb[3] = (addrDescIndex >> 16) & 0xff;
+    cdb[4] = (addrDescIndex >> 8) & 0xff;
+    cdb[5] = addrDescIndex & 0xff;
+    cdb[6] = (bufLen >> 24) & 0xff;
+    cdb[7] = (bufLen >> 16) & 0xff;
+    cdb[8] = (bufLen >> 8) & 0xff;
+    cdb[9] = bufLen & 0xff;
+    io_hdr.cmnd = cdb;
+    io_hdr.cmnd_len = sizeof(cdb);
+    io_hdr.sensep = sense;
+    io_hdr.max_sense_len = sizeof(sense);
+    io_hdr.timeout = SCSI_TIMEOUT_DEFAULT;
+
+    if (!device->scsi_pass_through(&io_hdr))
+      return -device->get_errno();
+    scsi_do_sense_disect(&io_hdr, &sinfo);
+    return scsiSimpleSenseFilter(&sinfo);
+}
+
 /* READ CAPACITY (10) command. Returns 0 if ok, 1 if NOT READY, 2 if
  * command not supported, 3 if field in command not supported or returns
  * negated errno. SBC-3 section 5.15 (rev 26) */
-int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap,
-                       unsigned int * lb_sizep)
+int
+scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap,
+                   unsigned int * lb_sizep)
 {
     int res;
     struct scsi_cmnd_io io_hdr;
@@ -1044,7 +1189,8 @@ int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbap,
 /* READ CAPACITY (16) command. The bufLen argument should be 32. Returns 0
  * if ok, 1 if NOT READY, 2 if command not supported, 3 if field in command
  * not supported or returns negated errno. SBC-3 section 5.16 (rev 26) */
-int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen)
+int
+scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen)
 {
     struct scsi_cmnd_io io_hdr;
     struct scsi_sense_disect sinfo;
@@ -1077,43 +1223,72 @@ int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen)
 /* Return number of bytes of storage in 'device' or 0 if error. If
  * successful and lb_sizep is not NULL then the logical block size
  * in bytes is written to the location pointed to by lb_sizep. */
-uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep)
+uint64_t
+scsiGetSize(scsi_device * device, unsigned int * lb_sizep,
+            int * lb_per_pb_expp)
 {
-    unsigned int last_lba, lb_size;
+    unsigned int last_lba = 0, lb_size = 0;
     int k, res;
     uint64_t ret_val = 0;
     UINT8 rc16resp[32];
 
     res = scsiReadCapacity10(device, &last_lba, &lb_size);
     if (res) {
-       if (scsi_debugmode)
-           pout("scsiGetSize: READ CAPACITY(10) failed, res=%d\n", res);
-       return ret_val;
+        if (scsi_debugmode)
+            pout("scsiGetSize: READ CAPACITY(10) failed, res=%d\n", res);
+        return 0;
     }
     if (0xffffffff == last_lba) {
-       res = scsiReadCapacity16(device, rc16resp, sizeof(rc16resp));
+        res = scsiReadCapacity16(device, rc16resp, sizeof(rc16resp));
         if (res) {
-           if (scsi_debugmode)
-               pout("scsiGetSize: READ CAPACITY(16) failed, res=%d\n", res);
-           return ret_val;
-       }
-       for (k = 0; k < 8; ++k) {
-           if (k > 0)
+            if (scsi_debugmode)
+                pout("scsiGetSize: READ CAPACITY(16) failed, res=%d\n", res);
+            return 0;
+        }
+        for (k = 0; k < 8; ++k) {
+            if (k > 0)
                 ret_val <<= 8;
             ret_val |= rc16resp[k + 0];
         }
-    } else
-       ret_val = last_lba;
+        if (lb_per_pb_expp)
+            *lb_per_pb_expp = (rc16resp[13] & 0xf);
+    } else {
+        ret_val = last_lba;
+        if (lb_per_pb_expp)
+            *lb_per_pb_expp = 0;
+    }
     if (lb_sizep)
-       *lb_sizep = lb_size;
-    ++ret_val; /* last_lba is origin 0 so need to bump to get number of */
+        *lb_sizep = lb_size;
+    ++ret_val;  /* last_lba is origin 0 so need to bump to get number of */
     return ret_val * lb_size;
 }
 
+/* Gets drive Protection and Logical/Physical block information. Writes
+ * back bytes 12 to 31 from a READ CAPACITY 16 command to the rc16_12_31p
+ * pointer. So rc16_12_31p should point to an array of 20 bytes. Returns 0
+ * if ok, 1 if NOT READY, 2 if command not supported, 3 if field in command
+ * not supported or returns negated errno. */
+int
+scsiGetProtPBInfo(scsi_device * device, unsigned char * rc16_12_31p)
+{
+    int res;
+    UINT8 rc16resp[32];
+
+    res = scsiReadCapacity16(device, rc16resp, sizeof(rc16resp));
+    if (res) {
+        if (scsi_debugmode)
+            pout("scsiGetSize: READ CAPACITY(16) failed, res=%d\n", res);
+        return res;
+    }
+    if (rc16_12_31p)
+        memcpy(rc16_12_31p, rc16resp + 12, 20);
+    return 0;
+}
 
 /* Offset into mode sense (6 or 10 byte) response that actual mode page
  * starts at (relative to resp[0]). Returns -1 if problem */
-int scsiModePageOffset(const UINT8 * resp, int len, int modese_len)
+int
+scsiModePageOffset(const UINT8 * resp, int len, int modese_len)
 {
     int resp_len, bd_len;
     int offset = -1;
@@ -1155,7 +1330,9 @@ int scsiModePageOffset(const UINT8 * resp, int len, int modese_len)
  * tries a 10 byte MODE SENSE command. Returns 0 if successful, a positive
  * number if a known error (see  SIMPLE_ERR_ ...) or a negative errno
  * value. */
-int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp, int modese_len)
+int
+scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp,
+                  int modese_len)
 {
     int err = 0;
 
@@ -1183,7 +1360,7 @@ int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp, int
             iecp->modese_len = 0;
             return err;
         }
-    } 
+    }
     iecp->gotCurrent = 1;
     iecp->requestedChangeable = 1;
     if (10 == iecp->modese_len)
@@ -1191,8 +1368,8 @@ int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp, int
                               0, MPAGE_CONTROL_CHANGEABLE,
                               iecp->raw_chg, sizeof(iecp->raw_chg));
     else if (6 == iecp->modese_len)
-        err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE, 
-                            0, MPAGE_CONTROL_CHANGEABLE, 
+        err = scsiModeSense(device, INFORMATIONAL_EXCEPTIONS_CONTROL_PAGE,
+                            0, MPAGE_CONTROL_CHANGEABLE,
                             iecp->raw_chg, sizeof(iecp->raw_chg));
     if (err)
         return err;
@@ -1200,7 +1377,8 @@ int scsiFetchIECmpage(scsi_device * device, struct scsi_iec_mode_page *iecp, int
     return 0;
 }
 
-int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
+int
+scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
 {
     int offset;
 
@@ -1215,7 +1393,8 @@ int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
         return 0;
 }
 
-int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
+int
+scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
 {
     int offset;
 
@@ -1231,10 +1410,10 @@ int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
 }
 
 /* set EWASC and clear PERF, EBF, DEXCPT TEST and LOGERR */
-#define SCSI_IEC_MP_BYTE2_ENABLED 0x10 
+#define SCSI_IEC_MP_BYTE2_ENABLED 0x10
 #define SCSI_IEC_MP_BYTE2_TEST_MASK 0x4
 /* exception/warning via an unrequested REQUEST SENSE command */
-#define SCSI_IEC_MP_MRIE 6      
+#define SCSI_IEC_MP_MRIE 6
 #define SCSI_IEC_MP_INTERVAL_T 0
 #define SCSI_IEC_MP_REPORT_COUNT 1
 
@@ -1245,8 +1424,9 @@ int scsi_IsWarningEnabled(const struct scsi_iec_mode_page *iecp)
  * is to be re-examined.
  * When -r ioctl is invoked 3 or more time on 'smartctl -s on ...'
  * then set the TEST bit (causes asc,ascq pair of 0x5d,0xff). */
-int scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
-                                      const struct scsi_iec_mode_page *iecp)
+int
+scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
+                                  const struct scsi_iec_mode_page *iecp)
 {
     int k, offset, resp_len;
     int err = 0;
@@ -1304,10 +1484,10 @@ int scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
                 pout("scsiSetExceptionControlAndWarning: already disabled\n");
             return 0;   /* nothing to do, leave other setting alone */
         }
-        if (wEnabled) 
+        if (wEnabled)
             rout[offset + 2] &= EWASC_DISABLE;
         if (eCEnabled) {
-            if (iecp->gotChangeable && 
+            if (iecp->gotChangeable &&
                 (iecp->raw_chg[offset + 2] & DEXCPT_ENABLE))
                 rout[offset + 2] |= DEXCPT_ENABLE;
                 rout[offset + 2] &= TEST_DISABLE;/* clear TEST bit for spec */
@@ -1320,7 +1500,8 @@ int scsiSetExceptionControlAndWarning(scsi_device * device, int enabled,
     return err;
 }
 
-int scsiGetTemp(scsi_device * device, UINT8 *currenttemp, UINT8 *triptemp)
+int
+scsiGetTemp(scsi_device * device, UINT8 *currenttemp, UINT8 *triptemp)
 {
     UINT8 tBuf[252];
     int err;
@@ -1342,9 +1523,9 @@ int scsiGetTemp(scsi_device * device, UINT8 *currenttemp, UINT8 *triptemp)
  * Fetching asc/ascq code potentially flagging an exception or warning.
  * Returns 0 if ok, else error number. A current temperature of 255
  * (Celsius) implies that the temperature not available. */
-int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
-                UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp,
-                UINT8 *triptemp)
+int
+scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
+            UINT8 *asc, UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp)
 {
     UINT8 tBuf[252];
     struct scsi_sense_disect sense_info;
@@ -1352,7 +1533,7 @@ int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
     int temperatureSet = 0;
     unsigned short pagesize;
     UINT8 currTemp, trTemp;
+
     *asc = 0;
     *ascq = 0;
     *currenttemp = 0;
@@ -1366,23 +1547,23 @@ int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
             return err;
         }
         // pull out page size from response, don't forget to add 4
-        pagesize = (unsigned short) ((tBuf[2] << 8) | tBuf[3]) + 4; 
+        pagesize = (unsigned short) ((tBuf[2] << 8) | tBuf[3]) + 4;
         if ((pagesize < 4) || tBuf[4] || tBuf[5]) {
             pout("Log Sense failed, IE page, bad parameter code or length\n");
             return SIMPLE_ERR_BAD_PARAM;
         }
         if (tBuf[7] > 1) {
-            sense_info.asc = tBuf[8]; 
+            sense_info.asc = tBuf[8];
             sense_info.ascq = tBuf[9];
             if (! hasTempLogPage) {
-                if (tBuf[7] > 2) 
+                if (tBuf[7] > 2)
                     *currenttemp = tBuf[10];
                 if (tBuf[7] > 3)        /* IBM extension in SMART (IE) lpage */
                     *triptemp = tBuf[11];
             }
-        } 
+        }
     }
-    if (0 == sense_info.asc) {    
+    if (0 == sense_info.asc) {
         /* ties in with MRIE field of 6 in IEC mode page (0x1c) */
         if ((err = scsiRequestSense(device, &sense_info))) {
             pout("Request Sense failed, [%s]\n", scsiErrString(err));
@@ -1401,7 +1582,7 @@ int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage,
 }
 
 // The first character (W, C, I) tells the severity
-static const char * TapeAlertsMessageTable[]= {  
+static const char * TapeAlertsMessageTable[]= {
     " ",
     /* 0x01 */
    "W: The tape drive is having problems reading data. No data has been lost,\n"
@@ -1625,16 +1806,17 @@ static const char * TapeAlertsMessageTable[]= {
         "  fault. If problem persists, call the supplier help line.",
     };
 
-const char * scsiTapeAlertsTapeDevice(unsigned short code)
+const char *
+scsiTapeAlertsTapeDevice(unsigned short code)
 {
     const int num = sizeof(TapeAlertsMessageTable) /
                         sizeof(TapeAlertsMessageTable[0]);
 
-    return (code < num) ?  TapeAlertsMessageTable[code] : "Unknown Alert"; 
+    return (code < num) ?  TapeAlertsMessageTable[code] : "Unknown Alert";
 }
 
 // The first character (W, C, I) tells the severity
-static const char * ChangerTapeAlertsMessageTable[]= {  
+static const char * ChangerTapeAlertsMessageTable[]= {
     " ",
     /* 0x01 */
     "C: The library mechanism is having difficulty communicating with the\n"
@@ -1760,12 +1942,13 @@ static const char * ChangerTapeAlertsMessageTable[]= {
     "I: The library was unable to read the bar code on a cartridge.",
 };
 
-const char * scsiTapeAlertsChangerDevice(unsigned short code)
+const char *
+scsiTapeAlertsChangerDevice(unsigned short code)
 {
     const int num = sizeof(ChangerTapeAlertsMessageTable) /
                         sizeof(ChangerTapeAlertsMessageTable[0]);
 
-    return (code < num) ?  ChangerTapeAlertsMessageTable[code] : "Unknown Alert"; 
+    return (code < num) ?  ChangerTapeAlertsMessageTable[code] : "Unknown Alert";
 }
 
 
@@ -1894,14 +2077,15 @@ static const char * strs_for_asc_b[] = {
 
 static char spare_buff[128];
 
-const char * scsiGetIEString(UINT8 asc, UINT8 ascq)
+const char *
+scsiGetIEString(UINT8 asc, UINT8 ascq)
 {
     const char * rp;
 
     if (SCSI_ASC_IMPENDING_FAILURE == asc) {
         if (ascq == 0xff)
             return "FAILURE PREDICTION THRESHOLD EXCEEDED (FALSE)";
-        else if (ascq < 
+        else if (ascq <
                  (sizeof(strs_for_asc_5d) / sizeof(strs_for_asc_5d[0]))) {
             rp = strs_for_asc_5d[ascq];
             if (strlen(rp) > 0)
@@ -1925,11 +2109,12 @@ const char * scsiGetIEString(UINT8 asc, UINT8 ascq)
 
 /* This is not documented in t10.org, page 0x80 is vendor specific */
 /* Some IBM disks do an offline read-scan when they get this command. */
-int scsiSmartIBMOfflineTest(scsi_device * device)
-{       
+int
+scsiSmartIBMOfflineTest(scsi_device * device)
+{
     UINT8 tBuf[256];
     int res;
-        
+
     memset(tBuf, 0, sizeof(tBuf));
     /* Build SMART Off-line Immediate Diag Header */
     tBuf[0] = 0x80; /* Page Code */
@@ -1946,8 +2131,9 @@ int scsiSmartIBMOfflineTest(scsi_device * device)
     return res;
 }
 
-int scsiSmartDefaultSelfTest(scsi_device * device)
-{       
+int
+scsiSmartDefaultSelfTest(scsi_device * device)
+{
     int res;
 
     res = scsiSendDiagnostic(device, SCSI_DIAG_DEF_SELF_TEST, NULL, 0);
@@ -1956,8 +2142,9 @@ int scsiSmartDefaultSelfTest(scsi_device * device)
     return res;
 }
 
-int scsiSmartShortSelfTest(scsi_device * device)
-{       
+int
+scsiSmartShortSelfTest(scsi_device * device)
+{
     int res;
 
     res = scsiSendDiagnostic(device, SCSI_DIAG_BG_SHORT_SELF_TEST, NULL, 0);
@@ -1966,8 +2153,9 @@ int scsiSmartShortSelfTest(scsi_device * device)
     return res;
 }
 
-int scsiSmartExtendSelfTest(scsi_device * device)
-{       
+int
+scsiSmartExtendSelfTest(scsi_device * device)
+{
     int res;
 
     res = scsiSendDiagnostic(device, SCSI_DIAG_BG_EXTENDED_SELF_TEST, NULL, 0);
@@ -1977,8 +2165,9 @@ int scsiSmartExtendSelfTest(scsi_device * device)
     return res;
 }
 
-int scsiSmartShortCapSelfTest(scsi_device * device)
-{       
+int
+scsiSmartShortCapSelfTest(scsi_device * device)
+{
     int res;
 
     res = scsiSendDiagnostic(device, SCSI_DIAG_FG_SHORT_SELF_TEST, NULL, 0);
@@ -1987,7 +2176,8 @@ int scsiSmartShortCapSelfTest(scsi_device * device)
     return res;
 }
 
-int scsiSmartExtendCapSelfTest(scsi_device * device)
+int
+scsiSmartExtendCapSelfTest(scsi_device * device)
 {
     int res;
 
@@ -1998,7 +2188,8 @@ int scsiSmartExtendCapSelfTest(scsi_device * device)
     return res;
 }
 
-int scsiSmartSelfTestAbort(scsi_device * device)
+int
+scsiSmartSelfTestAbort(scsi_device * device)
 {
     int res;
 
@@ -2010,7 +2201,9 @@ int scsiSmartSelfTestAbort(scsi_device * device)
 
 /* Returns 0 and the expected duration of an extended self test (in seconds)
    if successful; any other return value indicates a failure. */
-int scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec, int modese_len)
+int
+scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec,
+                              int modese_len)
 {
     int err, offset, res;
     UINT8 buff[64];
@@ -2029,11 +2222,11 @@ int scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec, int m
     }
     if (10 == modese_len) {
         err = scsiModeSense10(device, CONTROL_MODE_PAGE, 0,
-                              MPAGE_CONTROL_CURRENT, 
+                              MPAGE_CONTROL_CURRENT,
                               buff, sizeof(buff));
         if (err)
             return err;
-    } 
+    }
     offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
     if (offset < 0)
         return -EINVAL;
@@ -2046,8 +2239,8 @@ int scsiFetchExtendedSelfTestTime(scsi_device * device, int * durationSec, int m
         return -EINVAL;
 }
 
-void scsiDecodeErrCounterPage(unsigned char * resp, 
-                              struct scsiErrorCounter *ecp)
+void
+scsiDecodeErrCounterPage(unsigned char * resp, struct scsiErrorCounter *ecp)
 {
     int k, j, num, pl, pc;
     unsigned char * ucp;
@@ -2061,17 +2254,17 @@ void scsiDecodeErrCounterPage(unsigned char * resp,
         pc = (ucp[0] << 8) | ucp[1];
         pl = ucp[3] + 4;
         switch (pc) {
-            case 0: 
-            case 1: 
-            case 2: 
-            case 3: 
-            case 4: 
-            case 5: 
-            case 6: 
+            case 0:
+            case 1:
+            case 2:
+            case 3:
+            case 4:
+            case 5:
+            case 6:
                 ecp->gotPC[pc] = 1;
                 ullp = &ecp->counter[pc];
                 break;
-        default: 
+        default:
                 ecp->gotExtraPC = 1;
                 ullp = &ecp->counter[7];
                 break;
@@ -2093,8 +2286,9 @@ void scsiDecodeErrCounterPage(unsigned char * resp,
     }
 }
 
-void scsiDecodeNonMediumErrPage(unsigned char *resp, 
-                                struct scsiNonMediumError *nmep)
+void
+scsiDecodeNonMediumErrPage(unsigned char *resp,
+                           struct scsiNonMediumError *nmep)
 {
     int k, j, num, pl, pc, szof;
     unsigned char * ucp;
@@ -2108,7 +2302,7 @@ void scsiDecodeNonMediumErrPage(unsigned char *resp,
         pc = (ucp[0] << 8) | ucp[1];
         pl = ucp[3] + 4;
         switch (pc) {
-            case 0: 
+            case 0:
                 nmep->gotPC0 = 1;
                 k = pl - 4;
                 xp = ucp + 4;
@@ -2123,7 +2317,7 @@ void scsiDecodeNonMediumErrPage(unsigned char *resp,
                     nmep->counterPC0 |= xp[j];
                 }
                 break;
-            case 0x8009: 
+            case 0x8009:
                 nmep->gotTFE_H = 1;
                 k = pl - 4;
                 xp = ucp + 4;
@@ -2138,7 +2332,7 @@ void scsiDecodeNonMediumErrPage(unsigned char *resp,
                     nmep->counterTFE_H |= xp[j];
                 }
                 break;
-            case 0x8015: 
+            case 0x8015:
                 nmep->gotPE_H = 1;
                 k = pl - 4;
                 xp = ucp + 4;
@@ -2153,7 +2347,7 @@ void scsiDecodeNonMediumErrPage(unsigned char *resp,
                     nmep->counterPE_H |= xp[j];
                 }
                 break;
-        default: 
+        default:
                 nmep->gotExtraPC = 1;
                 break;
         }
@@ -2167,10 +2361,11 @@ void scsiDecodeNonMediumErrPage(unsigned char *resp,
    this function has a problem (typically -1), otherwise the bottom 8
    bits are the number of failed self tests and the 16 bits above that
    are the poweron hour of the most recent failure. Note: aborted self
-   tests (typically by the user) and self tests in progress are not 
-   considered failures. See Working Draft SCSI Primary Commands - 3 
+   tests (typically by the user) and self tests in progress are not
+   considered failures. See Working Draft SCSI Primary Commands - 3
    (SPC-3) section 7.2.10 T10/1416-D (rev 22a) */
-int scsiCountFailedSelfTests(scsi_device * fd, int noisy)
+int
+scsiCountFailedSelfTests(scsi_device * fd, int noisy)
 {
     int num, k, n, err, res, fails, fail_hour;
     UINT8 * ucp;
@@ -2210,7 +2405,7 @@ int scsiCountFailedSelfTests(scsi_device * fd, int noisy)
         res = ucp[4] & 0xf;
         if ((res > 2) && (res < 8)) {
             fails++;
-            if (1 == fails) 
+            if (1 == fails)
                 fail_hour = (ucp[6] << 8) + ucp[7];
         }
     }
@@ -2219,7 +2414,8 @@ int scsiCountFailedSelfTests(scsi_device * fd, int noisy)
 
 /* Returns 0 if able to read self test log page; then outputs 1 into
    *inProgress if self test still in progress, else outputs 0. */
-int scsiSelfTestInProgress(scsi_device * fd, int * inProgress)
+int
+scsiSelfTestInProgress(scsi_device * fd, int * inProgress)
 {
     int num;
     UINT8 * ucp;
@@ -2246,7 +2442,8 @@ int scsiSelfTestInProgress(scsi_device * fd, int * inProgress)
    malformed. Returns 0 if GLTSD bit is zero and returns 1 if the GLTSD
    bit is set. Examines default mode page when current==0 else examines
    current mode page. */
-int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current)
+int
+scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current)
 {
     int err, offset;
     UINT8 buff[64];
@@ -2268,18 +2465,163 @@ int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current)
                               buff, sizeof(buff));
         if (err)
             return -EINVAL;
-    } 
+    }
     offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
     if ((offset >= 0) && (buff[offset + 1] >= 0xa))
         return (buff[offset + 2] & 2) ? 1 : 0;
     return -EINVAL;
 }
 
+/* Returns a negative value on error, 0 if unknown and 1 if SSD,
+ * otherwise the positive returned value is the speed in rpm. First checks
+ * the Block Device Characteristics VPD page and if that fails it tries the
+ * RIGID_DISK_DRIVE_GEOMETRY_PAGE mode page. */
+
+int
+scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp)
+{
+    int err, offset, speed;
+    UINT8 buff[64];
+    int pc = MPAGE_CONTROL_DEFAULT;
+
+    memset(buff, 0, sizeof(buff));
+    if ((0 == scsiInquiryVpd(device, SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS,
+                             buff, sizeof(buff))) &&
+        (((buff[2] << 8) + buff[3]) > 2)) {
+        speed = (buff[4] << 8) + buff[5];
+        if (form_factorp)
+            *form_factorp = buff[7] & 0xf;
+        return speed;
+    }
+    if (form_factorp)
+        *form_factorp = 0;
+    if (modese_len <= 6) {
+        if ((err = scsiModeSense(device, RIGID_DISK_DRIVE_GEOMETRY_PAGE, 0, pc,
+                                 buff, sizeof(buff)))) {
+            if (SIMPLE_ERR_BAD_OPCODE == err)
+                modese_len = 10;
+            else
+                return -EINVAL;
+        } else if (0 == modese_len)
+            modese_len = 6;
+    }
+    if (10 == modese_len) {
+        err = scsiModeSense10(device, RIGID_DISK_DRIVE_GEOMETRY_PAGE, 0, pc,
+                              buff, sizeof(buff));
+        if (err)
+            return -EINVAL;
+    }
+    offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
+    return (buff[offset + 20] << 8) | buff[offset + 21];
+}
+
+/* Returns a non-zero value in case of error, wcep/rcdp == -1 - get value,
+   0 - clear bit, 1 - set bit  */
+
+int
+scsiGetSetCache(scsi_device * device,  int modese_len, short int * wcep,
+                short int * rcdp)
+{
+    int err, offset, resp_len, sp;
+    UINT8 buff[64], ch_buff[64];
+    short set_wce = *wcep;
+    short set_rcd = *rcdp;
+
+    memset(buff, 0, sizeof(buff));
+    if (modese_len <= 6) {
+        if ((err = scsiModeSense(device, CACHING_PAGE, 0, MPAGE_CONTROL_CURRENT,
+                                 buff, sizeof(buff)))) {
+            if (SIMPLE_ERR_BAD_OPCODE == err)
+                modese_len = 10;
+            else {
+                device->set_err(EINVAL, "SCSI MODE SENSE failed");
+                return -EINVAL;
+            }
+        } else if (0 == modese_len)
+            modese_len = 6;
+    }
+
+    if (10 == modese_len) {
+        err = scsiModeSense10(device, CACHING_PAGE, 0, MPAGE_CONTROL_CURRENT,
+                              buff, sizeof(buff));
+        if (err) {
+            device->set_err(EINVAL, "SCSI MODE SENSE failed");
+            return -EINVAL;
+        }
+    }
+    offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
+    if ((offset < 0) || (buff[offset + 1] < 0xa)) {
+        device->set_err(EINVAL, "Bad response");
+        return SIMPLE_ERR_BAD_RESP;
+    }
+
+    *wcep = ((buff[offset + 2] & 0x04) != 0);
+    *rcdp = ((buff[offset + 2] & 0x01) != 0);
+
+    if((*wcep == set_wce || set_wce == -1)
+          && ((*rcdp == set_rcd) || set_rcd == -1))
+      return 0; // no changes needed or nothing to set
+
+    if (modese_len == 6)
+        err = scsiModeSense(device, CACHING_PAGE, 0,
+                            MPAGE_CONTROL_CHANGEABLE,
+                            ch_buff, sizeof(ch_buff));
+    else
+        err = scsiModeSense10(device, CACHING_PAGE, 0,
+                              MPAGE_CONTROL_CHANGEABLE,
+                              ch_buff, sizeof(ch_buff));
+    if (err) {
+        device->set_err(EINVAL, "WCE/RCD bits not changable");
+        return err;
+    }
+
+    // set WCE bit
+    if(set_wce >= 0 && *wcep != set_wce) {
+       if (0 == (ch_buff[offset + 2] & 0x04)) {
+         device->set_err(EINVAL, "WCE bit not changable");
+         return 1;
+       }
+       if(set_wce)
+          buff[offset + 2] |= 0x04; // set bit
+       else
+          buff[offset + 2] &= 0xfb; // clear bit
+    }
+    // set RCD bit
+    if(set_rcd >= 0 && *rcdp != set_rcd) {
+       if (0 == (ch_buff[offset + 2] & 0x01)) {
+         device->set_err(EINVAL, "RCD bit not changable");
+         return 1;
+       }
+       if(set_rcd)
+          buff[offset + 2] |= 0x01; // set bit
+       else
+          buff[offset + 2] &= 0xfe; // clear bit
+    }
+
+    if (10 == modese_len) {
+        resp_len = (buff[0] << 8) + buff[1] + 2;
+        buff[3] &= 0xef;    /* for disks mask out DPOFUA bit */
+    } else {
+        resp_len = buff[0] + 1;
+        buff[2] &= 0xef;    /* for disks mask out DPOFUA bit */
+    }
+    sp = 0; /* Do not change saved values */
+    if (10 == modese_len)
+        err = scsiModeSelect10(device, sp, buff, resp_len);
+    else if (6 == modese_len)
+        err = scsiModeSelect(device, sp, buff, resp_len);
+    if(err)
+      device->set_err(EINVAL, "MODE SELECT command failed");
+    return err;
+}
+
+
 /* Attempts to set or clear GLTSD bit in Control mode page. If enabled is
    0 attempts to clear GLTSD otherwise it attempts to set it. Returns 0 if
    successful, negative if low level error, > 0 if higher level error (e.g.
    SIMPLE_ERR_BAD_PARAM if GLTSD bit is not changeable). */
-int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
+int
+scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
 {
     int err, offset, resp_len, sp;
     UINT8 buff[64];
@@ -2303,7 +2645,7 @@ int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
                               buff, sizeof(buff));
         if (err)
             return err;
-    } 
+    }
     offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
     if ((offset < 0) || (buff[offset + 1] < 0xa))
         return SIMPLE_ERR_BAD_RESP;
@@ -2325,7 +2667,7 @@ int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
         return err;
     if (0 == (ch_buff[offset + 2] & 2))
         return SIMPLE_ERR_BAD_PARAM;  /* GLTSD bit not chageable */
-    
+
     if (10 == modese_len) {
         resp_len = (buff[0] << 8) + buff[1] + 2;
         buff[3] &= 0xef;    /* for disks mask out DPOFUA bit */
@@ -2345,10 +2687,11 @@ int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len)
     return err;
 }
 
-/* Returns a negative value if failed to fetch Protocol specific port mode 
+/* Returns a negative value if failed to fetch Protocol specific port mode
    page or it was malformed. Returns transport protocol identifier when
    value >= 0 . */
-int scsiFetchTransportProtocol(scsi_device * device, int modese_len)
+int
+scsiFetchTransportProtocol(scsi_device * device, int modese_len)
 {
     int err, offset;
     UINT8 buff[64];
@@ -2371,12 +2714,70 @@ int scsiFetchTransportProtocol(scsi_device * device, int modese_len)
                               buff, sizeof(buff));
         if (err)
             return -EINVAL;
-    } 
+    }
     offset = scsiModePageOffset(buff, sizeof(buff), modese_len);
     if ((offset >= 0) && (buff[offset + 1] > 1)) {
         if ((0 == (buff[offset] & 0x40)) &&       /* SPF==0 */
-            (PROTOCOL_SPECIFIC_PORT_PAGE == (buff[offset] & 0x3f))) 
+            (PROTOCOL_SPECIFIC_PORT_PAGE == (buff[offset] & 0x3f)))
                 return (buff[offset + 2] & 0xf);
     }
     return -EINVAL;
 }
+
+const unsigned char *
+sg_scsi_sense_desc_find(const unsigned char * sensep, int sense_len,
+                        int desc_type)
+{
+    int add_sen_len, add_len, desc_len, k;
+    const unsigned char * descp;
+
+    if ((sense_len < 8) || (0 == (add_sen_len = sensep[7])))
+        return NULL;
+    if ((sensep[0] < 0x72) || (sensep[0] > 0x73))
+        return NULL;
+    add_sen_len = (add_sen_len < (sense_len - 8)) ?
+                         add_sen_len : (sense_len - 8);
+    descp = &sensep[8];
+    for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
+        descp += desc_len;
+        add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
+        desc_len = add_len + 2;
+        if (descp[0] == desc_type)
+            return descp;
+        if (add_len < 0) /* short descriptor ?? */
+            break;
+    }
+    return NULL;
+}
+
+// Convenience function for formatting strings from SCSI identify
+void
+scsi_format_id_string(char * out, const unsigned char * in, int n)
+{
+  char tmp[65];
+  n = n > 64 ? 64 : n;
+  strncpy(tmp, (const char *)in, n);
+  tmp[n] = '\0';
+
+  // Find the first non-space character (maybe none).
+  int first = -1;
+  int i;
+  for (i = 0; tmp[i]; i++)
+    if (!isspace((int)tmp[i])) {
+      first = i;
+      break;
+    }
+
+  if (first == -1) {
+    // There are no non-space characters.
+    out[0] = '\0';
+    return;
+  }
+
+  // Find the last non-space character.
+  for (i = strlen(tmp)-1; i >= first && isspace((int)tmp[i]); i--);
+  int last = i;
+
+  strncpy(out, tmp+first, last-first+1);
+  out[last-first+1] = '\0';
+}
index 3b311478857b39b6f2e3458647de0b0e05c3d089..afe656ecf99e154f4ad13a55420cee9a1ab35b0f 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
  *
  * Additional SCSI work:
- * Copyright (C) 2003-11 Douglas Gilbert <dgilbert@interlog.com>
+ * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
  *
  * 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
@@ -15,8 +15,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -32,7 +32,7 @@
 #ifndef SCSICMDS_H_
 #define SCSICMDS_H_
 
-#define SCSICMDS_H_CVSID "$Id: scsicmds.h 3413 2011-09-06 21:23:00Z dpgilbert $\n"
+#define SCSICMDS_H_CVSID "$Id: scsicmds.h 3783 2013-03-02 01:51:12Z dpgilbert $\n"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -78,6 +78,9 @@
 #ifndef READ_DEFECT_10
 #define READ_DEFECT_10  0x37
 #endif
+#ifndef READ_DEFECT_12
+#define READ_DEFECT_12  0xb7
+#endif
 #ifndef START_STOP_UNIT
 #define START_STOP_UNIT  0x1b
 #endif
@@ -114,11 +117,11 @@ struct scsi_cmnd_io
 {
     UINT8 * cmnd;       /* [in]: ptr to SCSI command block (cdb) */
     size_t  cmnd_len;   /* [in]: number of bytes in SCSI command */
-    int dxfer_dir;      /* [in]: DXFER_NONE, DXFER_FROM_DEVICE, or 
+    int dxfer_dir;      /* [in]: DXFER_NONE, DXFER_FROM_DEVICE, or
                                  DXFER_TO_DEVICE */
     UINT8 * dxferp;     /* [in]: ptr to outgoing or incoming data buffer */
     size_t dxfer_len;   /* [in]: bytes to be transferred to/from dxferp */
-    UINT8 * sensep;     /* [in]: ptr to sense buffer, filled when 
+    UINT8 * sensep;     /* [in]: ptr to sense buffer, filled when
                                  CHECK CONDITION status occurs */
     size_t max_sense_len; /* [in]: max number of bytes to write to sensep */
     unsigned timeout;   /* [in]: seconds, 0-> default timeout (60 seconds?) */
@@ -130,10 +133,11 @@ struct scsi_cmnd_io
 };
 
 struct scsi_sense_disect {
-    UINT8 error_code;
+    UINT8 resp_code;
     UINT8 sense_key;
-    UINT8 asc; 
+    UINT8 asc;
     UINT8 ascq;
+    int progress; /* -1 -> N/A, 0-65535 -> available */
 };
 
 /* Useful data from Informational Exception Control mode page (0x1c) */
@@ -201,7 +205,7 @@ struct scsiNonMediumError {
 /* Log page response lengths */
 #define LOG_RESP_SELF_TEST_LEN 0x194
 
-/* See the SSC-2 document at www.t10.org . Earler note: From IBM 
+/* See the SSC-2 document at www.t10.org . Earler note: From IBM
 Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
 #define TAPE_ALERTS_LPAGE                        0x2e
 
@@ -240,6 +244,18 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
 #define MPAGE_CONTROL_DEFAULT               2
 #define MPAGE_CONTROL_SAVED                 3
 
+/* SCSI Vital Product Data (VPD) pages */
+#define SCSI_VPD_SUPPORTED_VPD_PAGES    0x0
+#define SCSI_VPD_UNIT_SERIAL_NUMBER     0x80
+#define SCSI_VPD_DEVICE_IDENTIFICATION  0x83
+#define SCSI_VPD_EXTENDED_INQUIRY_DATA  0x86
+#define SCSI_VPD_ATA_INFORMATION        0x89
+#define SCSI_VPD_POWER_CONDITION        0x8a
+#define SCSI_VPD_POWER_CONSUMPTION      0x8d
+#define SCSI_VPD_BLOCK_LIMITS           0xb0
+#define SCSI_VPD_BLOCK_DEVICE_CHARACTERISTICS   0xb1
+#define SCSI_VPD_LOGICAL_BLOCK_PROVISIONING     0xb2
+
 /* defines for useful SCSI Status codes */
 #define SCSI_STATUS_CHECK_CONDITION     0x2
 
@@ -257,7 +273,7 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
 #define SCSI_ASC_NOT_READY              0x4     /* more info in ASCQ code */
 #define SCSI_ASC_NO_MEDIUM              0x3a    /* more info in ASCQ code */
 #define SCSI_ASC_UNKNOWN_OPCODE         0x20
-#define SCSI_ASC_UNKNOWN_FIELD          0x24
+#define SCSI_ASC_INVALID_FIELD          0x24
 #define SCSI_ASC_UNKNOWN_PARAM          0x26
 #define SCSI_ASC_WARNING                0xb
 #define SCSI_ASC_IMPENDING_FAILURE      0x5d
@@ -301,6 +317,27 @@ Documentation, see http://www.storage.ibm.com/techsup/hddtech/prodspecs.htm */
 
 class scsi_device;
 
+// Set of supported SCSI VPD pages. Constructor fetches Supported VPD pages
+// VPD page and remembers the response for later queries.
+class supported_vpd_pages
+{
+public:
+    supported_vpd_pages(scsi_device * device);
+    ~supported_vpd_pages() { num_valid = 0; }
+
+    bool is_supported(int vpd_page_num) const;
+
+    /* Returns 0 or less for VPD pages not supported or error */
+    int num_pages() const { return num_valid; }
+
+private:
+    int num_valid;      /* 0 or less for invalid */
+    unsigned char pages[256];
+};
+
+extern supported_vpd_pages * supported_vpd_pages_p;
+
+
 // Print SCSI debug messages?
 extern unsigned char scsi_debugmode;
 
@@ -354,14 +391,14 @@ int scsiReceiveDiagnostic(scsi_device * device, int pcv, int pagenum, UINT8 *pBu
 int scsiReadDefect10(scsi_device * device, int req_plist, int req_glist, int dl_format,
                      UINT8 *pBuf, int bufLen);
 
+int scsiReadDefect12(scsi_device * device, int req_plist, int req_glist,
+                     int dl_format, int addrDescIndex, UINT8 *pBuf, int bufLen);
+
 int scsiReadCapacity10(scsi_device * device, unsigned int * last_lbp,
                        unsigned int * lb_sizep);
 
 int scsiReadCapacity16(scsi_device * device, UINT8 *pBuf, int bufLen);
 
-uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep);
-
-
 /* SMART specific commands */
 int scsiCheckIE(scsi_device * device, int hasIELogPage, int hasTempLogPage, UINT8 *asc,
                 UINT8 *ascq, UINT8 *currenttemp, UINT8 *triptemp);
@@ -383,7 +420,12 @@ int scsiSelfTestInProgress(scsi_device * device, int * inProgress);
 int scsiFetchControlGLTSD(scsi_device * device, int modese_len, int current);
 int scsiSetControlGLTSD(scsi_device * device, int enabled, int modese_len);
 int scsiFetchTransportProtocol(scsi_device * device, int modese_len);
-
+int scsiGetRPM(scsi_device * device, int modese_len, int * form_factorp);
+int scsiGetSetCache(scsi_device * device,  int modese_len, short int * wce,
+                    short int * rcd);
+uint64_t scsiGetSize(scsi_device * device, unsigned int * lb_sizep,
+                     int * lb_per_pb_expp);
+int scsiGetProtPBInfo(scsi_device * device, unsigned char * rc16_12_31p);
 
 /* T10 Standard IE Additional Sense Code strings taken from t10.org */
 const char* scsiGetIEString(UINT8 asc, UINT8 ascq);
@@ -403,10 +445,18 @@ const char * scsiTapeAlertsTapeDevice(unsigned short code);
 const char * scsiTapeAlertsChangerDevice(unsigned short code);
 
 const char * scsi_get_opcode_name(UINT8 opcode);
+void scsi_format_id_string(char * out, const unsigned char * in, int n);
+
 void dStrHex(const char* str, int len, int no_ascii);
 inline void dStrHex(const unsigned char* str, int len, int no_ascii)
   { dStrHex((const char *)str, len, no_ascii); }
 
+/* Attempt to find the first SCSI sense data descriptor that matches the
+   given 'desc_type'. If found return pointer to start of sense data
+   descriptor; otherwise (including fixed format sense data) returns NULL. */
+const unsigned char * sg_scsi_sense_desc_find(const unsigned char * sensep,
+                                                     int sense_len, int desc_type);
+
 
 /* SCSI command transmission interface function declaration. Its
  * definition is target OS specific (see os_<OS>.c file).
@@ -422,4 +472,3 @@ inline void dStrHex(const unsigned char* str, int len, int no_ascii)
 
 
 #endif
-
index 3a3b95d3be9e0d268a117b566464001fcda4cec9..5c5b6e09fc0cb31320fb68820108bf309b4a885a 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
  *
  * Additional SCSI work:
- * Copyright (C) 2003-10 Douglas Gilbert <dgilbert@interlog.com>
+ * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
  *
  * 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
@@ -15,8 +15,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -42,7 +42,7 @@
 
 #define GBUF_SIZE 65535
 
-const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 3441 2011-10-12 17:22:15Z chrfranke $"
+const char * scsiprint_c_cvsid = "$Id: scsiprint.cpp 3807 2013-04-18 17:11:12Z chrfranke $"
                                  SCSIPRINT_H_CVSID;
 
 
@@ -76,17 +76,19 @@ static int gIecMPage = 1;     /* N.B. assume it until we know otherwise */
 /* Remember last successful mode sense/select command */
 static int modese_len = 0;
 
-static void scsiGetSupportedLogPages(scsi_device * device)
+
+static void
+scsiGetSupportedLogPages(scsi_device * device)
 {
     int i, err;
 
     if ((err = scsiLogSense(device, SUPPORTED_LPAGES, 0, gBuf,
                             LOG_RESP_LEN, 0))) {
         if (scsi_debugmode > 0)
-            pout("Log Sense for supported pages failed [%s]\n", 
-                 scsiErrString(err)); 
+            pout("Log Sense for supported pages failed [%s]\n",
+                 scsiErrString(err));
         return;
-    } 
+    }
 
     for (i = 4; i < gBuf[3] + LOGPAGEHDRSIZE; i++) {
         switch (gBuf[i])
@@ -144,7 +146,8 @@ static void scsiGetSupportedLogPages(scsi_device * device)
 
 /* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad
    (or at least something to report). */
-static int scsiGetSmartData(scsi_device * device, bool attribs)
+static int
+scsiGetSmartData(scsi_device * device, bool attribs)
 {
     UINT8 asc;
     UINT8 ascq;
@@ -152,7 +155,6 @@ static int scsiGetSmartData(scsi_device * device, bool attribs)
     UINT8 triptemp = 0;
     const char * cp;
     int err = 0;
-
     print_on();
     if (scsiCheckIE(device, gSmartLPage, gTempLPage, &asc, &ascq,
                     &currenttemp, &triptemp)) {
@@ -165,14 +167,12 @@ static int scsiGetSmartData(scsi_device * device, bool attribs)
     if (cp) {
         err = -2;
         print_on();
-        pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq); 
+        pout("SMART Health Status: %s [asc=%x, ascq=%x]\n", cp, asc, ascq);
         print_off();
     } else if (gIecMPage)
         pout("SMART Health Status: OK\n");
 
     if (attribs && !gTempLPage) {
-        if (currenttemp || triptemp)
-            pout("\n");
         if (currenttemp) {
             if (255 != currenttemp)
                 pout("Current Drive Temperature:     %d C\n", currenttemp);
@@ -182,6 +182,7 @@ static int scsiGetSmartData(scsi_device * device, bool attribs)
         if (triptemp)
             pout("Drive Trip Temperature:        %d C\n", triptemp);
     }
+    pout("\n");
     return err;
 }
 
@@ -190,7 +191,8 @@ static int scsiGetSmartData(scsi_device * device, bool attribs)
 // TapeAlerts fails
 static const char * const severities = "CWI";
 
-static int scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)
+static int
+scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)
 {
     unsigned short pagelength;
     unsigned short parametercode;
@@ -223,9 +225,10 @@ static int scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)
                     scsiTapeAlertsTapeDevice(parametercode);
                 if (*ts == *s) {
                     if (!failures)
-                        pout("TapeAlert Errors (C=Critical, W=Warning, I=Informational):\n");
+                        pout("TapeAlert Errors (C=Critical, W=Warning, "
+                             "I=Informational):\n");
                     pout("[0x%02x] %s\n", parametercode, ts);
-                    failures += 1; 
+                    failures += 1;
                 }
             }
         }
@@ -238,7 +241,8 @@ static int scsiGetTapeAlertsData(scsi_device * device, int peripheral_type)
     return failures;
 }
 
-static void scsiGetStartStopData(scsi_device * device)
+static void
+scsiGetStartStopData(scsi_device * device)
 {
     UINT32 u;
     int err, len, k, extra, pc;
@@ -312,21 +316,50 @@ static void scsiGetStartStopData(scsi_device * device)
             break;
         }
     }
-} 
+}
 
-static void scsiPrintGrownDefectListLen(scsi_device * device)
+static void
+scsiPrintGrownDefectListLen(scsi_device * device)
 {
-    int err, dl_format, dl_len, div;
+    int err, dl_format, got_rd12, generation;
+    unsigned int dl_len, div;
+
+    memset(gBuf, 0, 8);
+    if ((err = scsiReadDefect12(device, 0 /* req_plist */, 1 /* req_glist */,
+                                4 /* format: bytes from index */,
+                                0 /* addr desc index */, gBuf, 8))) {
+        if (2 == err) { /* command not supported */
+            if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */,
+                                        4 /* format: bytes from index */, gBuf, 4))) {
+                if (scsi_debugmode > 0) {
+                    print_on();
+                    pout("Read defect list (10) Failed: %s\n", scsiErrString(err));
+                    print_off();
+                }
+                return;
+            } else
+                got_rd12 = 0;
+        } else {
+            if (scsi_debugmode > 0) {
+                print_on();
+                pout("Read defect list (12) Failed: %s\n", scsiErrString(err));
+                print_off();
+            }
+            return;
+        }
+    } else
+        got_rd12 = 1;
 
-    memset(gBuf, 0, 4);
-    if ((err = scsiReadDefect10(device, 0 /* req_plist */, 1 /* req_glist */,
-                                4 /* bytes from index */, gBuf, 4))) {
-        if (scsi_debugmode > 0) {
+    if (got_rd12) {
+        generation = (gBuf[2] << 8) + gBuf[3];
+        if ((generation > 1) && (scsi_debugmode > 0)) {
             print_on();
-            pout("Read defect list (10) Failed: %s\n", scsiErrString(err));
+            pout("Read defect list (12): generation=%d\n", generation);
             print_off();
         }
-        return;
+        dl_len = (gBuf[4] << 24) + (gBuf[5] << 16) + (gBuf[6] << 8) + gBuf[7];
+    } else {
+        dl_len = (gBuf[2] << 8) + gBuf[3];
     }
     if (0x8 != (gBuf[1] & 0x18)) {
         print_on();
@@ -340,6 +373,11 @@ static void scsiPrintGrownDefectListLen(scsi_device * device)
         case 0:     /* short block */
             div = 4;
             break;
+        case 1:     /* extended bytes from index */
+        case 2:     /* extended physical sector */
+            /* extended = 1; # might use in future */
+            div = 8;
+            break;
         case 3:     /* long block */
         case 4:     /* bytes from index */
         case 5:     /* physical sector */
@@ -351,19 +389,19 @@ static void scsiPrintGrownDefectListLen(scsi_device * device)
             print_off();
             break;
     }
-    dl_len = (gBuf[2] << 8) + gBuf[3];
     if (0 == dl_len)
-        pout("Elements in grown defect list: 0\n");
+        pout("Elements in grown defect list: 0\n\n");
     else {
         if (0 == div)
-            pout("Grown defect list length=%d bytes [unknown "
-                 "number of elements]\n", dl_len);
+            pout("Grown defect list length=%u bytes [unknown "
+                 "number of elements]\n\n", dl_len);
         else
-            pout("Elements in grown defect list: %d\n", dl_len / div);
+            pout("Elements in grown defect list: %u\n\n", dl_len / div);
     }
 }
 
-static void scsiPrintSeagateCacheLPage(scsi_device * device)
+static void
+scsiPrintSeagateCacheLPage(scsi_device * device)
 {
     int k, j, num, pl, pc, err, len;
     unsigned char * ucp;
@@ -392,7 +430,7 @@ static void scsiPrintSeagateCacheLPage(scsi_device * device)
         switch (pc) {
         case 0: case 1: case 2: case 3: case 4:
             break;
-        default: 
+        default:
             if (scsi_debugmode > 0) {
                 print_on();
                 pout("Vendor (Seagate) cache lpage has unexpected parameter"
@@ -436,9 +474,11 @@ static void scsiPrintSeagateCacheLPage(scsi_device * device)
         num -= pl;
         ucp += pl;
     }
+    pout("\n");
 }
 
-static void scsiPrintSeagateFactoryLPage(scsi_device * device)
+static void
+scsiPrintSeagateFactoryLPage(scsi_device * device)
 {
     int k, j, num, pl, pc, len, err, good, bad;
     unsigned char * ucp;
@@ -470,7 +510,7 @@ static void scsiPrintSeagateFactoryLPage(scsi_device * device)
         case 0: case 8:
             ++good;
             break;
-        default: 
+        default:
             ++bad;
             break;
         }
@@ -530,9 +570,11 @@ static void scsiPrintSeagateFactoryLPage(scsi_device * device)
         num -= pl;
         ucp += pl;
     }
+    pout("\n");
 }
 
-static void scsiPrintErrorCounterLog(scsi_device * device)
+static void
+scsiPrintErrorCounterLog(scsi_device * device)
 {
     struct scsiErrorCounter errCounterArr[3];
     struct scsiErrorCounter * ecp;
@@ -563,7 +605,7 @@ static void scsiPrintErrorCounterLog(scsi_device * device)
         }
     }
     if (found[0] || found[1] || found[2]) {
-        pout("\nError counter log:\n");
+        pout("Error counter log:\n");
         pout("           Errors Corrected by           Total   "
              "Correction     Gigabytes    Total\n");
         pout("               ECC          rereads/    errors   "
@@ -574,15 +616,15 @@ static void scsiPrintErrorCounterLog(scsi_device * device)
             if (! found[k])
                 continue;
             ecp = &errCounterArr[k];
-            pout("%s%8"PRIu64" %8"PRIu64"  %8"PRIu64"  %8"PRIu64"   %8"PRIu64, 
-                 pageNames[k], ecp->counter[0], ecp->counter[1], 
+            pout("%s%8"PRIu64" %8"PRIu64"  %8"PRIu64"  %8"PRIu64"   %8"PRIu64,
+                 pageNames[k], ecp->counter[0], ecp->counter[1],
                  ecp->counter[2], ecp->counter[3], ecp->counter[4]);
             processed_gb = ecp->counter[5] / 1000000000.0;
             pout("   %12.3f    %8"PRIu64"\n", processed_gb, ecp->counter[6]);
         }
     }
-    else 
-        pout("\nError Counter logging not supported\n");
+    else
+        pout("Error Counter logging not supported\n");
     if (gNonMediumELPage && (0 == scsiLogSense(device,
                 NON_MEDIUM_ERROR_LPAGE, 0, gBuf, LOG_RESP_LEN, 0))) {
         scsiDecodeNonMediumErrPage(gBuf, &nme);
@@ -636,15 +678,16 @@ static void scsiPrintErrorCounterLog(scsi_device * device)
                      "bytes\n", LOG_RESP_LONG_LEN, truncated);
         }
     }
+    pout("\n");
 }
 
 static const char * self_test_code[] = {
-        "Default         ", 
-        "Background short", 
-        "Background long ", 
+        "Default         ",
+        "Background short",
+        "Background long ",
         "Reserved(3)     ",
-        "Abort background", 
-        "Foreground short", 
+        "Abort background",
+        "Foreground short",
         "Foreground long ",
         "Reserved(7)     "
 };
@@ -658,12 +701,12 @@ static const char * self_test_result[] = {
         "Failed in first segment  ",
         "Failed in second segment ",
         "Failed in segment -->    ",
-        "Reserved(8)              ", 
-        "Reserved(9)              ", 
-        "Reserved(10)             ", 
-        "Reserved(11)             ", 
-        "Reserved(12)             ", 
-        "Reserved(13)             ", 
+        "Reserved(8)              ",
+        "Reserved(9)              ",
+        "Reserved(10)             ",
+        "Reserved(11)             ",
+        "Reserved(12)             ",
+        "Reserved(13)             ",
         "Reserved(14)             ",
         "Self test in progress ..."
 };
@@ -672,13 +715,23 @@ static const char * self_test_result[] = {
 // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent
 // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or
 // FAILSMART is returned.
-static int scsiPrintSelfTest(scsi_device * device)
+static int
+scsiPrintSelfTest(scsi_device * device)
 {
     int num, k, n, res, err, durationSec;
     int noheader = 1;
     int retval = 0;
     UINT8 * ucp;
     uint64_t ull=0;
+    struct scsi_sense_disect sense_info;
+
+    // check if test is running
+    if (!scsiRequestSense(device, &sense_info) &&
+                        (sense_info.asc == 0x04 && sense_info.ascq == 0x09 &&
+                        sense_info.progress != -1)) {
+        pout("Self-test execution status:\t\t%d%% of test remaining\n",
+             100 - ((sense_info.progress * 100) / 65535));
+    }
 
     if ((err = scsiLogSense(device, SELFTEST_RESULTS_LPAGE, 0, gBuf,
                             LOG_RESP_SELF_TEST_LEN, 0))) {
@@ -716,7 +769,7 @@ static int scsiPrintSelfTest(scsi_device * device)
 
         // only print header if needed
         if (noheader) {
-            pout("\nSMART Self-test log\n");
+            pout("SMART Self-test log\n");
             pout("Num  Test              Status                 segment  "
                    "LifeTime  LBA_first_err [SK ASC ASQ]\n");
             pout("     Description                              number   "
@@ -725,7 +778,7 @@ static int scsiPrintSelfTest(scsi_device * device)
         }
 
         // print parameter code (test number) & self-test code text
-        pout("#%2d  %s", (ucp[0] << 8) | ucp[1], 
+        pout("#%2d  %s", (ucp[0] << 8) | ucp[1],
             self_test_code[(ucp[4] >> 5) & 0x7]);
 
         // check the self-test result nibble, using the self-test results
@@ -777,9 +830,9 @@ static int scsiPrintSelfTest(scsi_device * device)
         if (n==0 && res==0xf)
         // self-test in progress
             pout("     NOW");
-        else   
+        else
             pout("   %5d", n);
-          
+
         // construct 8-byte integer address of first failure
         for (i = 0; i < 8; i++) {
             ull <<= 8;
@@ -808,12 +861,12 @@ static int scsiPrintSelfTest(scsi_device * device)
     if (noheader)
         pout("No self-tests have been logged\n");
     else
-        pout("\n");
     if ((0 == scsiFetchExtendedSelfTestTime(device, &durationSec,
                         modese_len)) && (durationSec > 0)) {
         pout("Long (extended) Self Test duration: %d seconds "
              "[%.1f minutes]\n", durationSec, durationSec / 60.0);
     }
+    pout("\n");
     return retval;
 }
 
@@ -845,7 +898,8 @@ static const char * reassign_status[] = {
 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
 // and up to 2048 events (although would hope to have less). May set
 // FAILLOG if serious errors detected (in the future).
-static int scsiPrintBackgroundResults(scsi_device * device)
+static int
+scsiPrintBackgroundResults(scsi_device * device)
 {
     int num, j, m, err, pc, pl, truncated;
     int noheader = 1;
@@ -888,7 +942,7 @@ static int scsiPrintBackgroundResults(scsi_device * device)
         case 0:
             if (noheader) {
                 noheader = 0;
-                pout("\nBackground scan results log\n");
+                pout("Background scan results log\n");
             }
             pout("  Status: ");
             if ((pl < 16) || (num < 16)) {
@@ -945,6 +999,7 @@ static int scsiPrintBackgroundResults(scsi_device * device)
     if (truncated)
         pout(" >>>> log truncated, fetched %d of %d available "
              "bytes\n", LOG_RESP_LONG_LEN, truncated);
+    pout("\n");
     return retval;
 }
 
@@ -952,7 +1007,8 @@ static int scsiPrintBackgroundResults(scsi_device * device)
 // Returns 0 if ok else FAIL* bitmask. Note can have a status entry
 // and up to 2048 events (although would hope to have less). May set
 // FAILLOG if serious errors detected (in the future).
-static int scsiPrintSSMedia(scsi_device * device)
+static int
+scsiPrintSSMedia(scsi_device * device)
 {
     int num, err, pc, pl, truncated;
     int retval = 0;
@@ -990,14 +1046,14 @@ static int scsiPrintSSMedia(scsi_device * device)
         pl = ucp[3] + 4;
         switch (pc) {
         case 1:
-           if (pl < 8) {
+            if (pl < 8) {
                 print_on();
                 pout("Percentage used endurance indicator too short (pl=%d)\n", pl);
                 print_off();
                 return FAILSMART;
-           }
+            }
             pout("SS Media used endurance indicator: %d%%\n", ucp[7]);
-        default:       /* ignore other parameter codes */
+        default:        /* ignore other parameter codes */
             break;
         }
         num -= pl;
@@ -1006,8 +1062,8 @@ static int scsiPrintSSMedia(scsi_device * device)
     return retval;
 }
 
-static void show_sas_phy_event_info(int peis, unsigned int val,
-                                    unsigned thresh_val)
+static void
+show_sas_phy_event_info(int peis, unsigned int val, unsigned thresh_val)
 {
     unsigned int u;
 
@@ -1137,7 +1193,8 @@ static void show_sas_phy_event_info(int peis, unsigned int val,
     }
 }
 
-static void show_sas_port_param(unsigned char * ucp, int param_len)
+static void
+show_sas_port_param(unsigned char * ucp, int param_len)
 {
     int j, m, n, nphys, t, sz, spld_len;
     unsigned char * vcp;
@@ -1268,7 +1325,8 @@ static void show_sas_port_param(unsigned char * ucp, int param_len)
 }
 
 // Returns 1 if okay, 0 if non SAS descriptors
-static int show_protocol_specific_page(unsigned char * resp, int len)
+static int
+show_protocol_specific_page(unsigned char * resp, int len)
 {
     int k, num, param_len;
     unsigned char * ucp;
@@ -1284,6 +1342,7 @@ static int show_protocol_specific_page(unsigned char * resp, int len)
         k += param_len;
         ucp += param_len;
     }
+    pout("\n");
     return 1;
 }
 
@@ -1294,20 +1353,21 @@ static int show_protocol_specific_page(unsigned char * resp, int len)
 // Returns 0 if ok else FAIL* bitmask. Note that if any of the most recent
 // 20 self tests fail (result code 3 to 7 inclusive) then FAILLOG and/or
 // FAILSMART is returned.
-static int scsiPrintSasPhy(scsi_device * device, int reset)
+static int
+scsiPrintSasPhy(scsi_device * device, int reset)
 {
     int num, err;
 
     if ((err = scsiLogSense(device, PROTOCOL_SPECIFIC_LPAGE, 0, gBuf,
                             LOG_RESP_LONG_LEN, 0))) {
         print_on();
-        pout("scsiPrintSasPhy Log Sense Failed [%s]\n", scsiErrString(err));
+        pout("scsiPrintSasPhy Log Sense Failed [%s]\n\n", scsiErrString(err));
         print_off();
         return FAILSMART;
     }
     if ((gBuf[0] & 0x3f) != PROTOCOL_SPECIFIC_LPAGE) {
         print_on();
-        pout("Protocol specific Log Sense Failed, page mismatch\n");
+        pout("Protocol specific Log Sense Failed, page mismatch\n\n");
         print_off();
         return FAILSMART;
     }
@@ -1315,7 +1375,7 @@ static int scsiPrintSasPhy(scsi_device * device, int reset)
     num = (gBuf[2] << 8) + gBuf[3];
     if (1 != show_protocol_specific_page(gBuf, num + 4)) {
         print_on();
-        pout("Only support protocol specific log page on SAS devices\n");
+        pout("Only support protocol specific log page on SAS devices\n\n");
         print_off();
         return FAILSMART;
     }
@@ -1323,7 +1383,7 @@ static int scsiPrintSasPhy(scsi_device * device, int reset)
         if ((err = scsiLogSelect(device, 1 /* pcr */, 0 /* sp */, 0 /* pc */,
                                  PROTOCOL_SPECIFIC_LPAGE, 0, NULL, 0))) {
             print_on();
-            pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n",
+            pout("scsiPrintSasPhy Log Select (reset) Failed [%s]\n\n",
                  scsiErrString(err));
             print_off();
             return FAILSMART;
@@ -1372,16 +1432,19 @@ static const char * transport_proto_arr[] = {
 };
 
 /* Returns 0 on success, 1 on general error and 2 for early, clean exit */
-static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)
+static int
+scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all)
 {
     char timedatetz[DATEANDEPOCHLEN];
     struct scsi_iec_mode_page iec;
-    int err, iec_err, len, req_len, avail_len;
+    int err, iec_err, len, req_len, avail_len, n;
     int is_tape = 0;
     int peri_dt = 0;
     int returnval = 0;
     int transport = -1;
-        
+    int form_factor = 0;
+    int protect = 0;
+
     memset(gBuf, 0, 96);
     req_len = 36;
     if ((err = scsiStdInquiry(device, gBuf, req_len))) {
@@ -1411,11 +1474,18 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
         print_off();
         return 1;
     }
+
     if (all && (0 != strncmp((char *)&gBuf[8], "ATA", 3))) {
-        pout("Vendor:               %.8s\n", (char *)&gBuf[8]);
-       pout("Product:              %.16s\n", (char *)&gBuf[16]);
-       if (gBuf[32] >= ' ')
-           pout("Revision:             %.4s\n", (char *)&gBuf[32]);
+        char vendor[8+1], product[16+1], revision[4+1];
+        scsi_format_id_string(vendor, (const unsigned char *)&gBuf[8], 8);
+        scsi_format_id_string(product, (const unsigned char *)&gBuf[16], 16);
+        scsi_format_id_string(revision, (const unsigned char *)&gBuf[32], 4);
+
+        pout("=== START OF INFORMATION SECTION ===\n");
+        pout("Vendor:               %.8s\n", vendor);
+        pout("Product:              %.16s\n", product);
+        if (gBuf[32] >= ' ')
+            pout("Revision:             %.4s\n", revision);
     }
 
     if (!*device->get_req_type()/*no type requested*/ &&
@@ -1427,18 +1497,122 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
     if (! all)
         return 0;
 
-    unsigned int lb_size;
-    char cap_str[64];
-    char si_str[64];
-    char lb_str[16];
-    uint64_t capacity = scsiGetSize(device, &lb_size);
+    protect = gBuf[5] & 0x1;    /* from and including SPC-3 */
+
+    if (! is_tape) {    /* only do this for disks */
+        unsigned int lb_size = 0;
+        unsigned char lb_prov_resp[8];
+        char cap_str[64];
+        char si_str[64];
+        char lb_str[16];
+        int lb_per_pb_exp = 0;
+        uint64_t capacity = scsiGetSize(device, &lb_size, &lb_per_pb_exp);
+
+        if (capacity) {
+            format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);
+            format_capacity(si_str, sizeof(si_str), capacity);
+            pout("User Capacity:        %s bytes [%s]\n", cap_str, si_str);
+            snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);
+            pout("Logical block size:   %s bytes\n", lb_str);
+        }
+        int lbpme = -1;
+        int lbprz = -1;
+        if (protect || lb_per_pb_exp) {
+            unsigned char rc16_12[20] = {0, };
+
+            if (0 == scsiGetProtPBInfo(device, rc16_12)) {
+                lb_per_pb_exp = rc16_12[1] & 0xf;       /* just in case */
+                if (lb_per_pb_exp > 0) {
+                    snprintf(lb_str, sizeof(lb_str) - 1, "%u",
+                             (lb_size * (1 << lb_per_pb_exp)));
+                    pout("Physical block size:  %s bytes\n", lb_str);
+                    n = ((rc16_12[2] & 0x3f) << 8) + rc16_12[3];
+                    pout("Lowest aligned LBA:   %d\n", n);
+                }
+                if (rc16_12[0] & 0x1) { /* PROT_EN set */
+                    int p_type = ((rc16_12[0] >> 1) & 0x7);
+
+                    switch (p_type) {
+                    case 0 :
+                        pout("Formatted with type 1 protection\n");
+                        break;
+                    case 1 :
+                        pout("Formatted with type 2 protection\n");
+                        break;
+                    case 2 :
+                        pout("Formatted with type 3 protection\n");
+                        break;
+                    default:
+                        pout("Formatted with unknown protection type [%d]\n",
+                             p_type);
+                        break;
+                    }
+                    int p_i_exp = ((rc16_12[1] >> 4) & 0xf);
+
+                    if (p_i_exp > 0)
+                        pout("%d protection information intervals per "
+                             "logical block\n", (1 << p_i_exp));
+                }
+                /* Pick up some LB provisioning info since its available */
+                lbpme = !! (rc16_12[2] & 0x80);
+                lbprz = !! (rc16_12[2] & 0x40);
+            }
+        }
+        if (0 == scsiInquiryVpd(device, SCSI_VPD_LOGICAL_BLOCK_PROVISIONING,
+                                lb_prov_resp, sizeof(lb_prov_resp))) {
+            int prov_type = lb_prov_resp[6] & 0x7;
+
+            if (-1 == lbprz)
+                lbprz = !! (lb_prov_resp[5] & 0x4);
+            switch (prov_type) {
+            case 0:
+                pout("Logical block provisioning type unreported, "
+                     "LBPME=%d, LBPRZ=%d\n", lbpme, lbprz);
+                break;
+            case 1:
+                pout("LU is resource provisioned, LBPRZ=%d\n", lbprz);
+                break;
+            case 2:
+                pout("LU is thin provisioned, LBPRZ=%d\n", lbprz);
+                break;
+            default:
+                pout("LU provisioning type reserved [%d], LBPRZ=%d\n",
+                     prov_type, lbprz);
+                break;
+            }
+        } else if (1 == lbpme)
+            pout("Logical block provisioning enabled, LBPRZ=%d\n", lbprz);
 
-    if (capacity) {
-        format_with_thousands_sep(cap_str, sizeof(cap_str), capacity);
-        format_capacity(si_str, sizeof(si_str), capacity);
-        pout("User Capacity:        %s bytes [%s]\n", cap_str, si_str);
-        snprintf(lb_str, sizeof(lb_str) - 1, "%u", lb_size);
-        pout("Logical block size:   %s bytes\n", lb_str);
+        int rpm = scsiGetRPM(device, modese_len, &form_factor);
+        if (rpm > 0) {
+            if (1 == rpm)
+                pout("Rotation Rate:        Solid State Device\n");
+            else
+                pout("Rotation Rate:        %d rpm\n", rpm);
+        }
+        if (form_factor > 0) {
+            const char * cp = NULL;
+
+            switch (form_factor) {
+            case 1:
+                cp = "5.25";
+                break;
+            case 2:
+                cp = "3.5";
+                break;
+            case 3:
+                cp = "2.5";
+                break;
+            case 4:
+                cp = "1.8";
+                break;
+            case 5:
+                cp = "< 1.8";
+                break;
+            }
+            if (cp)
+                pout("Form Factor:          %s inches\n", cp);
+        }
     }
 
     /* Do this here to try and detect badly conforming devices (some USB
@@ -1455,12 +1629,13 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
         modese_len = iec.modese_len;
 
     if (! dont_print_serial_number) {
-       if (0 == (err = scsiInquiryVpd(device, 0x83, gBuf, 200))) {
-           char s[256];
+        if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_DEVICE_IDENTIFICATION,
+                                       gBuf, 252))) {
+            char s[256];
 
             len = gBuf[3];
-           scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);
-           if (strlen(s) > 0)
+            scsi_decode_lu_dev_id(gBuf + 4, len, s, sizeof(s), &transport);
+            if (strlen(s) > 0)
                 pout("Logical Unit id:      %s\n", s);
         } else if (scsi_debugmode > 0) {
             print_on();
@@ -1470,10 +1645,14 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
                 pout("Vital Product Data (VPD) INQUIRY failed [%d]\n", err);
             print_off();
         }
-       if (0 == (err = scsiInquiryVpd(device, 0x80, gBuf, 64))) {
+        if (0 == (err = scsiInquiryVpd(device, SCSI_VPD_UNIT_SERIAL_NUMBER,
+                                       gBuf, 252))) {
+            char serial[256];
             len = gBuf[3];
+
             gBuf[4 + len] = '\0';
-            pout("Serial number:        %s\n", &gBuf[4]);
+            scsi_format_id_string(serial, &gBuf[4], len);
+            pout("Serial number:        %s\n", serial);
         } else if (scsi_debugmode > 0) {
             print_on();
             if (SIMPLE_ERR_BAD_RESP == err)
@@ -1485,7 +1664,7 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
     }
 
     // print SCSI peripheral device type
-    if (peri_dt < (int)(sizeof(peripheral_dt_arr) / 
+    if (peri_dt < (int)(sizeof(peripheral_dt_arr) /
                         sizeof(peripheral_dt_arr[0])))
         pout("Device type:          %s\n", peripheral_dt_arr[peri_dt]);
     else
@@ -1528,15 +1707,13 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
         }
         failuretest(MANDATORY_CMD, returnval|=FAILID);
     }
-   
+
     if (iec_err) {
         if (!is_tape) {
             print_on();
-            pout("Device does not support SMART");
+            pout("SMART support is:     Unavailable - device lacks SMART capability.\n");
             if (scsi_debugmode > 0)
                 pout(" [%s]\n", scsiErrString(iec_err));
-            else
-                pout("\n");
             print_off();
         }
         gIecMPage = 0;
@@ -1544,22 +1721,24 @@ static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool
     }
 
     if (!is_tape)
-        pout("Device supports SMART and is %s\n",
+        pout("SMART support is:     Available - device has SMART capability.\n"
+             "SMART support is:     %s\n",
              (scsi_IsExceptionControlEnabled(&iec)) ? "Enabled" : "Disabled");
-    pout("%s\n", (scsi_IsWarningEnabled(&iec)) ? 
-                  "Temperature Warning Enabled" :
-                  "Temperature Warning Disabled or Not Supported");
+    pout("%s\n", (scsi_IsWarningEnabled(&iec)) ?
+                  "Temperature Warning Enabled" :
+                  "Temperature Warning Disabled or Not Supported");
     return 0;
 }
 
-static int scsiSmartEnable(scsi_device * device)
+static int
+scsiSmartEnable(scsi_device * device)
 {
     struct scsi_iec_mode_page iec;
     int err;
 
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
         print_on();
-        pout("unable to fetch IEC (SMART) mode page [%s]\n", 
+        pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));
         print_off();
         return 1;
@@ -1575,7 +1754,7 @@ static int scsiSmartEnable(scsi_device * device)
     }
     /* Need to refetch 'iec' since could be modified by previous call */
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
-        pout("unable to fetch IEC (SMART) mode page [%s]\n", 
+        pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));
         return 1;
     } else
@@ -1587,15 +1766,16 @@ static int scsiSmartEnable(scsi_device * device)
          scsi_IsWarningEnabled(&iec) ? "enabled" : "disabled");
     return 0;
 }
-        
-static int scsiSmartDisable(scsi_device * device)
+
+static int
+scsiSmartDisable(scsi_device * device)
 {
     struct scsi_iec_mode_page iec;
     int err;
 
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
         print_on();
-        pout("unable to fetch IEC (SMART) mode page [%s]\n", 
+        pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));
         print_off();
         return 1;
@@ -1611,7 +1791,7 @@ static int scsiSmartDisable(scsi_device * device)
     }
     /* Need to refetch 'iec' since could be modified by previous call */
     if ((err = scsiFetchIECmpage(device, &iec, modese_len))) {
-        pout("unable to fetch IEC (SMART) mode page [%s]\n", 
+        pout("unable to fetch IEC (SMART) mode page [%s]\n",
              scsiErrString(err));
         return 1;
     } else
@@ -1624,14 +1804,15 @@ static int scsiSmartDisable(scsi_device * device)
     return 0;
 }
 
-static void scsiPrintTemp(scsi_device * device)
+static void
+scsiPrintTemp(scsi_device * device)
 {
     UINT8 temp = 0;
     UINT8 trip = 0;
 
     if (scsiGetTemp(device, &temp, &trip))
         return;
-  
+
     if (temp) {
         if (255 != temp)
             pout("Current Drive Temperature:     %d C\n", temp);
@@ -1640,55 +1821,140 @@ static void scsiPrintTemp(scsi_device * device)
     }
     if (trip)
         pout("Drive Trip Temperature:        %d C\n", trip);
+    if (temp || trip)
+        pout("\n");
 }
 
 /* Main entry point used by smartctl command. Return 0 for success */
-int scsiPrintMain(scsi_device * device, const scsi_print_options & options)
+int
+scsiPrintMain(scsi_device * device, const scsi_print_options & options)
 {
     int checkedSupportedLogPages = 0;
     UINT8 peripheral_type = 0;
     int returnval = 0;
     int res, durationSec;
+    struct scsi_sense_disect sense_info;
 
     bool any_output = options.drive_info;
 
+    if (supported_vpd_pages_p) {
+        delete supported_vpd_pages_p;
+        supported_vpd_pages_p = NULL;
+    }
+    supported_vpd_pages_p = new supported_vpd_pages(device);
+
     res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info);
     if (res) {
         if (2 == res)
             return 0;
         else
             failuretest(MANDATORY_CMD, returnval |= FAILID);
-       any_output = true;
+        any_output = true;
     }
 
+  // Print read look-ahead status for disks
+  short int wce = -1, rcd = -1;
+  if (options.get_rcd || options.get_wce) {
+    if (SCSI_PT_DIRECT_ACCESS == peripheral_type)
+       res = scsiGetSetCache(device, modese_len, &wce, &rcd);
+    else
+       res = -1; // fetch for disks only
+    any_output = true;
+  }
+
+  if (options.get_rcd) {
+    pout("Read Cache is:        %s\n",
+      res ? "Unavailable" : // error
+      rcd ? "Disabled" : "Enabled");
+   }
+
+  if (options.get_wce) {
+    pout("Writeback Cache is:   %s\n",
+      res ? "Unavailable" : // error
+      !wce ? "Disabled" : "Enabled");
+   }
+   if (options.drive_info)
+     pout("\n");
+
+  // START OF THE ENABLE/DISABLE SECTION OF THE CODE
+  if (   options.smart_disable           || options.smart_enable
+      || options.smart_auto_save_disable || options.smart_auto_save_enable)
+    pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n");
+
     if (options.smart_enable) {
         if (scsiSmartEnable(device))
             failuretest(MANDATORY_CMD, returnval |= FAILSMART);
-       any_output = true;
+        any_output = true;
     }
 
     if (options.smart_disable) {
         if (scsiSmartDisable(device))
             failuretest(MANDATORY_CMD,returnval |= FAILSMART);
-       any_output = true;
+        any_output = true;
     }
-    
+
     if (options.smart_auto_save_enable) {
       if (scsiSetControlGLTSD(device, 0, modese_len)) {
         pout("Enable autosave (clear GLTSD bit) failed\n");
         failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
       }
+      else {
+         pout("Autosave enabled (GLTSD bit set).\n");
+      }
+      any_output = true;
+    }
+
+    // Enable/Disable write cache
+    if (options.set_wce && SCSI_PT_DIRECT_ACCESS == peripheral_type) {
+      short int enable = wce = (options.set_wce > 0);
+      rcd = -1;
+      if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
+          pout("Write cache %sable failed: %s\n", (enable ? "en" : "dis"),
+               device->get_errmsg());
+          failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
+      }
+      else
+        pout("Write cache %sabled\n", (enable ? "en" : "dis"));
+      any_output = true;
+    }
+
+    // Enable/Disable read cache
+    if (options.set_rcd && SCSI_PT_DIRECT_ACCESS == peripheral_type) {
+      short int enable =  (options.set_rcd > 0);
+      rcd = !enable;
+      wce = -1;
+      if (scsiGetSetCache(device, modese_len, &wce, &rcd)) {
+          pout("Read cache %sable failed: %s\n", (enable ? "en" : "dis"),
+                device->get_errmsg());
+          failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
+      }
+      else
+        pout("Read cache %sabled\n", (enable ? "en" : "dis"));
       any_output = true;
     }
-    
+
     if (options.smart_auto_save_disable) {
       if (scsiSetControlGLTSD(device, 1, modese_len)) {
         pout("Disable autosave (set GLTSD bit) failed\n");
         failuretest(OPTIONAL_CMD,returnval |= FAILSMART);
       }
+      else {
+         pout("Autosave disabled (GLTSD bit cleared).\n");
+      }
       any_output = true;
     }
-    
+  if (   options.smart_disable           || options.smart_enable
+      || options.smart_auto_save_disable || options.smart_auto_save_enable)
+    pout("\n"); // END OF THE ENABLE/DISABLE SECTION OF THE CODE
+
+    // START OF READ-ONLY OPTIONS APART FROM -V and -i
+    if (    options.smart_check_status  || options.smart_ss_media_log
+           || options.smart_vendor_attrib || options.smart_error_log
+           || options.smart_selftest_log  || options.smart_vendor_attrib
+           || options.smart_background_log || options.sasphy
+         )
+    pout("=== START OF READ SMART DATA SECTION ===\n");
+
     if (options.smart_check_status) {
         scsiGetSupportedLogPages(device);
         checkedSupportedLogPages = 1;
@@ -1711,7 +1977,8 @@ int scsiPrintMain(scsi_device * device, const scsi_print_options & options)
             }
         }
         any_output = true;
-    }   
+    }
+
     if (options.smart_ss_media_log) {
         if (! checkedSupportedLogPages)
             scsiGetSupportedLogPages(device);
@@ -1726,8 +1993,6 @@ int scsiPrintMain(scsi_device * device, const scsi_print_options & options)
         if (! checkedSupportedLogPages)
             scsiGetSupportedLogPages(device);
         if (gTempLPage) {
-            if (options.smart_check_status)
-                pout("\n");
             scsiPrintTemp(device);
         }
         if (gStartStopLPage)
@@ -1790,6 +2055,24 @@ int scsiPrintMain(scsi_device * device, const scsi_print_options & options)
         pout("Short Foreground Self Test Successful\n");
         any_output = true;
     }
+    // check if another test is running
+    if (options.smart_short_selftest || options.smart_extend_selftest) {
+      if (!scsiRequestSense(device, &sense_info) &&
+            (sense_info.asc == 0x04 && sense_info.ascq == 0x09)) {
+         if (!options.smart_selftest_force) {
+           pout("Can't start self-test without aborting current test");
+           if (sense_info.progress != -1) {
+             pout(" (%d%% remaining)",
+                  100 - sense_info.progress * 100 / 65535);
+           }
+           pout(",\nadd '-t force' option to override, or run 'smartctl -X' "
+                "to abort test.\n");
+            return -1;
+         }
+         else
+            scsiSmartSelfTestAbort(device);
+       }
+    }
     if (options.smart_short_selftest) {
         if (scsiSmartShortSelfTest(device))
             return returnval | FAILSMART;
@@ -1806,11 +2089,11 @@ int scsiPrintMain(scsi_device * device, const scsi_print_options & options)
             time_t t = time(NULL);
 
             t += durationSec;
-            pout("Please wait %d minutes for test to complete.\n", 
+            pout("Please wait %d minutes for test to complete.\n",
                  durationSec / 60);
             pout("Estimated completion time: %s\n", ctime(&t));
         }
-        pout("Use smartctl -X to abort test\n");        
+        pout("Use smartctl -X to abort test\n");
         any_output = true;
     }
     if (options.smart_extend_cap_selftest) {
@@ -1823,12 +2106,12 @@ int scsiPrintMain(scsi_device * device, const scsi_print_options & options)
             return returnval | FAILSMART;
         pout("Self Test returned without error\n");
         any_output = true;
-    }           
+    }
     if (options.sasphy) {
         if (scsiPrintSasPhy(device, options.sasphy_reset))
             return returnval | FAILSMART;
         any_output = true;
-    }           
+    }
 
     if (!any_output)
       pout("SCSI device successfully opened\n\n"
index fc332f60cc159bef49286629dea9aee2fd73273e..fad594de9c197f48430f03b99cee14013642ffee 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
  *
  * Additional SCSI work:
- * Copyright (C) 2003-10 Douglas Gilbert <dgilbert@interlog.com>
+ * Copyright (C) 2003-13 Douglas Gilbert <dgilbert@interlog.com>
  *
  * 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
@@ -15,8 +15,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -29,7 +29,7 @@
 #ifndef SCSI_PRINT_H_
 #define SCSI_PRINT_H_
 
-#define SCSIPRINT_H_CVSID "$Id: scsiprint.h 3413 2011-09-06 21:23:00Z dpgilbert $\n"
+#define SCSIPRINT_H_CVSID "$Id: scsiprint.h 3776 2013-02-17 04:25:42Z dpgilbert $\n"
 
 // Options for scsiPrintMain
 struct scsi_print_options
@@ -49,8 +49,12 @@ struct scsi_print_options
   bool smart_short_selftest, smart_short_cap_selftest;
   bool smart_extend_selftest, smart_extend_cap_selftest;
   bool smart_selftest_abort;
+  bool smart_selftest_force; // Ignore already running test
 
   bool sasphy, sasphy_reset;
+  
+  bool get_wce, get_rcd;
+  short int set_wce, set_rcd;  // disable(-1), enable(1) cache
 
   scsi_print_options()
     : drive_info(false),
@@ -66,7 +70,10 @@ struct scsi_print_options
       smart_short_selftest(false), smart_short_cap_selftest(false),
       smart_extend_selftest(false), smart_extend_cap_selftest(false),
       smart_selftest_abort(false),
-      sasphy(false), sasphy_reset(false)
+      smart_selftest_force(false),
+      sasphy(false), sasphy_reset(false),
+      get_wce(false), get_rcd(false),
+      set_wce(0), set_rcd(0)
     { }
 };
 
index 42ea7192fcbe8244406af30635ba82c076a742b9..c30e03e570627831a49489ad420a5dcc8174eafd 100644 (file)
@@ -1,21 +1,21 @@
 .ig
- Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-
- $Id: smartctl.8.in 3561 2012-06-05 19:49:31Z 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
- 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, write to the Free Software Foundation, Inc., 675
- Mass Ave, Cambridge, MA 02139, USA.
-
- This code was originally developed as a Senior Thesis by Michael Cornwell
- at the Concurrent Systems Laboratory (now part of the Storage Systems
- Research Center), Jack Baskin School of Engineering, University of
- California, Santa Cruz. http://ssrc.soe.ucsc.edu/
+Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+Copyright (C) 2004-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
+
+$Id: smartctl.8.in 3799 2013-03-15 17:47:25Z 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 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/>.
+
+This code was originally developed as a Senior Thesis by Michael Cornwell
+at the Concurrent Systems Laboratory (now part of the Storage Systems
+Research Center), Jack Baskin School of Engineering, University of
+California, Santa Cruz. http://ssrc.soe.ucsc.edu/
 
 ..
 .TH SMARTCTL 8 CURRENT_SVN_DATE CURRENT_SVN_VERSION CURRENT_SVN_DATE
@@ -39,23 +39,16 @@ CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV
 .\"! It does not contain info specific to other platforms.]
 .\"! .PP
 .\" %ENDIF NOT OS ALL
-\fBsmartctl\fP controls the Self\-Monitoring, Analysis and Reporting
-Technology (SMART) system built into many ATA\-3 and later ATA, IDE and
-SCSI\-3 hard drives. The purpose of SMART is to monitor the reliability
-of the hard drive and predict drive failures, and to carry out
-different types of drive self\-tests.  This version of \fBsmartctl\fP
-is compatible with ATA/ATAPI\-7 and earlier standards (see REFERENCES
-below)
-
-\fBsmartctl\fP is a command line utility designed to perform SMART
-tasks such as printing the SMART self\-test and error logs, enabling
-and disabling SMART automatic testing, and initiating device
-self\-tests. Note: if the user issues a SMART command that is
-(apparently) not implemented by the device, \fBsmartctl\fP will print
-a warning message but issue the command anyway (see the \fB\-T,
-\-\-tolerance\fP option below).  This should not cause problems: on
-most devices, unimplemented SMART commands issued to a drive are
-ignored and/or return an error.
+\fBsmartctl\fP controls the Self-Monitoring, Analysis and
+Reporting Technology (SMART) system built into most ATA/SATA and SCSI/SAS
+hard drives and solid-state drives.
+The purpose of SMART is to monitor the reliability of the hard drive
+and predict drive failures, and to carry out different types of drive
+self-tests.
+\fBsmartctl\fP also supports some features not related to SMART.
+This version of \fBsmartctl\fP is compatible with
+ACS-2, ATA8-ACS, ATA/ATAPI-7 and earlier standards
+(see \fBREFERENCES\fP below).
 
 \fBsmartctl\fP also provides support for polling TapeAlert messages
 from SCSI tape drives and changers.
@@ -78,7 +71,14 @@ below. For disks behind HighPoint RocketRAID controllers you may need
 \fB"/dev/sd[a\-z]"\fP.  For disks behind Areca SATA RAID controllers,
 you need \fB"/dev/sg[2\-9]"\fP (note that smartmontools interacts with
 the Areca controllers via a SCSI generic device which is different
-than the SCSI device used for reading and writing data)!
+than the SCSI device used for reading and writing data)!  For HP Smart
+Array RAID controllers, there are three currently supported drivers: cciss,
+hpsa, and hpahcisr.  For disks accessed via the cciss driver the device nodes
+are of the form \fB"/dev/cciss/c[0\-9]d0"\fP.  For disks accessed via
+the hpahcisr and hpsa drivers, the device nodes you need are \fB"/dev/sg[0\-9]*"\fP.
+("lsscsi \-g" is helpful in determining which scsi generic device node corresponds
+to which device.)  Use the nodes corresponding to the RAID controllers,
+not the nodes corresponding to logical drives.  See the \fB\-d\fP option below, as well.
 .\" %ENDIF OS Linux
 .\" %IF OS Darwin
 .IP \fBDARWIN\fP: 9
@@ -93,7 +93,9 @@ Firewire devices (see INSTALL file).
 .IP \fBFREEBSD\fP: 9
 Use the forms \fB"/dev/ad[0\-9]+"\fP for IDE/ATA
 devices and \fB"/dev/da[0\-9]+"\fP or \fB"/dev/pass[0\-9]+"\fP for SCSI devices.
-For SATA devices on AHCI bus use \fB"/dev/ada[0\-9]+"\fP format.
+For SATA devices on AHCI bus use \fB"/dev/ada[0\-9]+"\fP format.  For HP Smart
+Array RAID controllers, use \fB"/dev/ciss[0\-9]"\fP (and see the \fB-d\fP option,
+below).
 .\" %ENDIF OS FreeBSD
 .\" %IF OS NetBSD OpenBSD
 .IP \fBNETBSD/OPENBSD\fP: 9
@@ -108,18 +110,11 @@ your architecture.
 Use the forms \fB"/dev/rdsk/c?t?d?s?"\fP for IDE/ATA and SCSI disk
 devices, and \fB"/dev/rmt/*"\fP for SCSI tape devices.
 .\" %ENDIF OS Solaris
-.\" %IF OS Windows
-.IP \fBWINDOWS\ 9x/ME\fP: 9
-Use the forms \fB"/dev/hd[a\-d]"\fP for standard IDE/ATA devices
-accessed via SMARTVSD.VXD, and \fB"/dev/hd[e\-h]"\fP for additional devices
-accessed via a patched SMARTVSE.VXD (see INSTALL file for details).
-Use the form \fB"/dev/scsi[0\-9][0\-f]"\fP for SCSI devices via an aspi dll
-on ASPI adapter 0\-9, ID 0\-15. The prefix \fB"/dev/"\fP is optional.
-.\" %ENDIF OS Windows
 .\" %IF OS Windows Cygwin
-.IP \fBWINDOWS\ NT4/2000/XP/2003/Vista/Win7/2008\fP: 9
+.IP \fBWINDOWS\fP: 9
 Use the forms \fB"/dev/sd[a\-z]"\fP for IDE/(S)ATA and SCSI disks
 "\\\\.\\PhysicalDrive[0\-25]" (where "a" maps to "0").
+Use \fB"/dev/sd[a\-z][a\-z]"\fP for "\\\\.\\PhysicalDrive[26\-...]".
 These disks can also be referred to as \fB"/dev/pd[0\-255]"\fP for
 "\\\\.\\PhysicalDrive[0\-255]".
 ATA disks can also be referred to as \fB"/dev/hd[a\-z]"\fP for
@@ -145,15 +140,11 @@ For disks behind an Intel ICHxR controller with RST driver use
 \fB"/dev/csmi[0\-9],N"\fP where N specifies the port behind the logical
 scsi controller "\\\\.\\Scsi[0\-9]:".
 
-[NEW EXPERIMENTAL SMARTCTL FEATURE] For SATA disks behind an Areca SATA
-or SAS controller use \fB"/dev/arcmsr[0\-9]"\fP, see \'\-d areca,N[/E]\' below.
+[NEW EXPERIMENTAL SMARTCTL FEATURE] For SATA or SAS disks behind an Areca
+controller use \fB"/dev/arcmsr[0\-9]"\fP, see \'\-d areca,N[/E]\' below.
 
 The prefix \fB"/dev/"\fP is optional.
 .\" %ENDIF OS Windows Cygwin
-.\" %IF OS Cygwin
-.IP \fBCYGWIN\fP: 9
-See "WINDOWS NT4/2000/XP/2003/Vista/Win7/2008" above.
-.\" %ENDIF OS Cygwin
 .\" %IF OS OS2
 .IP \fBOS/2,eComStation\fP: 9
 Use the form \fB"/dev/hd[a\-z]"\fP for IDE/ATA devices.
@@ -164,7 +155,7 @@ interprets it's own debug output from standard input.
 See \'\-r ataioctl\' below for details.
 .PP
 Based on the device path, \fBsmartctl\fP will guess the device type
-(ATA or SCSI).  If necessary, the \'\-d\' option can be used to over\-ride
+(ATA or SCSI).  If necessary, the \'\-d\' option can be used to override
 this guess
 
 Note that the printed output of \fBsmartctl\fP displays most numerical
@@ -203,6 +194,20 @@ in the smartmontools database (see \'\-v\' options below).  If so, the
 drive model family may also be printed. If \'\-n\' (see below) is
 specified, the power mode of the drive is printed.
 .TP
+.B \-\-identify[=[w][nvb]]
+[ATA only] [NEW EXPERIMENTAL SMARTCTL FEATURE] Prints an annotated
+table of the IDENTIFY DEVICE data.
+By default, only valid words (words not equal to 0x0000 or 0xffff)
+and nonzero bits and bit fields are printed.
+This can be changed by the optional argument which consists of one or
+two characters from the set \'wnvb\'.
+The character \'w\' enables printing of all 256 words. The character
+\'n\' suppresses printing of bits, \'v\' enables printing of all bits
+from valid words, \'b\' enables printing of all bits.
+For example \'\-\-identify=n\' (valid words, no bits) produces the
+shortest output and \'\-\-identify=wb\' (all words, all bits) produces
+the longest output.
+.TP
 .B \-a, \-\-all
 Prints all SMART information about the disk, or TapeAlert information
 about the tape drive or changer.  For ATA devices this is equivalent
@@ -222,7 +227,7 @@ Prints all SMART and non-SMART information about the device. For ATA
 devices this is equivalent to
 .nf
 \'\-H \-i \-g all \-c \-A \-f brief \-l xerror,error \-l xselftest,selftest
-\-l selective \-l directory \-l scttemp \-l scterc \-l sataphy\'.
+\-l selective \-l directory \-l scttemp \-l scterc \-l devstat \-l sataphy\'.
 .fi
 and for SCSI, this is equivalent to
 .nf
@@ -245,14 +250,14 @@ This option can be used to create a draft \fBsmartd.conf\fP file.
 All options after \'\-\-\' are appended to each output line.
 For example:
 .nf
-smartctl --scan-open -- -a -W 4,45,50 -m admin@work > smartd.conf
+smartctl \-\-scan\-open \-\- \-a \-W 4,45,50 \-m admin@work > smartd.conf
 .fi
 .TP
 .B \-g NAME, \-\-get=NAME
-Get non\-SMART device settings.  See \'\-s, \-\-set\' below for further info.
+Get non-SMART device settings.  See \'\-s, \-\-set\' below for further info.
 
 .TP
-.B RUN\-TIME BEHAVIOR OPTIONS:
+.B RUN-TIME BEHAVIOR OPTIONS:
 .TP
 .B \-q TYPE, \-\-quietmode=TYPE
 Specifies that \fBsmartctl\fP should run in one of the two quiet modes
@@ -260,11 +265,11 @@ described here.  The valid arguments to this option are:
 
 .I errorsonly
 \- only print: For the \'\-l error\' option, if nonzero, the number
-of errors recorded in the SMART error log and the power\-on time when
+of errors recorded in the SMART error log and the power-on time when
 they occurred; For the \'\-l selftest\' option, errors recorded in the device
-self\-test log; For the \'\-H\' option, SMART "disk failing" status or device
-Attributes (pre\-failure or usage) which failed either now or in the
-past; For the \'\-A\' option, device Attributes (pre\-failure or usage)
+self-test log; For the \'\-H\' option, SMART "disk failing" status or device
+Attributes (pre-failure or usage) which failed either now or in the
+past; For the \'\-A\' option, device Attributes (pre-failure or usage)
 which failed either now or in the past.
 
 .I silent
@@ -279,13 +284,13 @@ Specifies the type of the device.
 The valid arguments to this option are:
 
 .I auto
-- attempt to guess the device type from the device name or from
+\- attempt to guess the device type from the device name or from
 controller type info provided by the operating system or from
 a matching USB ID entry in the drive database.
 This is the default.
 
 .I test
-- prints the guessed type, then opens the device and prints the
+\- prints the guessed type, then opens the device and prints the
 (possibly changed) TYPE name and then exists without performing
 any further commands.
 
@@ -308,8 +313,7 @@ SAT defines two ATA PASS THROUGH SCSI commands, one 12 bytes long and
 the other 16 bytes long.  The default is the 16 byte variant which can be
 overridden with either \'\-d sat,12\' or \'\-d sat,16\'.
 
-[NEW EXPERIMENTAL SMARTCTL FEATURE] If \'-d sat,auto\' is specified,
-device type SAT (for ATA/SATA disks) is
+If \'\-d sat,auto\' is specified, device type SAT (for ATA/SATA disks) is
 only used if the SCSI INQUIRY data reports a SATL (VENDOR: "ATA     ").
 Otherwise device type SCSI (for SCSI/SAS disks) is used.
 
@@ -320,8 +324,8 @@ The default SCSI operation code is 0x24, but although it can be overridden
 with \'\-d usbcypress,0xN\', where N is the scsi operation code,
 you're running the risk of damage to the device or filesystems on it.
 
-.I usbjmicron
-- this device type is for SATA disks that are behind a JMicron USB to
+.I usbjmicron[,p][,x][,PORT]
+\- this device type is for SATA disks that are behind a JMicron USB to
 PATA/SATA bridge.  The 48-bit ATA commands (required e.g. for \'\-l xerror\',
 see below) do not work with all of these bridges and are therefore disabled by
 default.  These commands can be enabled by \'\-d usbjmicron,x\'.
@@ -335,6 +339,13 @@ CAUTION: Specifying \',x\' for a device which does not support it results
 in I/O errors and may disconnect the drive.  The same applies if the specified
 PORT does not exist or is not connected to a disk.
 
+[NEW EXPERIMENTAL SMARTCTL FEATURE]
+The Prolific PL2507/3507 USB bridges with older firmware support a pass-through
+command similar to JMicron and work with \'\-d usbjmicron,0\'.
+Newer Prolific firmware requires a modified command which can be selected by
+\'\-d usbjmicron,p\'.
+Note that this does not yet support the SMART status command.
+
 .I usbsunplus
 \- this device type is for SATA disks that are behind a SunplusIT USB to SATA
 bridge.
@@ -356,12 +367,18 @@ Use syntax such as:
 .nf
 \fBsmartctl \-a \-d megaraid,0 /dev/sdb\fP
 .fi
+.nf
+\fBsmartctl \-a \-d megaraid,0 /dev/bus/0\fP
+.fi
 This interface will also work for Dell PERC controllers.
-The following /dev/XXX entry must exist:
+It is possible to set RAID device name as /dev/bus/N, where N is a SCSI bus
+number.
+
+The following entry in /proc/devices must exist:
 .fi
-For PERC2/3/4 controllers: \fB/dev/megadev0\fP
+For PERC2/3/4 controllers: \fBmegadevN\fP
 .fi
-For PERC5/6 controllers: \fB/dev/megaraid_sas_ioctl_node\fP
+For PERC5/6 controllers: \fBmegaraid_sas_ioctlN\fP
 
 .\" %ENDIF OS Linux
 .\" %IF OS FreeBSD Linux
@@ -372,7 +389,7 @@ connected to a 3ware RAID controller.  The non-negative integer N
 is monitored.
 Use syntax such as:
 .nf
-\fBsmartctl \-a \-d 3ware,2 /dev/sda\fP
+\fBsmartctl \-a \-d 3ware,2 /dev/sda\fP  [Linux only]
 .fi
 .nf
 \fBsmartctl \-a \-d 3ware,0 /dev/twe0\fP
@@ -381,28 +398,31 @@ Use syntax such as:
 \fBsmartctl \-a \-d 3ware,1 /dev/twa0\fP
 .fi
 .nf
-\fBsmartctl \-a \-d 3ware,1 /dev/twl0\fP
+\fBsmartctl \-a \-d 3ware,1 /dev/twl0\fP [Linux only]
+.fi
+.nf
+\fBsmartctl \-a \-d 3ware,1 /dev/tws0\fP [FreeBSD only]
 .fi
 The first two forms, which refer to devices /dev/sda\-z and /dev/twe0\-15,
 may be used with 3ware series 6000, 7000, and 8000 series controllers
-that use the 3x\-xxxx driver.
+that use the 3x-xxxx driver.
 \fBNote that the /dev/sda\-z form is deprecated\fP starting with
 the Linux 2.6 kernel series and may not be supported by the Linux
 kernel in the near future.  The final form, which refers to devices
 /dev/twa0\-15, must be used with 3ware 9000 series controllers, which
 use the 3w\-9xxx driver.
 
-The devices /dev/twl0\-15 must be used with the 3ware/LSI 9750 series
+The devices /dev/twl0\-15 [Linux] or /dev/tws0\-15 [FreeBSD] must be used with the 3ware/LSI 9750 series
 controllers which use the 3w-sas driver.
 
-Note that if the special character device nodes /dev/twl?, /dev/twa?
+Note that if the special character device nodes /dev/tw[ls]?, /dev/twa?
 and /dev/twe? do not exist, or exist with the incorrect major or minor
 numbers, smartctl will recreate them on the fly.  Typically /dev/twa0
-refers to the first 9000\-series controller, /dev/twa1 refers to the
+refers to the first 9000-series controller, /dev/twa1 refers to the
 second 9000 series controller, and so on.  The /dev/twl0 devices refers
 to the first 9750 series controller, /dev/twl1 resfers to the second
 9750 series controller, and so on.  Likewise /dev/twe0 refers to
-the first 6/7/8000\-series controller, /dev/twe1 refers to the second
+the first 6/7/8000-series controller, /dev/twe1 refers to the second
 6/7/8000 series controller, and so on.
 
 Note that for the 6/7/8000 controllers, \fBany\fP of the physical
@@ -424,19 +444,19 @@ disk attached to it, the behavior of \fBsmartctl\fP depends upon the
 specific controller model, firmware, Linux kernel and platform.  In
 some cases you will get a warning message that the device does not
 exist.  In other cases you will be presented with \'void\' data for a
-non\-existent device.
+non-existent device.
 
-Note that if the /dev/sd? addressing form is used, then older 3w\-xxxx
+Note that if the /dev/sd? addressing form is used, then older 3w-xxxx
 drivers do not pass the "Enable Autosave"
 (\'\fB\-S on\fP\') and "Enable Automatic Offline" (\'\fB\-o on\fP\')
 commands to the disk, and produce these types of harmless syslog error
-messages instead: "\fB3w\-xxxx: tw_ioctl(): Passthru size (123392) too
+messages instead: "\fB3w-xxxx: tw_ioctl(): Passthru size (123392) too
 big\fP".  This can be fixed by upgrading to version 1.02.00.037 or
-later of the 3w\-xxxx driver, or by applying a patch to older
+later of the 3w-xxxx driver, or by applying a patch to older
 versions.  Alternatively, use the character device /dev/twe0\-15 interface.
 
-The selective self\-test functions (\'\-t select,A\-B\') are only supported
-using the character device interface /dev/twl0\-15, /dev/twa0\-15 and /dev/twe0\-15.
+The selective self-test functions (\'\-t select,A\-B\') are only supported
+using the character device interface /dev/twl0\-15, /dev/tws0\-15, /dev/twa0\-15 and /dev/twe0\-15.
 The necessary WRITE LOG commands can not be passed through the SCSI
 interface.
 
@@ -498,21 +518,35 @@ error messages and no SMART information.
 
 .I areca,N/E
 \- [FreeBSD, Linux, Windows and Cygwin only] [NEW EXPERIMENTAL SMARTCTL FEATURE] the
-device consists of one or more SATA disks connected to an Areca SAS RAID controller.
+device consists of one or more SATA or SAS disks connected to an Areca SAS RAID controller.
 The integer N (range 1 to 128) denotes the channel (slot) and E (range
 1 to 8) denotes the enclosure.
-Important: This requires upcoming Areca SAS controller firmware version 1.51 or a
-recent beta version.
+Important: This requires Areca SAS controller firmware version 1.51 or later.
 
 .\" %ENDIF OS FreeBSD Linux Windows Cygwin
 .\" %IF OS FreeBSD Linux
 .I cciss,N
-\- [FreeBSD and Linux only] the device consists of one or more SCSI/SAS disks
+\- [FreeBSD and Linux only] the device consists of one or more SCSI/SAS or SATA disks
 connected to a cciss RAID controller.  The non-negative integer N (in the range
 from 0 to 15 inclusive) denotes which disk on the controller is monitored.
 
-If the controller firmware or driver provides a SAT Layer it may be possible
-to monitor also SATA disks by specifiying \'\-d sat+cciss,N\'.
+To look at disks behind HP Smart Array controllers, use syntax
+such as:
+.\" %ENDIF OS FreeBSD Linux
+.\" %IF OS Linux
+.nf
+\fBsmartctl \-a \-d cciss,0 /dev/cciss/c0d0\fP    (cciss driver under Linux)
+.fi
+.nf
+\fBsmartctl \-a \-d cciss,0 /dev/sg2\fP    (hpsa or hpahcisr drivers under Linux)
+.fi
+.\" %ENDIF OS Linux
+.\" %IF OS FreeBSD
+.nf
+\fBsmartctl \-a \-d cciss,0 /dev/ciss0\fP    (under FreeBSD)
+.fi
+.\" %ENDIF OS FreeBSD
+.\" %IF OS FreeBSD Linux
 
 .I hpt,L/M/N
 \- [FreeBSD and Linux only] the device consists of one or more ATA disks
@@ -553,9 +587,9 @@ command failures.
 
 The behavior of \fBsmartctl\fP depends upon whether the command is
 "\fBoptional\fP" or "\fBmandatory\fP". Here "\fBmandatory\fP" means
-"required by the ATA/ATAPI\-5 Specification if the device implements
+"required by the ATA Specification if the device implements
 the SMART command set" and "\fBoptional\fP" means "not required by the
-ATA/ATAPI\-5 Specification even if the device implements the SMART
+ATA Specification even if the device implements the SMART
 command set."  The "\fBmandatory\fP" ATA and SMART commands are: (1)
 ATA IDENTIFY DEVICE, (2) SMART ENABLE/DISABLE ATTRIBUTE AUTOSAVE, (3)
 SMART ENABLE/DISABLE, and (4) SMART RETURN STATUS.
@@ -578,8 +612,8 @@ final message, Feature X is \fBnot\fP enabled.
 \- ignore failure(s) of \fBmandatory\fP SMART commands.  This option
 may be given more than once.  Each additional use of this option will
 cause one more additional failure to be ignored.  Note that the use of
-this option can lead to messages like "Feature X not implemented",
-followed shortly by "Error: unable to enable Feature X".  In a few
+this option can lead to messages like "Feature X not supported",
+followed shortly by "Feature X enable failed".  In a few
 such cases, contrary to the final message, Feature X \fBis\fP enabled.
 
 .I verypermissive
@@ -590,7 +624,7 @@ Please see the note above.
 .B \-b TYPE, \-\-badsum=TYPE
 [ATA only] Specifies the action \fBsmartctl\fP should take if a checksum
 error is detected in the: (1) Device Identity Structure, (2) SMART
-Self\-Test Log Structure, (3) SMART Attribute Value Structure, (4) SMART
+Self-Test Log Structure, (3) SMART Attribute Value Structure, (4) SMART
 Attribute Threshold Structure, or (5) ATA Error Log Structure.
 
 The valid arguments to this option are:
@@ -607,7 +641,7 @@ default.
 .TP
 .B \-r TYPE, \-\-report=TYPE
 Intended primarily to help \fBsmartmontools\fP developers understand
-the behavior of \fBsmartmontools\fP on non\-conforming or poorly
+the behavior of \fBsmartmontools\fP on non-conforming or poorly
 conforming hardware.  This option reports details of \fBsmartctl\fP
 transactions with the device.  The option can be used multiple times.
 When used just once, it shows a record of the ioctl() transactions
@@ -643,13 +677,13 @@ behaviour. This is does not work for SCSI devices yet.
 .TP
 .B \-n POWERMODE, \-\-nocheck=POWERMODE
 [ATA only] Specifies if \fBsmartctl\fP should exit before performing any
-checks when the device is in a low\-power mode. It may be used to prevent
-a disk from being spun\-up by \fBsmartctl\fP. The power mode is ignored by
+checks when the device is in a low-power mode. It may be used to prevent
+a disk from being spun-up by \fBsmartctl\fP. The power mode is ignored by
 default.  A nonzero exit status is returned if the device is in one of the
-specified low\-power modes (see RETURN VALUES below).
+specified low-power modes (see RETURN VALUES below).
 
 Note: If this option is used it may also be necessary to specify the device
-type with the \'-d\' option.  Otherwise the device may spin up due to
+type with the \'\-d\' option.  Otherwise the device may spin up due to
 commands issued during device type autodetection.
 
 The valid arguments to this option are:
@@ -687,9 +721,9 @@ the corresponding disable command.
 Enables or disables SMART on device.  The valid arguments to
 this option are \fIon\fP and \fIoff\fP.  Note that the command \'\-s on\'
 (perhaps used with with the \'\-o on\' and \'\-S on\' options) should be
-placed in a start\-up script for your machine, for example in rc.local or
+placed in a start-up script for your machine, for example in rc.local or
 rc.sysinit. In principle the SMART feature settings are preserved over
-power\-cycling, but it doesn\'t hurt to be sure. It is not necessary (or
+power-cycling, but it doesn\'t hurt to be sure. It is not necessary (or
 useful) to enable SMART to see the TapeAlert messages.
 .TP
 .B \-o VALUE, \-\-offlineauto=VALUE
@@ -700,13 +734,13 @@ and \fIoff\fP.
 
 Note that the SMART automatic offline test command is listed as
 "Obsolete" in every version of the ATA and ATA/ATAPI Specifications.
-It was originally part of the SFF\-8035i Revision 2.0 specification,
+It was originally part of the SFF-8035i Revision 2.0 specification,
 but was never part of any ATA specification.  However it is
 implemented and used by many vendors. [Good documentation can be found
 in IBM\'s Official Published Disk Specifications.  For example the IBM
 Travelstar 40GNX Hard Disk Drive Specifications (Revision 1.1, 22
-April 2002, Publication # 1541, Document S07N\-7715\-02) page 164. You
-can also read the SFF\-8035i Specification \-\- see REFERENCES below.]
+April 2002, Publication # 1541, Document S07N-7715-02) page 164. You
+can also read the SFF-8035i Specification -- see REFERENCES below.]
 You can tell if automatic offline testing is supported by seeing if
 this command enables and disables it, as indicated by the \'Auto
 Offline Data Collection\' part of the SMART capabilities report
@@ -722,12 +756,12 @@ type of test can, in principle, degrade the device performance.  The
 automatically, on a regular scheduled basis.  Normally, the disk will
 suspend offline testing while disk accesses are taking place, and then
 automatically resume it when the disk would otherwise be idle, so in
-practice it has little effect.  Note that a one\-time offline test can
+practice it has little effect.  Note that a one-time offline test can
 also be carried out immediately upon receipt of a user command.  See
-the \'\-t offline\' option below, which causes a one\-time offline test
+the \'\-t offline\' option below, which causes a one-time offline test
 to be carried out immediately.
 
-The choice (made by the SFF\-8035i and ATA specification authors) of
+The choice (made by the SFF-8035i and ATA specification authors) of
 the word \fItesting\fP for these first two categories is unfortunate,
 and often leads to confusion.  In fact these first two categories of
 online and offline testing could have been more accurately described
@@ -740,9 +774,9 @@ Attributes will go below their failure thresholds; some types of
 errors may also appear in the SMART error log. These are visible with
 the \'\-A\' and \'\-l error\' options respectively.
 
-Some SMART attribute values are updated only during off\-line data
+Some SMART attribute values are updated only during off-line data
 collection activities; the rest are updated during normal operation of
-the device or during both normal operation and off\-line testing.  The
+the device or during both normal operation and off-line testing.  The
 Attribute value table produced by the \'\-A\' option indicates this in
 the UPDATED column.  Attributes of the first type are labeled
 "Offline" and Attributes of the second type are labeled "Always".
@@ -751,20 +785,20 @@ The \fBthird\fP category of testing (and the \fIonly\fP category for
 which the word \'testing\' is really an appropriate choice) is "self"
 testing.  This third type of test is only performed (immediately) when
 a command to run it is issued.  The \'\-t\' and \'\-X\' options can be
-used to carry out and abort such self\-tests; please see below for
+used to carry out and abort such self-tests; please see below for
 further details.
 
 Any errors detected in the self testing will be shown in the
-SMART self\-test log, which can be examined using the \'\-l selftest\'
+SMART self-test log, which can be examined using the \'\-l selftest\'
 option.
 
 \fBNote:\fP in this manual page, the word \fB"Test"\fP is used in
 connection with the second category just described, e.g. for the
-"offline" testing.  The words \fB"Self\-test"\fP are used in
+"offline" testing.  The words \fB"Self-test"\fP are used in
 connection with the third category.
 .TP
 .B \-S VALUE, \-\-saveauto=VALUE
-[ATA] Enables or disables SMART autosave of device vendor\-specific
+[ATA] Enables or disables SMART autosave of device vendor-specific
 Attributes. The valid arguments to this option are \fIon\fP
 and \fIoff\fP.  Note that this feature is preserved across disk power
 cycles, so you should only need to issue it once.
@@ -776,16 +810,16 @@ a warning if autosave is disabled.
 [SCSI] For SCSI devices this toggles the value of the Global Logging
 Target Save Disabled (GLTSD) bit in the Control Mode Page. Some disk
 manufacturers set this bit by default. This prevents error counters,
-power\-up hours and other useful data from being placed in non\-volatile
+power-up hours and other useful data from being placed in non-volatile
 storage, so these values may be reset to zero the next time the device
-is power\-cycled.  If the GLTSD bit is set then \'smartctl \-a\' will
+is power-cycled.  If the GLTSD bit is set then \'smartctl \-a\' will
 issue a warning. Use \fIon\fP to clear the GLTSD bit and thus enable
-saving counters to non\-volatile storage. For extreme streaming\-video
+saving counters to non-volatile storage. For extreme streaming-video
 type applications you might consider using \fIoff\fP to set the GLTSD
 bit.
 .TP
 .B \-g NAME, \-\-get=NAME, \-s NAME[,VALUE], \-\-set=NAME[,VALUE]
-[NEW EXPERIMENTAL SMARTCTL FEATURE] Gets/sets non\-SMART device settings.
+Gets/sets non-SMART device settings.
 Note that the \'\-\-set\' option shares its short option \'\-s\' with
 \'\-\-smart\'.  Valid arguments are:
 
@@ -800,7 +834,7 @@ Note that the \'\-\-set\' option shares its short option \'\-s\' with
 (if supported).  A value of 128 sets the most quiet (slowest) mode and 254
 the fastest (loudest) mode, \'off\' disables AAM.  Devices may support
 intermediate levels.  Values below 128 are defined as vendor specific (0)
-or retired (1\-127).  Note that the AAM feature was declared obsolete in
+or retired (1 to 127).  Note that the AAM feature was declared obsolete in
 ATA ACS-2 Revision 4a (Dec 2010).
 
 .I apm[,N|off]
@@ -842,9 +876,20 @@ because ATA standards do not specify a method to read the standby timer.
 the drive.  The setting of the standby timer is not affected.
 
 .I wcache[,on|off]
-\- [ATA only] Gets/sets the volatile write cache feature (if supported).
+\- [ATA] Gets/sets the volatile write cache feature (if supported).
 The write cache is usually enabled by default.
 
+.I wcache[,on|off]
+\- [SCSI] [NEW EXPERIMENTAL SMARTCTL FEATURE]
+Gets/sets the \'Write Cache Enable\' (WCE) bit (if supported).
+The write cache is usually enabled by default.
+
+.I rcache[,on|off]
+\- [SCSI only] [NEW EXPERIMENTAL SMARTCTL FEATURE]
+Gets/sets the \'Read Cache Disable\' (RCE) bit. \'Off\' value disables read cache
+(if supported).
+The read cache is usually enabled by default.
+
 .TP
 .B SMART READ AND DISPLAY DATA OPTIONS:
 .TP
@@ -853,7 +898,7 @@ Check: Ask the device to report its SMART health status or pending
 TapeAlert messages.  SMART status is based on
 information that it has gathered from online and offline
 tests, which were used to determine/update its
-SMART vendor\-specific Attribute values. TapeAlert status is obtained
+SMART vendor-specific Attribute values. TapeAlert status is obtained
 by reading the TapeAlert log page.
 
 If the device reports failing health status, this means
@@ -869,10 +914,10 @@ this happens, use the \'\-a\' option to get more information, and
 show what SMART features are implemented and how the device will
 respond to some of the different SMART commands.  For example it
 shows if the device logs errors, if it supports offline surface
-scanning, and so on.  If the device can carry out self\-tests, this
+scanning, and so on.  If the device can carry out self-tests, this
 option also shows the estimated time required to run those tests.
 
-Note that the time required to run the Self\-tests (listed in minutes)
+Note that the time required to run the Self-tests (listed in minutes)
 are fixed.  However the time required to run the Immediate Offline
 Test (listed in seconds) is variable.  This means that if you issue a
 command to perform an Immediate Offline test with the \'\-t offline\' option,
@@ -889,9 +934,9 @@ disk been powered up.
 
 Each Attribute has a "Raw" value, printed under the heading
 "RAW_VALUE", and a "Normalized" value printed under the heading
-"VALUE".  [Note: \fBsmartctl\fP prints these values in base\-10.]  In
+"VALUE".  [Note: \fBsmartctl\fP prints these values in base-10.]  In
 the example just given, the "Raw Value" for Attribute 12 would be the
-actual number of times that the disk has been power\-cycled, for
+actual number of times that the disk has been power-cycled, for
 example 365 if the disk has been turned on once per day for exactly
 one year.  Each vendor uses their own algorithm to convert this "Raw"
 value to a "Normalized" value in the range from 1 to 254.  Please keep
@@ -905,30 +950,30 @@ not specified by the SMART standard. In most cases, the values printed
 by \fBsmartctl\fP are sensible.  For example the temperature Attribute
 generally has its raw value equal to the temperature in Celsius.
 However in some cases vendors use unusual conventions.  For example
-the Hitachi disk on my laptop reports its power\-on hours in minutes,
+the Hitachi disk on my laptop reports its power-on hours in minutes,
 not hours. Some IBM disks track three temperatures rather than one, in
 their raw values.  And so on.
 
 Each Attribute also has a Threshold value (whose range is 0 to 255)
 which is printed under the heading "THRESH".  If the Normalized value
 is \fBless than or equal to\fP the Threshold value, then the Attribute
-is said to have failed.  If the Attribute is a pre\-failure Attribute,
+is said to have failed.  If the Attribute is a pre-failure Attribute,
 then disk failure is imminent.
 
 Each Attribute also has a "Worst" value shown under the heading
 "WORST".  This is the smallest (closest to failure) value that the
 disk has recorded at any time during its lifetime when SMART was
 enabled.  [Note however that some vendors firmware may actually
-\fBincrease\fP the "Worst" value for some "rate\-type" Attributes.]
+\fBincrease\fP the "Worst" value for some "rate-type" Attributes.]
 
 The Attribute table printed out by \fBsmartctl\fP also shows the
 "TYPE" of the Attribute. Attributes are one of two possible types:
-Pre\-failure or Old age.  Pre\-failure Attributes are ones which, if
+Pre-failure or Old age.  Pre-failure Attributes are ones which, if
 less than or equal to their threshold values, indicate pending disk
 failure.  Old age, or usage Attributes, are ones which indicate
-end\-of\-product life from old\-age or normal aging and wearout, if
+end-of-product life from old-age or normal aging and wearout, if
 the Attribute value is less than or equal to the threshold.  \fBPlease
-note\fP: the fact that an Attribute is of type 'Pre\-fail' does
+note\fP: the fact that an Attribute is of type 'Pre-fail' does
 \fBnot\fP mean that your disk is about to fail!  It only has this
 meaning if the Attribute\'s current Normalized value is less than or
 equal to the threshold value.
@@ -942,13 +987,13 @@ a dash: \'\-\') then this Attribute is OK now (not failing) and has
 also never failed in the past.
 
 The table column labeled "UPDATED" shows if the SMART Attribute values
-are updated during both normal operation and off\-line testing, or
+are updated during both normal operation and off-line testing, or
 only during offline testing.  The former are labeled "Always" and the
 latter are labeled "Offline".
 
 So to summarize: the Raw Attribute values are the ones that might have
 a real physical interpretation, such as "Temperature Celsius",
-"Hours", or "Start\-Stop Cycles".  Each manufacturer converts these,
+"Hours", or "Start-Stop Cycles".  Each manufacturer converts these,
 using their detailed knowledge of the disk\'s operations and failure
 modes, to Normalized Attribute values in the range 1\-254.  The
 current and worst (lowest measured) of these Normalized Attribute
@@ -959,13 +1004,17 @@ fail, or that it has exceeded its design age or aging limit.
 thresholds, or types, it merely reports them from the SMART data on
 the device.
 
-Note that starting with ATA/ATAPI\-4, revision 4, the meaning of these
-Attribute fields has been made entirely vendor\-specific.  However most
-ATA/ATAPI\-5 disks seem to respect their meaning, so we have retained
+Note that starting with ATA/ATAPI-4, revision 4, the meaning of these
+Attribute fields has been made entirely vendor-specific.  However most
+newer ATA/SATA disks seem to respect their meaning, so we have retained
 the option of printing the Attribute values.
 
+Solid-state drives use different meanings for some of the attributes.
+In this case the attribute name printed by smartctl is incorrect unless
+the drive is already in the smartmontools drive database.
+
 [SCSI] For SCSI devices the "attributes" are obtained from the temperature
-and start\-stop cycle counter log pages. Certain vendor specific
+and start-stop cycle counter log pages. Certain vendor specific
 attributes are listed if recognised. The attributes are output in a
 relatively free format (compared with ATA disk attributes).
 .TP
@@ -991,15 +1040,15 @@ This is the default if the '\-x\' option is specified.
 \- Same as \'\-f hex,id \-f hex,val\'.
 .TP
 .B \-l TYPE, \-\-log=TYPE
-Prints either the SMART Error Log, the SMART Self\-Test Log, the SMART
-Selective Self\-Test Log [ATA only], the Log Directory [ATA only], or
+Prints either the SMART Error Log, the SMART Self-Test Log, the SMART
+Selective Self-Test Log [ATA only], the Log Directory [ATA only], or
 the Background Scan Results Log [SCSI only].
 The valid arguments to this option are:
 
 .I error
 \- [ATA] prints the Summary SMART error log.  SMART disks maintain a log
-of the most recent five non\-trivial errors. For each of these errors, the
-disk power\-on lifetime at which the error occurred is recorded, as is
+of the most recent five non-trivial errors. For each of these errors, the
+disk power-on lifetime at which the error occurred is recorded, as is
 the device status (idle, standby, etc) at the time of the error.  For
 some common types of errors, the Error Register (ER) and Status
 Register (SR) values are decoded and printed as text. The meanings of these
@@ -1011,7 +1060,7 @@ are:
    \fBEOM\fP:   \fBE\fPnd \fBO\fPf \fBM\fPedia
    \fBICRC\fP:  \fBI\fPnterface \fBC\fPyclic \fBR\fPedundancy \fBC\fPode (CRC) error
    \fBIDNF\fP:  \fBID\fPentity \fBN\fPot \fBF\fPound
-   \fBILI\fP:   (packet command\-set specific)
+   \fBILI\fP:   (packet command-set specific)
    \fBMC\fP:    \fBM\fPedia \fBC\fPhanged
    \fBMCR\fP:   \fBM\fPedia \fBC\fPhange \fBR\fPequest
    \fBNM\fP:    \fBN\fPo \fBM\fPedia
@@ -1027,18 +1076,18 @@ Dd+HH:MM:SS.msec where D is the number of days, HH is hours, MM is
 minutes, SS is seconds and msec is milliseconds.  [Note: this time
 stamp wraps after 2^32 milliseconds, or 49 days 17 hours 2 minutes and
 47.296 seconds.]  The key ATA disk registers are also recorded in the
-log.  The final column of the error log is a text\-string description
+log.  The final column of the error log is a text-string description
 of the ATA command defined by the Command Register (CR) and Feature
 Register (FR) values.  Commands that are obsolete in the most current
-(ATA\-7) spec are listed like this: \fBREAD LONG (w/ retry) [OBS\-4]\fP,
-indicating that the command became obsolete with or in the ATA\-4
+spec are listed like this: \fBREAD LONG (w/ retry) [OBS-4]\fP,
+indicating that the command became obsolete with or in the ATA-4
 specification.  Similarly, the notation \fB[RET\-\fP\fIN\fP\fB]\fP is
-used to indicate that a command was retired in the ATA\-\fIN\fP
+used to indicate that a command was retired in the ATA-\fIN\fP
 specification.  Some commands are not defined in any version of the
 ATA specification but are in common use nonetheless; these are marked
-\fB[NS]\fP, meaning non\-standard.
+\fB[NS]\fP, meaning non-standard.
 
-The ATA Specification (ATA\-5 Revision 1c, Section 8.41.6.8.2) says:
+The ATA Specification (ATA-5 Revision 1c, Section 8.41.6.8.2) says:
 \fB"Error log structures shall include UNC errors, IDNF errors for
 which the address requested was valid, servo errors, write fault
 errors, etc.  Error log data structures shall not include errors
@@ -1051,14 +1100,14 @@ to data which has been read from the disk, but for which the Error
 Checking and Correction (ECC) codes are inconsistent.  In effect, this
 means that the data can not be read.
 .br
-\fBIDNF\fP (\fBID N\fPot \fBF\fPound): user\-accessible address could
+\fBIDNF\fP (\fBID N\fPot \fBF\fPound): user-accessible address could
 not be found. For READ LOG type commands, \fBIDNF\fP can also indicate
 that a device data log structure checksum was incorrect.
 
 If the command that caused the error was a READ or WRITE command, then
 the Logical Block Address (LBA) at which the error occurred will be
 printed in base 10 and base 16.  The LBA is a linear address, which
-counts 512\-byte sectors on the disk, starting from zero.  (Because of
+counts 512-byte sectors on the disk, starting from zero.  (Because of
 the limitations of the SMART error log, if the LBA is greater than
 0xfffffff, then either no error log entry will be made, or the error
 log entry will have an incorrect LBA. This may happen for drives with
@@ -1083,7 +1132,7 @@ the contents of the 48-bit LBA register set introduced with ATA-6.
 It also supports logs with more than one sector.  Each sector holds
 up to 4 log entries. The actual number of log sectors is vendor
 specific, typical values for HDD are 2 (Samsung), 5 (Seagate) or
-6 (WD).  Some recent SSD devices have much larger error logs.
+6 (WD).
 
 Only the 8 most recent error log entries are printed by default.
 This number can be changed by the optional parameter NUM.
@@ -1096,11 +1145,11 @@ Comprehensive SMART error log.  The Summary SMART error log may be reported
 as supported but is always empty then.
 
 .I selftest
-\- [ATA] prints the SMART self\-test log.  The disk maintains a self\-test
+\- [ATA] prints the SMART self-test log.  The disk maintains a self-test
 log showing the results of the self tests, which can be run using the
 \'\-t\' option described below.  For each of the most recent
-twenty\-one self\-tests, the log shows the type of test (short or
-extended, off\-line or captive) and the final status of the test.  If
+twenty-one self-tests, the log shows the type of test (short or
+extended, off-line or captive) and the final status of the test.  If
 the test did not complete successfully, then the percentage of the
 test remaining is shown.  The time at which the test took place,
 measured in hours of disk lifetime, is also printed. [Note: this time
@@ -1111,18 +1160,18 @@ smartmontools web page has instructions about how to convert this LBA
 address to the name of the disk file containing the erroneous block.
 
 .I selftest
-\- [SCSI] the self\-test log for a SCSI device has a slightly different
+\- [SCSI] the self-test log for a SCSI device has a slightly different
 format than for an ATA device.  For each of the most recent twenty
-self\-tests, it shows the type of test and the status (final or in
+self-tests, it shows the type of test and the status (final or in
 progress) of the test. SCSI standards use the terms "foreground" and
 "background" (rather than ATA\'s corresponding "captive" and
-"off\-line") and "short" and "long" (rather than ATA\'s corresponding
+"off-line") and "short" and "long" (rather than ATA\'s corresponding
 "short" and "extended") to describe the type of the test.  The printed
 segment number is only relevant when a test fails in the third or
 later test segment.  It identifies the test that failed and consists
 of either the number of the segment that failed during the test, or
 the number of the test that failed and the number of the segment in
-which the test was run, using a vendor\-specific method of putting both
+which the test was run, using a vendor-specific method of putting both
 numbers into a single byte.  The Logical Block Address (LBA) of the
 first error is printed in hexadecimal notation.  On Linux systems the
 smartmontools web page has instructions about how to convert this LBA
@@ -1133,8 +1182,8 @@ can be run using the \'\-t\' option described below (using the ATA
 test terminology).
 
 .I xselftest[,NUM][,selftest]
-\- [ATA only] prints the Extended SMART self\-test log (General Purpose
-Log address 0x07). Unlike the SMART self\-test log (see \'\-l selftest\'
+\- [ATA only] prints the Extended SMART self-test log (General Purpose
+Log address 0x07). Unlike the SMART self-test log (see \'\-l selftest\'
 above), it supports 48-bit LBA and logs with more than one sector.
 Each sector holds up to 19 log entries. The actual number of log sectors
 is vendor specific, typical values are 1 (Seagate) or 2 (Samsung).
@@ -1147,26 +1196,24 @@ supported, the old SMART self-test log is printed.
 
 .I selective
 \- [ATA only] Please see the \'\-t select\' option below for a
-description of selective self\-tests.  The selective self\-test log
+description of selective self-tests.  The selective self-test log
 shows the start/end Logical Block Addresses (LBA) of each of the five
 test spans, and their current test status.  If the span is being
-tested or the remainder of the disk is being read\-scanned, the
-current 65536\-sector block of LBAs being tested is also displayed.
-The selective self\-test log also shows if a read\-scan of the
+tested or the remainder of the disk is being read-scanned, the
+current 65536-sector block of LBAs being tested is also displayed.
+The selective self-test log also shows if a read-scan of the
 remainder of the disk will be carried out after the selective
-self\-test has completed (see \'\-t afterselect\' option) and the time
-delay before restarting this read\-scan if it is interrupted (see
-\'\-t pending\' option). This is a new smartmontools feature; please
-report unusual or incorrect behavior to the smartmontools\-support
-mailing list.
+self-test has completed (see \'\-t afterselect\' option) and the time
+delay before restarting this read-scan if it is interrupted (see
+\'\-t pending\' option).
 
 .I directory[,gs]
 \- [ATA only] if the device supports the General Purpose Logging feature
-set (ATA\-6 and above) then this prints the Log Directory (the log at
+set (ATA-6 and above) then this prints the Log Directory (the log at
 address 0).  The Log Directory shows what logs are available and their
 length in sectors (512 bytes).  The contents of the logs at address 1
-[Summary SMART error log] and at address 6 [SMART self\-test log] may
-be printed using the previously\-described
+[Summary SMART error log] and at address 6 [SMART self-test log] may
+be printed using the previously-described
 .I error
 and
 .I selftest
@@ -1178,7 +1225,7 @@ SL directory by \'\-l directory,q\' or \'\-l directory,s\' respectively.
 
 .I background
 \- [SCSI only] the background scan results log outputs information derived
-from Background Media Scans (BMS) done after power up and/or periodocally
+from Background Media Scans (BMS) done after power up and/or periodically
 (e.g. every 24 hours) on recent SCSI disks. If supported, the BMS status
 is output first, indicating whether a background scan is currently
 underway (and if so a progress percentage), the amount of time the disk
@@ -1186,7 +1233,7 @@ has been powered up and the number of scans already completed. Then there
 is a header and a line for each background scan "event". These will
 typically be either recovered or unrecoverable errors. That latter group
 may need some attention. There is a description of the background scan
-mechansim in section 4.18 of SBC\-3 revision 6 (see www.t10.org ).
+mechanism in section 4.18 of SBC-3 revision 6 (see www.t10.org ).
 
 .I scttemp, scttempsts, scttemphist
 \- [ATA only] prints the disk temperature information provided by the
@@ -1198,8 +1245,8 @@ the SCT Data Table command, and \'scttemp\' prints both.
 The temperature values are preserved across power cycles.
 The logging interval can be configured with the
 \'\-l scttempint,N[,p]\' option, see below.
-The SCT commands were introduced in ATA\-8 ACS and were also
-supported by in many ATA\-7 disks.
+The SCT commands were introduced in ATA8-ACS and were also
+supported by many ATA-7 disks.
 
 .I scttempint,N[,p]
 \- [ATA only] clears the SCT temperature history table and sets the
@@ -1219,19 +1266,20 @@ than 65 are probably not supported. For RAID configurations, this is
 typically set to 70,70 deciseconds.
 
 .I devstat[,PAGE]
-\- [ATA only] [NEW EXPERIMENTAL SMARTCTL FEATURE] prints values
-and descriptions of the ATA Device Statistics log pages
-(General Purpose Log address 0x04).  If no PAGE number is specified,
+\- [ATA only] prints values and descriptions of the ATA Device Statistics
+log pages (General Purpose Log address 0x04).  If no PAGE number is specified,
 entries from all supported pages are printed.  If PAGE 0 is specified,
 the list of supported pages is printed.  Device Statistics was
-introduced in ATA\-8 ACS and is only supported by some recent devices
-(e.g. Hitachi 7K3000, Intel 320, 330 and 710 Series SSDs, Crucial/Micron
+introduced in ACS-2 and is only supported by some recent devices
+(e.g. Hitachi 7K3000, Intel 320, 330, 520 and 710 Series SSDs, Crucial/Micron
 m4 SSDs).
 
 .I sataphy[,reset]
 \- [SATA only] prints values and descriptions of the SATA Phy Event
 Counters (General Purpose Log address 0x11).  If \'\-l sataphy,reset\'
 is specified, all counters are reset after reading the values.
+This also works for SATA devices with Packet interface like CD/DVD
+drives.
 
 .I sasphy[,reset]
 \- [SAS (SCSI) only] prints values and descriptions of the SAS (SSP)
@@ -1277,7 +1325,7 @@ indicates the device is at the end of its lifetime as projected by the
 manufacturer. The value may reach 255.
 .TP
 .B \-v ID,FORMAT[:BYTEORDER][,NAME], \-\-vendorattribute=ID,FORMAT[:BYTEORDER][,NAME]
-[ATA only] Sets a vendor\-specific raw value print FORMAT, an optional
+[ATA only] Sets a vendor-specific raw value print FORMAT, an optional
 BYTEORDER and an optional NAME for Attribute ID.
 This option may be used multiple times.
 
@@ -1286,11 +1334,11 @@ ID, the settings for all Attributes are changed.
 
 The optional BYTEORDER consists of 1 to 8 characters from the
 set \'012345rvwz\'. The characters \'0\' to \'5\' select the byte 0
-to 5 from the 48\-bit raw value, \'r\' selects the reserved byte of
+to 5 from the 48-bit raw value, \'r\' selects the reserved byte of
 the attribute data block, \'v\' selects the normalized value, \'w\'
 selects the worst value and \'z\' inserts a zero byte.
-The default BYTEORDER is \'543210\' for all 48\-bit formats, \'r543210\'
-for the 54\-bit formats, and \'543210wv\' for the 64\-bit formats.
+The default BYTEORDER is \'543210\' for all 48-bit formats, \'r543210\'
+for the 54-bit formats, and \'543210wv\' for the 64-bit formats.
 For example, \'\-v 5,raw48:012345\' prints the raw value of
 attribute 5 with big endian instead of little endian
 byte ordering.
@@ -1306,15 +1354,15 @@ then exits.
 Valid arguments for FORMAT are:
 
 .I raw8
-\- Print the Raw value as six 8\-bit unsigned base\-10 integers.
+\- Print the Raw value as six 8-bit unsigned base-10 integers.
 This may be useful for decoding the meaning of the Raw value.
 
 .I raw16
-\- Print the Raw value as three 16\-bit unsigned base\-10 integers.
+\- Print the Raw value as three 16-bit unsigned base-10 integers.
 This may be useful for decoding the meaning of the Raw value.
 
 .I raw48
-\- Print the Raw value as a 48\-bit unsigned base\-10 integer.
+\- Print the Raw value as a 48-bit unsigned base-10 integer.
 This is the default for most attributes.
 
 .I hex48
@@ -1322,15 +1370,15 @@ This is the default for most attributes.
 This may be useful for decoding the meaning of the Raw value.
 
 .I raw56
-\- Print the Raw value as a 54\-bit unsigned base\-10 integer.
-This includes the reserved byte which follows the 48\-bit raw value.
+\- Print the Raw value as a 54-bit unsigned base-10 integer.
+This includes the reserved byte which follows the 48-bit raw value.
 
 .I hex56
 \- Print the Raw value as a 14 digit hexadecimal number.
-This includes the reserved byte which follows the 48\-bit raw value.
+This includes the reserved byte which follows the 48-bit raw value.
 
 .I raw64
-\- Print the Raw value as a 64\-bit unsigned base\-10 integer.
+\- Print the Raw value as a 64-bit unsigned base-10 integer.
 This includes two bytes from the normalized and worst attribute value.
 This raw format is used by some SSD devices with Indilinx controller.
 
@@ -1340,27 +1388,27 @@ This includes two bytes from the normalized and worst attribute value.
 This raw format is used by some SSD devices with Indilinx controller.
 
 .I min2hour
-\- Raw Attribute is power\-on time in minutes.  Its raw value
+\- Raw Attribute is power-on time in minutes.  Its raw value
 will be displayed in the form "Xh+Ym".  Here X is hours, and Y is
 minutes in the range 0\-59 inclusive.  Y is always printed with two
 digits, for example "06" or "31" or "00".
 
 .I sec2hour
-\- Raw Attribute is power\-on time in seconds.  Its raw value
+\- Raw Attribute is power-on time in seconds.  Its raw value
 will be displayed in the form "Xh+Ym+Zs".  Here X is hours, Y is
 minutes in the range 0\-59 inclusive, and Z is seconds in the range
 0\-59 inclusive.  Y and Z are always printed with two digits, for
 example "06" or "31" or "00".
 
 .I halfmin2hour
-\- Raw Attribute is power\-on time, measured in units of 30
+\- Raw Attribute is power-on time, measured in units of 30
 seconds.  This format is used by some Samsung disks.  Its raw value
 will be displayed in the form "Xh+Ym".  Here X is hours, and Y is
 minutes in the range 0\-59 inclusive.  Y is always printed with two
 digits, for example "06" or "31" or "00".
 
 .I msec24hour32
-\- Raw Attribute is power\-on time measured in 32\-bit hours and 24\-bit
+\- Raw Attribute is power-on time measured in 32-bit hours and 24-bit
 milliseconds since last hour update.  It will be displayed in the form
 "Xh+Ym+Z.Ms".  Here X is hours, Y is minutes, Z is seconds and M is
 milliseconds.
@@ -1376,8 +1424,8 @@ specific.
 \- Raw Attribute is ten times the disk temperature in Celsius.
 
 .I raw16(raw16)
-\- Print the raw attribute as a 16\-bit value and two optional
-16\-bit values if these words are nonzero.  This is the default
+\- Print the raw attribute as a 16-bit value and two optional
+16-bit values if these words are nonzero.  This is the default
 for Attributes 5 and 196.
 
 .I raw16(avg16)
@@ -1386,12 +1434,12 @@ and an optional "Average" 16-bit value if the word is nonzero.
 This is the default for Attribute 3.
 
 .I raw24(raw8)
-\- Print the raw attribute as a 24\-bit value and three optional
-8\-bit values if these bytes are nonzero.  This is the default
+\- Print the raw attribute as a 24-bit value and three optional
+8-bit values if these bytes are nonzero.  This is the default
 for Attribute 9.
 
 .I raw24/raw24
-\- Raw Attribute contains two 24\-bit values. The first is the
+\- Raw Attribute contains two 24-bit values. The first is the
 number of load cycles.  The second is the number of unload cycles.
 The difference between these two values is the number of times that
 the drive was unexpectedly powered off (also called an emergency
@@ -1400,8 +1448,8 @@ emergency unload is equivalent to that created by one hundred normal
 unloads.
 
 .I raw24/raw32
-\- Raw attribute is an error rate which consists of a 24\-bit error
-count and a 32\-bit total count.
+\- Raw attribute is an error rate which consists of a 24-bit error
+count and a 32-bit total count.
 
 The following old arguments to \'\-v\' are also still valid:
 
@@ -1465,7 +1513,7 @@ is not reset if uncorrectable sectors are reallocated
 
 .I 220,temp
 \- same as:
-.I 220,raw48,Temperature_Celsius.
+.I 220,tempminmax,Temperature_Celsius.
 
 Note: a table of hard drive models, listing which Attribute
 corresponds to temperature, can be found at:
@@ -1473,43 +1521,49 @@ corresponds to temperature, can be found at:
 .TP
 .B \-F TYPE, \-\-firmwarebug=TYPE
 [ATA only] Modifies the behavior of \fBsmartctl\fP to compensate for some
-known and understood device firmware or driver bug.  Except \'swapid\',
-the arguments to this option are exclusive, so that only the final
-option given is used.  The valid values are:
+known and understood device firmware or driver bug.  This option may be used
+multiple times.  The valid arguments are:
 
 .I none
 \- Assume that the device firmware obeys the ATA specifications.  This
 is the default, unless the device has presets for \'\-F\' in the
-device database (see note below).
+drive database.  Using this option on the command line will over-ride any
+preset values.
+
+.I nologdir
+\- Suppresses read attempts of SMART or GP Log Directory.
+Support for all standard logs is assumed without an actual check.
+Some Intel SSDs may freeze if log address 0 is read.
 
 .I samsung
 \- In some Samsung disks (example: model SV4012H Firmware Version:
-RM100\-08) some of the two\- and four\-byte quantities in the SMART data
-structures are byte\-swapped (relative to the ATA specification).
+RM100-08) some of the two- and four-byte quantities in the SMART data
+structures are byte-swapped (relative to the ATA specification).
 Enabling this option tells \fBsmartctl\fP to evaluate these quantities
-in byte\-reversed order.  Some signs that your disk needs this option
-are (1) no self\-test log printed, even though you have run self\-tests;
+in byte-reversed order.  Some signs that your disk needs this option
+are (1) no self-test log printed, even though you have run self-tests;
 (2) very large numbers of ATA errors reported in the ATA error log;
 (3) strange and impossible values for the ATA error log timestamps.
 
 .I samsung2
 \- In some Samsung disks the number of ATA errors reported is byte swapped.
 Enabling this option tells \fBsmartctl\fP to evaluate this quantity in
-byte\-reversed order. An indication that your Samsung disk needs this
-option is that the self\-test log is printed correctly, but there are a
+byte-reversed order. An indication that your Samsung disk needs this
+option is that the self-test log is printed correctly, but there are a
 very large number of errors in the SMART error log.  This is because
 the error count is byte swapped.  Thus a disk with five errors
 (0x0005) will appear to have 20480 errors (0x5000).
 
 .I samsung3
-\- Some Samsung disks (at least SP2514N with Firmware VF100\-37) report
-a self\-test still in progress with 0% remaining when the test was already
-completed. Enabling this option modifies the output of the self\-test
+\- Some Samsung disks (at least SP2514N with Firmware VF100-37) report
+a self-test still in progress with 0% remaining when the test was already
+completed. Enabling this option modifies the output of the self-test
 execution status (see options \'\-c\' or \'\-a\' above) accordingly.
 
-Note that an explicit \'\-F\' option on the command line will
-over\-ride any preset values for \'\-F\' (see the \'\-P\' option
-below).
+.I xerrorlba
+\- Fixes LBA byte ordering in Extended Comprehensive SMART error log.
+Some disk use little endian byte ordering instead of ATA register
+ordering to specifiy the LBA addresses in the log entries.
 
 .I swapid
 \- Fixes byte swapped ATA identify strings (device name, serial number,
@@ -1522,8 +1576,8 @@ in the \fBsmartmontools\fP database, then the presets are used.
 
 \fBsmartctl\fP can automatically set appropriate options for known
 drives.  For example, the Maxtor 4D080H4 uses Attribute 9 to stores
-power\-on time in minutes whereas most drives use that Attribute to
-store the power\-on time in hours.  The command\-line option \'\-v
+power-on time in minutes whereas most drives use that Attribute to
+store the power-on time in hours.  The command-line option \'\-v
 9,minutes\' ensures that \fBsmartctl\fP correctly interprets Attribute
 9 in this case, but that option is preset for the Maxtor 4D080H4 and
 so need not be specified by the user on the \fBsmartctl\fP command
@@ -1545,9 +1599,9 @@ The valid arguments to this option are:
 
 .I use
 \- if a drive is recognized, then use the stored presets for it.  This
-is the default. Note that presets will NOT over\-ride additional
-Attribute interpretation (\'\-v N,something\') command\-line options or
-explicit \'\-F\' command\-line options..
+is the default. Note that presets will NOT override additional
+Attribute interpretation (\'\-v N,something\') command-line options or
+explicit \'\-F\' command-line options..
 
 .I ignore
 \- do not use presets.
@@ -1652,19 +1706,28 @@ Example:
 .fi
 
 .TP
-.B SMART RUN/ABORT OFFLINE TEST AND SELF\-TEST OPTIONS:
+.B SMART RUN/ABORT OFFLINE TEST AND self-test OPTIONS:
 .TP
 .B \-t TEST, \-\-test=TEST
 Executes TEST immediately.  The \'\-C\' option can be used in
 conjunction with this option to run the short or long (and also for
-ATA devices, selective or conveyance) self\-tests in captive mode
+ATA devices, selective or conveyance) self-tests in captive mode
 (known as "foreground mode" for SCSI devices).  Note that only one
 test type can be run at a time, so only one test type should be
 specified per command line.  Note also that if a computer is shutdown
-or power cycled during a self\-test, no harm should result.  The
-self\-test will either be aborted or will resume automatically.
+or power cycled during a self-test, no harm should result.  The
+self-test will either be aborted or will resume automatically.
+
+All \'\-t TEST\' commands can be given during normal system operation
+unless captive mode (\'\-C\' option) is used.
+A running self-test can, however, degrade performance of the drive.
+Frequent I/O requests from the operating system increase the duration
+of a test.  These impacts may vary from device to device.
 
-The valid arguments to this option are:  
+If a test failure occurs then the device may discontinue the testing
+and report the result immediately.
+
+The valid arguments to this option are:
 
 .I offline
 \- [ATA] runs SMART Immediate Offline Test.  This immediately
@@ -1696,11 +1759,11 @@ tests.  The "Self" tests check the electrical and mechanical
 performance as well as the read performance of the disk.  Their
 results are reported in the Self Test Error Log, readable with
 the \'\-l selftest\' option.  Note that on some disks the progress of the
-self\-test can be monitored by watching this log during the self\-test; with other disks
+self-test can be monitored by watching this log during the self-test; with other disks
 use the \'\-c\' option to monitor progress.
 
 .I short
-\- [SCSI] runs the "Background short" self\-test.
+\- [SCSI] runs the "Background short" self-test.
 
 .I long
 \- [ATA] runs SMART Extended Self Test (tens of minutes). This is a
@@ -1709,12 +1772,12 @@ above.  Note that this command can be given during normal
 system operation (unless run in captive mode \- see the \'\-C\' option below).
 
 .I long
-\- [SCSI] runs the "Background long" self\-test.
+\- [SCSI] runs the "Background long" self-test.
 
 .I conveyance
 \- [ATA only] runs a SMART Conveyance Self Test (minutes).  This
-self\-test routine is intended to identify damage incurred during
-transporting of the device. This self\-test routine should take on the
+self-test routine is intended to identify damage incurred during
+transporting of the device. This self-test routine should take on the
 order of minutes to complete.  Note that this command can be given
 during normal system operation (unless run in captive mode \- see the
 \'\-C\' option below).
@@ -1749,21 +1812,21 @@ overlap partially or completely, for example:
 .nf
   smartctl \-t select,0\-10 \-t select,5\-15 \-t select,10\-20 /dev/hda
 .fi
-The results of the selective self\-test can be obtained (both during
-and after the test) by printing the SMART self\-test log, using the
+The results of the selective self-test can be obtained (both during
+and after the test) by printing the SMART self-test log, using the
 \'\-l selftest\' option to smartctl.
 
 Selective self tests are particularly useful as disk capacities
 increase: an extended self test (smartctl \-t long) can take several
-hours.  Selective self\-tests are helpful if (based on SYSLOG error
-messages, previous failed self\-tests, or SMART error log entries) you
+hours.  Selective self-tests are helpful if (based on SYSLOG error
+messages, previous failed self-tests, or SMART error log entries) you
 suspect that a disk is having problems at a particular range of
 Logical Block Addresses (LBAs).
 
-Selective self\-tests can be run during normal system operation (unless
+Selective self-tests can be run during normal system operation (unless
 done in captive mode \- see the \'\-C\' option below).
 
-The following variants of the selective self\-test command use spans based
+The following variants of the selective self-test command use spans based
 on the ranges from past tests already stored on the disk:
 
 .I select,redo[+SIZE]
@@ -1815,30 +1878,30 @@ that the last test was aborted by the host. Otherwise it run the \'next\'
 (above) test.
 
 .I afterselect,on
-\- [ATA only] perform an offline read scan after a Selective Self\-test
+\- [ATA only] perform an offline read scan after a Selective self-test
 has completed. This option must be used together with one or more of
 the \fIselect,N\-M\fP options above. If the LBAs that have been
-specified in the Selective self\-test pass the test with no errors
+specified in the Selective self-test pass the test with no errors
 found, then read scan the \fBremainder\fP of the disk.  If the device
-is powered\-cycled while this read scan is in progress, the read scan
+is powered-cycled while this read scan is in progress, the read scan
 will be automatically resumed after a time specified by the pending
 timer (see below).  The value of this option is preserved between
-selective self\-tests.
+selective self-tests.
 
 .I afterselect,off
 \- [ATA only] do not read scan the remainder of the disk after a
-Selective self\-test has completed.  This option must be use together
+Selective self-test has completed.  This option must be use together
 with one or more of the \fIselect,N\-M\fP options above.  The value of this
-option is preserved between selective self\-tests.
+option is preserved between selective self-tests.
 
 .I pending,N 
 \- [ATA only] set the pending offline read scan timer to N minutes.
 Here N is an integer in the range from 0 to 65535 inclusive.  If the
-device is powered off during a read scan after a Selective self\-test,
-then resume the test automatically N minutes after power\-up.  This
+device is powered off during a read scan after a Selective self-test,
+then resume the test automatically N minutes after power-up.  This
 option must be use together with one or more of the \fIselect,N\-M\fP
 options above. The value of this option is preserved between selective
-self\-tests.
+self-tests.
 
 .I vendor,N
 \- [ATA only] issues the ATA command SMART EXECUTE OFF-LINE IMMEDIATE
@@ -1852,32 +1915,29 @@ T13/1699-D Revision 6a (ATA8-ACS).  Note that the subcommands
 \fBWARNING: Only run subcommands documented by the vendor of the
 device.\fP
 
-Example for Intel (X18/X25\-M G2, 320, 520 and 710 Series) SSDs only:
+Example for Intel (X18/X25-M G2, 320, 520 and 710 Series) SSDs only:
 The subcommand 0x40 (\'\-t vendor,0x40\') clears the timed workload
 related SMART attributes (226, 227, 228).  Note that the raw values of
 these attributes are held at 65535 (0xffff) until the workload timer
 reaches 60 minutes.
 
 .I force
-\- [ATA only] start new self\-test even if another test is already running.
-By default a running self\-test will not be interrupted to begin another
+\- start new self-test even if another test is already running.
+By default a running self-test will not be interrupted to begin another
 test.
-
-.I scttempint,N[,p]
-\- is no longer supported, use \'\-l scttempint,N[,p]\' instead, see above.
 .TP
 .B \-C, \-\-captive
-[ATA] Runs self\-tests in captive mode.  This has no effect with \'\-t
+[ATA] Runs self-tests in captive mode.  This has no effect with \'\-t
 offline\' or if the \'\-t\' option is not used.
 
 \fBWARNING: Tests run in captive mode may busy out the drive for the
 length of the test.  Only run captive tests on drives without any
 mounted partitions!\fP
 
-[SCSI] Runs the self\-test in "Foreground" mode.
+[SCSI] Runs the self-test in "Foreground" mode.
 .TP
 .B \-X, \-\-abort
-Aborts non\-captive SMART Self Tests.  Note that this
+Aborts non-captive SMART Self Tests.  Note that this
 command will abort the Offline Immediate Test routine only if your
 disk has the "Abort Offline collection upon new command" capability.
 .PP
@@ -1948,14 +2008,14 @@ Disable SMART monitoring and data log collection on drive /dev/hdd .
 .fi
 Enable SMART on drive /dev/hda, enable automatic offline
 testing every four hours, and enable autosaving of
-SMART Attributes.  This is a good start\-up line for your system\'s
+SMART Attributes.  This is a good start-up line for your system\'s
 init files.  You can issue this command on a running system.
 .PP
 .nf
 .B smartctl \-t long /dev/hdc
 .fi
-Begin an extended self\-test of drive /dev/hdc.  You can issue this
-command on a running system.  The results can be seen in the self\-test
+Begin an extended self-test of drive /dev/hdc.  You can issue this
+command on a running system.  The results can be seen in the self-test
 log visible with the \'\-l selftest\' option after it has completed.
 .PP
 .nf
@@ -1970,14 +2030,14 @@ the SMART error log, which can be seen with the \'\-l error\' option.
 .nf
 .B smartctl \-A \-v 9,minutes /dev/hda
 .fi
-Shows the vendor Attributes, when the disk stores its power\-on time
+Shows the vendor Attributes, when the disk stores its power-on time
 internally in minutes rather than hours.
 .PP
 .nf
 .B smartctl \-q errorsonly \-H \-l selftest /dev/hda
 .fi
 Produces output only if the device returns failing SMART status,
-or if some of the logged self\-tests ended with errors.
+or if some of the logged self-tests ended with errors.
 .PP
 .nf
 .B smartctl \-q silent \-a /dev/hda
@@ -1987,7 +2047,7 @@ printed output.  You must use the exit status (the
 .B $?
 shell variable) to learn if any Attributes are out of bound, if the
 SMART status is failing, if there are errors recorded in the
-self\-test log, or if there are errors recorded in the disk error log.
+self-test log, or if there are errors recorded in the disk error log.
 .PP
 .nf
 .B smartctl \-a \-d 3ware,0 /dev/sda
@@ -2016,13 +2076,13 @@ Examine all SMART data for the first SATA (not SAS) disk connected to a
 .nf
 .B smartctl \-t short \-d 3ware,3 /dev/sdb
 .fi
-Start a short self\-test on the fourth ATA disk connected to the 3ware RAID
+Start a short self-test on the fourth ATA disk connected to the 3ware RAID
 controller card which is the second SCSI device /dev/sdb.
 .PP
 .nf
 .B smartctl \-t long \-d areca,4 /dev/sg2
 .fi
-Start a long self\-test on the fourth SATA disk connected to an Areca RAID
+Start a long self-test on the fourth SATA disk connected to an Areca RAID
 controller addressed by /dev/sg2.
 .PP
 .nf
@@ -2037,15 +2097,15 @@ first HighPoint RocketRAID controller card.
 .B smartctl \-t short \-d hpt,1/1/2 /dev/sda    (under Linux)
 .B smartctl \-t short \-d hpt,1/1/2 /dev/hptrr    (under FreeBSD)
 .fi
-Start a short self\-test on the (S)ATA disk connected to second pmport on the
+Start a short self-test on the (S)ATA disk connected to second pmport on the
 first channel of the first HighPoint RocketRAID controller card.
 .PP
 .nf
 .B smartctl \-t select,10\-100 \-t select,30\-300 \-t afterselect,on \-t pending,45 /dev/hda
 .fi
-Run a selective self\-test on LBAs 10 to 100 and 30 to 300.  After the
-these LBAs have been tested, read\-scan the remainder of the disk.  If the disk is
-power\-cycled during the read\-scan, resume the scan 45 minutes after power to the
+Run a selective self-test on LBAs 10 to 100 and 30 to 300.  After the
+these LBAs have been tested, read-scan the remainder of the disk.  If the disk is
+power-cycled during the read-scan, resume the scan 45 minutes after power to the
 device is restored.
 .PP
 .nf
@@ -2058,7 +2118,7 @@ RAID controller card.
 The return values of \fBsmartctl\fP are defined by a bitmask.  If all
 is well with the disk, the return value (exit status) of
 \fBsmartctl\fP is 0 (all bits turned off).  If a problem occurs, or an
-error, potential error, or fault is detected, then a non\-zero status
+error, potential error, or fault is detected, then a non-zero status
 is returned.  In this case, the eight different bits in the return
 value have the following meanings for ATA disks; some of these values
 may also be returned for SCSI disks.
@@ -2089,9 +2149,9 @@ past.
 The device error log contains records of errors.
 .TP
 .B Bit 7:
-The device self\-test log contains records of errors.
+The device self-test log contains records of errors.
 [ATA only] Failed self-tests outdated by a newer successful extended
-self\-test are ignored.
+self-test are ignored.
 .PP
 To test within the shell for whether or not the different bits are
 turned on or off, you can use the following type of construction (this
@@ -2121,17 +2181,21 @@ once by \fBsmartctl\fP for each initiator for each activation of the
 condition.
 
 .PP
-.SH AUTHOR
-\fBBruce Allen\fP smartmontools\-support@lists.sourceforge.net
-.fi
+.SH AUTHORS
+\fBBruce Allen\fP
+.br
 University of Wisconsin \- Milwaukee Physics Department
+.br
+\fBChristian Franke\fP (Windows interface, C++ redesign, most enhancements
+since 2009)
+.br
+\fBsmartmontools\-support@lists.sourceforge.net\fP
 
 .PP
 .SH CONTRIBUTORS
 The following have made large contributions to smartmontools:
 .nf
 \fBCasper Dik\fP (Solaris SCSI interface)
-\fBChristian Franke\fP (Windows interface, C++ redesign, USB support, ...)
 \fBDouglas Gilbert\fP (SCSI subsystem)
 \fBGuido Guenther\fP (Autoconf/Automake packaging)
 \fBGeoffrey Keating\fP (Darwin ATA interface)
@@ -2153,7 +2217,7 @@ Many other individuals have made smaller contributions and corrections.
 .fi
 This code was derived from the smartsuite package, written by Michael
 Cornwell, and from the previous UCSC smartsuite package.  It extends
-these to cover ATA\-5 disks.  This code was originally developed as a
+these to cover ATA-5 disks.  This code was originally developed as a
 Senior Thesis by Michael Cornwell at the Concurrent Systems Laboratory
 (now part of the Storage Systems Research Center), Jack Baskin School
 of Engineering, University of California, Santa
@@ -2172,18 +2236,18 @@ REFERENCES FOR SMART
 .fi
 An introductory article about smartmontools is \fIMonitoring Hard
 Disks with SMART\fP, by Bruce Allen, Linux Journal, January 2004,
-pages 74\-77. This is \fBhttp://www.linuxjournal.com/article/6983\fP
+pages 74-77. This is \fBhttp://www.linuxjournal.com/article/6983\fP
 online.
 
 If you would like to understand better how SMART works, and what it
 does, a good place to start is with Sections 4.8 and 6.54 of the first
-volume of the \'AT Attachment with Packet Interface\-7\' (ATA/ATAPI\-7)
+volume of the \'AT Attachment with Packet Interface-7\' (ATA/ATAPI-7)
 specification Revision 4b.  This documents the SMART functionality which the
 \fBsmartmontools\fP utilities provide access to.
 
 .fi
-The functioning of SMART was originally defined by the SFF\-8035i
-revision 2 and the SFF\-8055i revision 1.4 specifications.  These are
+The functioning of SMART was originally defined by the SFF-8035i
+revision 2 and the SFF-8055i revision 1.4 specifications.  These are
 publications of the Small Form Factors (SFF) Committee.
 
 Links to these and other documents may be found on the Links page of the
@@ -2192,4 +2256,4 @@ Links to these and other documents may be found on the Links page of the
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartctl.8.in 3561 2012-06-05 19:49:31Z chrfranke $
+$Id: smartctl.8.in 3799 2013-03-15 17:47:25Z chrfranke $
index 9b414e0a8b8b8b69a9a1646082fb5c6d27337b42..190f9f3af6ded2e07b89ab0066e8b5746cd4404e 100644 (file)
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
 #include <sys/param.h>
 #endif
 
-#if defined(__QNXNTO__) 
-#include <new> // TODO: Why is this include necessary on QNX ?
-#endif
-
 #include "int64.h"
 #include "atacmds.h"
 #include "dev_interface.h"
@@ -55,7 +50,7 @@
 #include "smartctl.h"
 #include "utility.h"
 
-const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 3531 2012-03-27 20:02:25Z chrfranke $"
+const char * smartctl_cpp_cvsid = "$Id: smartctl.cpp 3726 2012-12-12 20:02:48Z chrfranke $"
   CONFIG_H_CVSID SMARTCTL_H_CVSID;
 
 // Globals to control printing
@@ -87,8 +82,10 @@ static void Usage()
 "         Print license, copyright, and version information and exit\n\n"
 "  -i, --info\n"
 "         Show identity information for device\n\n"
+"  --identify[=[w][nvb]]\n"
+"         Show words and bits from IDENTIFY DEVICE data                (ATA)\n\n"
 "  -g NAME, --get=NAME\n"
-"        Get device setting: all, aam, apm, lookahead, security, wcache\n\n"
+"        Get device setting: all, aam, apm, lookahead, security, wcache, rcache\n\n"
 "  -a, --all\n"
 "         Show all SMART information for device\n\n"
 "  -x, --xall\n"
@@ -124,7 +121,7 @@ static void Usage()
 "  -s NAME[,VALUE], --set=NAME[,VALUE]\n"
 "        Enable/disable/change device setting: aam,[N|off], apm,[N|off],\n"
 "        lookahead,[on|off], security-freeze, standby,[N|off|now],\n"
-"        wcache,[on|off]\n\n"
+"        wcache,[on|off], rcache,[on|off]\n\n"
   );
   printf(
 "======================================= READ AND DISPLAY DATA OPTIONS =====\n\n"
@@ -146,13 +143,14 @@ static void Usage()
 "  -v N,OPTION , --vendorattribute=N,OPTION                            (ATA)\n"
 "        Set display OPTION for vendor Attribute N (see man page)\n\n"
 "  -F TYPE, --firmwarebug=TYPE                                         (ATA)\n"
-"        Use firmware bug workaround: none, samsung, samsung2,\n"
-"                                     samsung3, swapid\n\n"
+"        Use firmware bug workaround:\n"
+"        %s, swapid\n\n"
 "  -P TYPE, --presets=TYPE                                             (ATA)\n"
 "        Drive-specific presets: use, ignore, show, showall\n\n"
 "  -B [+]FILE, --drivedb=[+]FILE                                       (ATA)\n"
 "        Read and replace [add] drive database from FILE\n"
 "        [default is +%s",
+    get_valid_firmwarebug_args(),
     get_drivedb_path_add()
   );
 #ifdef SMARTMONTOOLS_DRIVEDBDIR
@@ -179,7 +177,7 @@ static void Usage()
 }
 
 // Values for  --long only options, see parse_options()
-enum { opt_scan = 1000, opt_scan_open, opt_set, opt_smart };
+enum { opt_identify = 1000, opt_scan, opt_scan_open, opt_set, opt_smart };
 
 /* Returns a string containing a formatted list of the valid arguments
    to the option opt or empty on failure. Note 'v' case different */
@@ -214,18 +212,20 @@ static std::string getvalidarglist(int opt)
     return "offline, short, long, conveyance, force, vendor,N, select,M-N, "
            "pending,N, afterselect,[on|off]";
   case 'F':
-    return "none, samsung, samsung2, samsung3, swapid";
+    return std::string(get_valid_firmwarebug_args()) + ", swapid";
   case 'n':
     return "never, sleep, standby, idle";
   case 'f':
     return "old, brief, hex[,id|val]";
   case 'g':
-    return "aam, apm, lookahead, security, wcache";
+    return "aam, apm, lookahead, security, wcache, rcache";
   case opt_set:
     return "aam,[N|off], apm,[N|off], lookahead,[on|off], security-freeze, "
-           "standby,[N|off|now], wcache,[on|off]";
+           "standby,[N|off|now], wcache,[on|off], rcache,[on|off]";
   case 's':
     return getvalidarglist(opt_smart)+", "+getvalidarglist(opt_set);
+  case opt_identify:
+    return "n, wn, w, v, wv, wb";
   case 'v':
   default:
     return "";
@@ -300,6 +300,7 @@ static const char * parse_options(int argc, char** argv,
     { "drivedb",         required_argument, 0, 'B' },
     { "format",          required_argument, 0, 'f' },
     { "get",             required_argument, 0, 'g' },
+    { "identify",        optional_argument, 0, opt_identify },
     { "set",             required_argument, 0, opt_set },
     { "scan",            no_argument,       0, opt_scan      },
     { "scan-open",       no_argument,       0, opt_scan_open },
@@ -439,19 +440,10 @@ static const char * parse_options(int argc, char** argv,
       scsiopts.smart_ss_media_log = true;
       break;
     case 'F':
-      if (!strcmp(optarg,"none")) {
-        ataopts.fix_firmwarebug = FIX_NONE;
-      } else if (!strcmp(optarg,"samsung")) {
-        ataopts.fix_firmwarebug = FIX_SAMSUNG;
-      } else if (!strcmp(optarg,"samsung2")) {
-        ataopts.fix_firmwarebug = FIX_SAMSUNG2;
-      } else if (!strcmp(optarg,"samsung3")) {
-        ataopts.fix_firmwarebug = FIX_SAMSUNG3;
-      } else if (!strcmp(optarg,"swapid")) {
+      if (!strcmp(optarg, "swapid"))
         ataopts.fix_swapped_id = true;
-      } else {
+      else if (!parse_firmwarebug_def(optarg, ataopts.firmwarebugs))
         badarg = true;
-      }
       break;
     case 'c':
       ataopts.smart_general_values = true;
@@ -498,7 +490,7 @@ static const char * parse_options(int argc, char** argv,
         unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg);
         if (!(   sscanf(optarg,"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1
               && 0 < interval && interval <= 0xffff && (n1 == len || n2 == len))) {
-            strcpy(extraerror, "Option -l scttempint,N[,p] must have positive integer N\n");
+            snprintf(extraerror, sizeof(extraerror), "Option -l scttempint,N[,p] must have positive integer N\n");
             badarg = true;
         }
         ataopts.sct_temp_int = interval;
@@ -554,7 +546,7 @@ static const char * parse_options(int argc, char** argv,
           ataopts.sct_erc_writetime = wt;
         }
         else {
-          sprintf(extraerror, "Option -l scterc,[READTIME,WRITETIME] syntax error\n");
+          snprintf(extraerror, sizeof(extraerror), "Option -l scterc,[READTIME,WRITETIME] syntax error\n");
           badarg = true;
         }
       } else if (   !strncmp(optarg, "gplog,"   , sizeof("gplog,"   )-1)
@@ -570,14 +562,14 @@ static const char * parse_options(int argc, char** argv,
         const char * erropt = (gpl ? "gplog" : "smartlog");
         if (!(   n1 == len || n2 == len
               || (n3 == len && (sign == '+' || sign == '-')))) {
-          sprintf(extraerror, "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt);
+          snprintf(extraerror, sizeof(extraerror), "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt);
           badarg = true;
         }
         else if (!(    logaddr <= 0xff && page <= (gpl ? 0xffffU : 0x00ffU)
                    && 0 < nsectors
                    && (nsectors <= (gpl ? 0xffffU : 0xffU) || nsectors == ~0U)
                    && (sign != '-' || page <= nsectors)                       )) {
-          sprintf(extraerror, "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt);
+          snprintf(extraerror, sizeof(extraerror), "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt);
           badarg = true;
         }
         else {
@@ -593,6 +585,22 @@ static const char * parse_options(int argc, char** argv,
     case 'i':
       ataopts.drive_info = scsiopts.drive_info = true;
       break;
+
+    case opt_identify:
+      ataopts.identify_word_level = ataopts.identify_bit_level = 0;
+      if (optarg) {
+        for (int i = 0; optarg[i]; i++) {
+          switch (optarg[i]) {
+            case 'w': ataopts.identify_word_level = 1; break;
+            case 'n': ataopts.identify_bit_level = -1; break;
+            case 'v': ataopts.identify_bit_level = 1; break;
+            case 'b': ataopts.identify_bit_level = 2; break;
+            default: badarg = true;
+          }
+        }
+      }
+      break;
+
     case 'a':
       ataopts.drive_info           = scsiopts.drive_info          = true;
       ataopts.smart_check_status   = scsiopts.smart_check_status  = true;
@@ -618,11 +626,13 @@ static const char * parse_options(int argc, char** argv,
       ataopts.smart_logdir = ataopts.gp_logdir = true;
       ataopts.sct_temp_sts = ataopts.sct_temp_hist = true;
       ataopts.sct_erc_get = true;
+      ataopts.devstat_all_pages = true;
       ataopts.sataphy = true;
       ataopts.get_set_used = true;
       ataopts.get_aam = ataopts.get_apm = true;
       ataopts.get_security = true;
       ataopts.get_lookahead = ataopts.get_wcache = true;
+      scsiopts.get_rcd = scsiopts.get_wce = true;
       scsiopts.smart_background_log = true;
       scsiopts.smart_ss_media_log = true;
       scsiopts.sasphy = true;
@@ -680,6 +690,7 @@ static const char * parse_options(int argc, char** argv,
         ataopts.smart_selftest_type = CONVEYANCE_SELF_TEST;
       } else if (!strcmp(optarg,"force")) {
         ataopts.smart_selftest_force = true;
+        scsiopts.smart_selftest_force = true;
       } else if (!strcmp(optarg,"afterselect,on")) {
         // scan remainder of disk after doing selected segment
         ataopts.smart_selective_args.scan_after_select = 2;
@@ -693,10 +704,10 @@ static const char * parse_options(int argc, char** argv,
        errno=0;
        i=(int)strtol(optarg+strlen("pending,"), &tailptr, 10);
        if (errno || *tailptr != '\0') {
-         sprintf(extraerror, "Option -t pending,N requires N to be a non-negative integer\n");
+          snprintf(extraerror, sizeof(extraerror), "Option -t pending,N requires N to be a non-negative integer\n");
           badarg = true;
        } else if (i<0 || i>65535) {
-         sprintf(extraerror, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i);
+          snprintf(extraerror, sizeof(extraerror), "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i);
           badarg = true;
        } else {
           ataopts.smart_selective_args.pending_time = i+1;
@@ -707,15 +718,15 @@ static const char * parse_options(int argc, char** argv,
         // parse range of LBAs to test
         uint64_t start, stop; int mode;
         if (split_selective_arg(optarg, &start, &stop, &mode)) {
-         sprintf(extraerror, "Option -t select,M-N must have non-negative integer M and N\n");
+          snprintf(extraerror, sizeof(extraerror), "Option -t select,M-N must have non-negative integer M and N\n");
           badarg = true;
         } else {
           if (ataopts.smart_selective_args.num_spans >= 5 || start > stop) {
             if (start > stop) {
-              sprintf(extraerror, "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n",
+              snprintf(extraerror, sizeof(extraerror), "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n",
                 start, stop, optarg);
             } else {
-              sprintf(extraerror,"ERROR: No more than five selective self-test spans may be"
+              snprintf(extraerror, sizeof(extraerror),"ERROR: No more than five selective self-test spans may be"
                 " defined\n");
             }
             badarg = true;
@@ -727,13 +738,13 @@ static const char * parse_options(int argc, char** argv,
           ataopts.smart_selftest_type = SELECTIVE_SELF_TEST;
         }
       } else if (!strncmp(optarg, "scttempint", sizeof("scstempint")-1)) {
-        strcpy(extraerror, "-t scttempint is no longer supported, use -l scttempint instead\n");
+        snprintf(extraerror, sizeof(extraerror), "-t scttempint is no longer supported, use -l scttempint instead\n");
         badarg = true;
       } else if (!strncmp(optarg, "vendor,", sizeof("vendor,")-1)) {
         unsigned subcmd = ~0U; int n = -1;
         if (!(   sscanf(optarg, "%*[a-z],0x%x%n", &subcmd, &n) == 1
               && subcmd <= 0xff && n == (int)strlen(optarg))) {
-          strcpy(extraerror, "Option -t vendor,0xNN syntax error\n");
+          snprintf(extraerror, sizeof(extraerror), "Option -t vendor,0xNN syntax error\n");
           badarg = true;
         }
         else
@@ -819,6 +830,7 @@ static const char * parse_options(int argc, char** argv,
             ataopts.get_aam = ataopts.get_apm = true;
             ataopts.get_security = true;
             ataopts.get_lookahead = ataopts.get_wcache = true;
+            scsiopts.get_rcd = scsiopts.get_wce = true;
           }
           else if (!strcmp(name, "aam")) {
             if (get)
@@ -828,7 +840,7 @@ static const char * parse_options(int argc, char** argv,
             else if (val <= 254)
               ataopts.set_aam = val + 1;
             else {
-              sprintf(extraerror, "Option -s aam,N must have 0 <= N <= 254\n");
+              snprintf(extraerror, sizeof(extraerror), "Option -s aam,N must have 0 <= N <= 254\n");
               badarg = true;
             }
           }
@@ -840,13 +852,14 @@ static const char * parse_options(int argc, char** argv,
             else if (1 <= val && val <= 254)
               ataopts.set_apm = val + 1;
             else {
-              sprintf(extraerror, "Option -s apm,N must have 1 <= N <= 254\n");
+              snprintf(extraerror, sizeof(extraerror), "Option -s apm,N must have 1 <= N <= 254\n");
               badarg = true;
             }
           }
           else if (!strcmp(name, "lookahead")) {
-            if (get)
+            if (get) {
               ataopts.get_lookahead = true;
+            }
             else if (off)
               ataopts.set_lookahead = -1;
             else if (on)
@@ -854,6 +867,16 @@ static const char * parse_options(int argc, char** argv,
             else
               badarg = true;
           }
+          else if (!strcmp(name, "rcache")) {
+            if (get)
+              scsiopts.get_rcd = true;
+            else if (off)
+              scsiopts.set_rcd = -1;
+            else if (on)
+              scsiopts.set_rcd = 1;
+            else
+              badarg = true;
+          }
           else if (get && !strcmp(name, "security")) {
             ataopts.get_security = true;
           }
@@ -869,17 +892,23 @@ static const char * parse_options(int argc, char** argv,
             else if (val <= 255)
               ataopts.set_standby = val + 1;
             else {
-              sprintf(extraerror, "Option -s standby,N must have 0 <= N <= 255\n");
+              snprintf(extraerror, sizeof(extraerror), "Option -s standby,N must have 0 <= N <= 255\n");
               badarg = true;
             }
           }
           else if (!strcmp(name, "wcache")) {
-            if (get)
+            if (get) {
               ataopts.get_wcache = true;
-            else if (off)
+              scsiopts.get_wce = true;
+            }
+            else if (off) {
               ataopts.set_wcache = -1;
-            else if (on)
+              scsiopts.set_wce = -1;
+            }
+            else if (on) {
               ataopts.set_wcache = 1;
+              scsiopts.set_wce = 1;
+            }
             else
               badarg = true;
           }
@@ -941,7 +970,8 @@ static const char * parse_options(int argc, char** argv,
       // a clean way to do it.
       char optstr[] = { (char)optchar, 0 };
       pout("=======> INVALID ARGUMENT TO -%s: %s\n",
-        (optchar == opt_set ? "-set" :
+        (optchar == opt_identify ? "-identify" :
+         optchar == opt_set ? "-set" :
          optchar == opt_smart ? "-smart" : optstr), optarg);
       printvalidarglistmessage(optchar);
       if (extraerror[0])
@@ -1190,7 +1220,7 @@ static int main_worker(int argc, char **argv)
   if (!strcmp(name,"-")) {
     // Parse "smartctl -r ataioctl,2 ..." output from stdin
     if (type || print_type_only) {
-      pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n");
+      pout("-d option is not allowed in conjunction with device name \"-\".\n");
       UsageSummary();
       return FAILCMD;
     }
@@ -1205,7 +1235,7 @@ static int main_worker(int argc, char **argv)
     if (type)
       printvalidarglistmessage('d');
     else
-      pout("Smartctl: please specify device type with the -d option.\n");
+      pout("Please specify device type with the -d option.\n");
     UsageSummary();
     return FAILCMD;
   }
index 3ec3e086f6f417f6b62bcc890b829951a7bd73cf..8820287c6c5f1cdcb8aac09a058aa96edd818f25 100644 (file)
@@ -13,8 +13,8 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -26,7 +26,7 @@
 #ifndef SMARTCTL_H_
 #define SMARTCTL_H_
 
-#define SMARTCTL_H_CVSID "$Id: smartctl.h 3196 2010-10-28 21:31:49Z chrfranke $\n"
+#define SMARTCTL_H_CVSID "$Id: smartctl.h 3727 2012-12-13 17:23:06Z samm2 $\n"
 
 // Return codes (bitmask)
 
index d23497483a8c16e74e149826831f7eeeafb7d7f4..f90f3b699f15062f3e7bba1a0d81cd3c8ca3a7e4 100644 (file)
@@ -1,21 +1,22 @@
 .ig
 Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-$Id: smartd.8.in 3561 2012-06-05 19:49:31Z chrfranke $
+Copyright (C) 2004-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
+
+$Id: smartd.8.in 3799 2013-03-15 17:47:25Z 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 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, write to the Free Software Foundation, Inc.,
-675 Mass Ave, Cambridge, MA 02139, USA.
-This code was originally developed as a Senior Thesis by Michael
-Cornwell at the Concurrent Systems Laboratory (now part of the Storage
-Systems Research Center), Jack Baskin School of Engineering,
-University of California, Santa Cruz. http://ssrc.soe.ucsc.edu/
+
+You should have received a copy of the GNU General Public License
+(for example COPYING); If not, see <http://www.gnu.org/licenses/>.
+
+This code was originally developed as a Senior Thesis by Michael Cornwell
+at the Concurrent Systems Laboratory (now part of the Storage Systems
+Research Center), Jack Baskin School of Engineering, University of
+California, Santa Cruz. http://ssrc.soe.ucsc.edu/
+
 ..
 .TH SMARTD 8 CURRENT_SVN_DATE CURRENT_SVN_VERSION CURRENT_SVN_DATE
 .SH NAME
@@ -38,13 +39,15 @@ CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV
 .\"! It does not contain info specific to other platforms.]
 .\"! .PP
 .\" %ENDIF NOT OS ALL
-\fBsmartd\fP is a daemon that monitors the Self-Monitoring, Analysis
-and Reporting Technology (SMART) system built into many ATA-3 and
-later ATA, IDE and SCSI-3 hard drives. The purpose of SMART is to
-monitor the reliability of the hard drive and predict drive failures,
-and to carry out different types of drive self-tests.  This version of
-\fBsmartd\fP is compatible with ATA/ATAPI-7 and earlier standards (see
-\fBREFERENCES\fP below).
+\fBsmartd\fP is a daemon that monitors the Self-Monitoring, Analysis and
+Reporting Technology (SMART) system built into most ATA/SATA and SCSI/SAS
+hard drives and solid-state drives.
+The purpose of SMART is to monitor the reliability of the hard drive
+and predict drive failures, and to carry out different types of drive
+self-tests.
+This version of \fBsmartd\fP is compatible with
+ACS-2, ATA8-ACS, ATA/ATAPI-7 and earlier standards
+(see \fBREFERENCES\fP below).
 
 \fBsmartd\fP will attempt to enable SMART monitoring on ATA devices
 (equivalent to \fBsmartctl -s on\fP) and polls these and SCSI devices
@@ -57,7 +60,7 @@ command-line option described below.
 
 In addition to logging to a file, \fBsmartd\fP can also be configured
 to send email warnings if problems are detected.  Depending upon the
-type of problem, you may want to run self\-tests on the disk, back up
+type of problem, you may want to run self-tests on the disk, back up
 the disk, replace the disk, or use a manufacturer\'s utility to force
 reallocation of bad or unreadable disk sectors.  If disk problems are
 detected, please see the \fBsmartctl\fP manual page and the
@@ -89,11 +92,11 @@ the contents of the (faulty) configuration file, as if the \fBHUP\fP
 signal had never been received.
 
 When \fBsmartd\fP is running in debug mode, the \fBINT\fP signal
-(normally generated from a shell with CONTROL\-C) is treated in the
+(normally generated from a shell with CONTROL-C) is treated in the
 same way as a \fBHUP\fP signal: it makes \fBsmartd\fP reload its
 configuration file. To exit \fBsmartd\fP use CONTROL-\e
 .\" %IF OS Windows
-(Windows: CONTROL\-Break).
+(Windows: CONTROL-Break).
 .\" %ENDIF OS Windows
 
 On startup, in the absence of the configuration file
@@ -104,10 +107,12 @@ devices that support SMART.  The scanning is done as follows:
 Examine all entries \fB"/dev/hd[a-t]"\fP for IDE/ATA
 devices, and \fB"/dev/sd[a-z]"\fP, \fB"/dev/sd[a-c][a-z]"\fP
 for SCSI or SATA devices.
+Disks behind RAID controllers are not included.
 .\" %ENDIF OS Linux
 .\" %IF OS FreeBSD
 .IP \fBFREEBSD:\fP 9
 Authoritative list of disk devices is obtained from SCSI (CAM) and ATA subsystems.
+Disks behind RAID controllers are not included.
 .\" %ENDIF OS FreeBSD
 .\" %IF OS NetBSD OpenBSD
 .IP \fBNETBSD/OPENBSD:\fP 9
@@ -123,17 +128,11 @@ devices, and entries \fB"/dev/rmt/*"\fP for SCSI tape devices.
 .IP \fBDARWIN:\fP 9
 The IOService plane is scanned for ATA block storage devices.
 .\" %ENDIF OS Darwin
-.\" %IF OS Windows
-.IP \fBWINDOWS\ 9x/ME\fP: 9
-Examine all entries \fB"/dev/hd[a-d]"\fP (bitmask
-from "\\\\.\\SMARTVSD") for IDE/ATA devices.
-Examine all entries \fB"/dev/scsi[0\-9][0\-f]"\fP for SCSI devices 
-on ASPI adapter 0\-9, ID 0\-15.
-.\" %ENDIF OS Windows
 .\" %IF OS Windows Cygwin
-.IP \fBWINDOWS\ NT4/2000/XP/2003/Vista/Win7/2008\fP: 9
-Examine all entries \fB"/dev/sd[a-j]"\fP ("\\\\.\\PhysicalDrive[0-9]")
-for IDE/(S)ATA and SCSI disk devices 
+.IP \fBWINDOWS\fP: 9
+Examine all entries \fB"/dev/sd[a\-z]"\fP, \fB"/dev/sd[a\-c][a\-z]"\fP
+and \fB"/dev/sdd[a\-x]"\fP ("\\\\.\\PhysicalDrive[0\-127]") for
+IDE/(S)ATA and SCSI disk devices.
 
 If a 3ware 9000 controller is installed, examine all entries
 \fB"/dev/sdX,N"\fP for the first logical drive (\'unit\'
@@ -143,30 +142,24 @@ detected behind this controller. Same for a second controller if present.
 If directive \'\-d csmi\' or no \'\-d\' directive is specified,
 examine all entries \fB"/dev/csmi[0\-9],N"\fP for drives behind an Intel
 ICHxR controller with RST driver.
+
+Disks behind Areca RAID controllers are not included.
 .\" %ENDIF OS Windows Cygwin
-.\" %IF OS Cygwin
-.IP \fBCYGWIN\fP: 9
-See "WINDOWS NT4/2000/XP/2003/Vista/Win7/2008" above.
-.\" %ENDIF OS Cygwin
-.\" %IF OS OS2
-.IP \fBOS/2,eComStation\fP: 9
-Use the form \fB"/dev/hd[a\-z]"\fP for IDE/ATA devices.
-.\" %ENDIF OS OS2
 .PP
 \fBsmartd\fP then monitors
 for \fIall\fP possible SMART errors (corresponding to the \fB\'\-a\'\fP
-Directive in the configuration file; see \fBCONFIGURATION FILE\fP
-below). 
+Directive in the configuration file; see the \fBsmartd.conf\fP(5) man page).
 
 .SH 
 OPTIONS
 
 .TP
 .B \-A PREFIX, \-\-attributelog=PREFIX
-[ATA only] Writes \fBsmartd\fP attribute information (normalized and raw
-attribute values) to files \'PREFIX\'\'MODEL\-SERIAL.ata.csv\'.  At each
+Writes \fBsmartd\fP attribute information (normalized and raw
+attribute values) to files \'PREFIX\'\'MODEL\-SERIAL.ata.csv\' or \'PREFIX\'\'VENDOR\-MODEL\-SERIAL.scsi.csv\'.  At each
 check cycle attributes are logged as a line of semicolon separated triplets
 of the form "attribute-ID;attribute-norm-value;attribute-raw-value;".
+For SCSI devices error counters and temperature recorded in the form "counter-name;counter-value;"
 Each line is led by a date string of the form "yyyy-mm-dd HH:MM:SS" (in UTC).
 
 .\" %IF ENABLE_ATTRIBUTELOG
@@ -218,10 +211,10 @@ information to STDOUT rather than logging it to SYSLOG and does not
 terminal.  In this mode, \fBsmartd\fP also prints more verbose
 information about what it is doing than when operating in "daemon"
 mode. In this mode, the \fBINT\fP signal (normally generated from a
-terminal with CONTROL\-C) makes \fBsmartd\fP reload its configuration
+terminal with CONTROL-C) makes \fBsmartd\fP reload its configuration
 file.  Please use CONTROL-\e to exit
 .\" %IF OS Windows
-(Windows: CONTROL\-Break).
+(Windows: CONTROL-Break).
 
 [Windows only] The "debug" mode can be toggled by the command
 \fBsmartd sigusr2\fP. A new console for debug output is opened when
@@ -308,18 +301,12 @@ Windows: Some \fBsyslog\fP functionality is implemented
 internally in \fBsmartd\fP as follows: If no \'\-l\' option
 (or \'\-l daemon\') is specified, messages are written to Windows
 event log or to file \fB./smartd.log\fP if event log is not available
-(Win9x/ME or access denied). By specifying other values of FACILITY,
+(access denied). By specifying other values of FACILITY,
 log output is redirected as follows:
 \'\-l local0\' to file \fB./smartd.log\fP,
 \'\-l local1\' to standard output (redirect with \'>\' to any file),
 \'\-l local2\' to standard error,
 \'\-l local[3-7]\': to file \fB./smartd[1-5].log\fP.
-
-When using the event log, the enclosed utility \fBsyslogevt.exe\fP
-should be registered as an event message file to avoid error
-messages from the event viewer. Use \'\fBsyslogevt -r smartd\fP\'
-to register, \'\fBsyslogevt -u smartd\fP\' to unregister and
-\'\fBsyslogevt\fP\' for more help.
 .\" %ENDIF OS Windows
 .TP
 .B \-n, \-\-no\-fork
@@ -392,7 +379,7 @@ a list of future scheduled self tests to stdout, and then exit with zero
 exit status if all of these steps worked correctly.
 Device's SMART status is not checked.
 
-This option is intended to test whether the '-s REGEX' directives in
+This option is intended to test whether the '\-s REGEX' directives in
 smartd.conf will have the desired effect. The output lists the next test
 schedules, limited to 5 tests per type and device. This is followed by a
 summary of all tests of each device within the next 90 days.
@@ -427,17 +414,19 @@ The default level is 1, so \'\-r ataioctl,1\' and \'\-r ataioctl\' are
 equivalent.
 .TP
 .B \-s PREFIX, \-\-savestates=PREFIX
-[ATA only] Reads/writes \fBsmartd\fP state information from/to files
-\'PREFIX\'\'MODEL\-SERIAL.ata.state\'. This preserves SMART attributes, drive
-min and max temperatures (\-W directive), info about last sent warning email
+Reads/writes \fBsmartd\fP state information from/to files
+\'PREFIX\'\'MODEL\-SERIAL.ata.state\' or \'PREFIX\'\'VENDOR\-MODEL\-SERIAL.scsi.state\'. 
+This preserves SMART attributes, drive min and max temperatures (\-W directive),
+info about last sent warning email
 (\-m directive), and the time of next check of the self-test REGEXP
 (\-s directive) across boot cycles.
 
 .\" %IF ENABLE_SAVESTATES
 If this option is not specified, state information is maintained in files
-\'/usr/local/var/lib/smartmontools/smartd.MODEL\-SERIAL.ata.state\'.
+\'/usr/local/var/lib/smartmontools/smartd.MODEL\-SERIAL.ata.state\' for ATA devices and
+\'/usr/local/var/lib/smartmontools/smartd.VENDOR\-MODEL\-SERIAL.scsi.state\' for SCSI devices.
 To disable state files, specify this option with an empty string
-argument: \'-s ""\'.
+argument: \'\-s ""\'.
 .\" %ENDIF ENABLE_SAVESTATES
 MODEL and SERIAL are build from drive identify information, invalid
 characters are replaced by underline.
@@ -453,6 +442,22 @@ always (re)written after reading the configuration file, before rereading
 the configuration file (SIGHUP), before smartd shutdown, and after a check
 forced by SIGUSR1. After a normal check cycle, a file is only rewritten if
 an important change (which usually results in a SYSLOG output) occurred.
+.TP
+.B \-w PATH, \-\-warnexec=PATH
+[NEW EXPERIMENTAL SMARTD FEATURE]
+Run the executable PATH instead of the default script when smartd
+needs to send warning messages.  PATH must point to an executable binary
+file or script.
+The default script is
+.\" %IF NOT OS Windows
+\fB/usr/local/etc/smartd_warning.sh\fP.
+.\" %ENDIF NOT OS Windows
+.\" %IF OS ALL
+(Windows: EXEDIR/smartd_warning.cmd)
+.\" %ENDIF OS ALL
+.\" %IF OS Windows
+.\"! \fBEXEDIR/smartd_warning.cmd\fP.
+.\" %ENDIF OS Windows
 .\" %IF OS Windows
 .TP
 .B \-\-service
@@ -570,7 +575,7 @@ to read:
        ...;daemon.info;...          /var/adm/messages
 .fi
 Alternatively, you can use a local facility to log messages: please
-see the \fBsmartd\fP '-l' command-line option described above.
+see the \fBsmartd\fP '\-l' command-line option described above.
 
 .\" %ENDIF OS Solaris
 .\" %IF OS Cygwin
@@ -587,7 +592,7 @@ The service can be started and stopped by the start-up script as usual
 .\" %ENDIF OS Cygwin
 .\" %IF OS Windows
 On Windows, the log messages are written to the event log or to a file.
-See documentation of the '-l FACILITY' option above for details.
+See documentation of the '\-l FACILITY' option above for details.
 
 On Windows, the following built-in commands can be used to control
 \fBsmartd\fP, if running as a daemon:
@@ -609,22 +614,24 @@ The Windows Version of \fBsmartd\fP has buildin support for services:
 \'\fBsmartd install [options]\fP\' installs a service
 named "smartd" (display name "SmartD Service") using the command line
 \'/INSTALLPATH/smartd.exe \-\-service [options]\'.
+This also installs smartd.exe as a event message file for the Windows
+event viewer.
 
-\'\fBsmartd remove\fP\' can later be used to remove the service entry
-from registry.
+\'\fBsmartd remove\fP\' can later be used to remove the service and
+event message entries from the registry.
 
 Upon startup, the smartd service changes the working directory
 to its own installation path. If smartd.conf and blat.exe are stored
 in this directory, no \'-c\' option and \'-M exec\' directive is needed.
 
-The debug mode (\'-d\', \'-q onecheck\') does not work if smartd is
+The debug mode (\'\-d\', \'\-q onecheck\') does not work if smartd is
 running as service.
 
 The service can be controlled as usual with Windows commands \'net\'
 or \'sc\' (\'\fBnet start smartd\fP\', \'\fBnet stop smartd\fP\').
 
 Pausing the service (\'\fBnet pause smartd\fP\') sets the interval between
-disk checks (\'-i N\') to infinite.
+disk checks (\'\-i N\') to infinite.
 
 Continuing the paused service (\'\fBnet continue smartd\fP\') resets the
 interval and rereads the configuration file immediately (like \fBSIGHUP\fP):
@@ -671,7 +678,7 @@ Forking the daemon failed.
 Couldn\'t create PID file.
 .TP
 .B 5:
-Config file does not exist (only returned in conjunction with the \'-c\' option).
+Config file does not exist (only returned in conjunction with the \'\-c\' option).
 .TP
 .B 6:
 Config file exists, but cannot be read.
@@ -716,17 +723,21 @@ status is then 128 plus the signal number.  For example if
 is killed by SIGKILL (signal 9) then the exit status is 137.
 
 .PP
-.SH AUTHOR
-\fBBruce Allen\fP smartmontools\-support@lists.sourceforge.net
-.fi
+.SH AUTHORS
+\fBBruce Allen\fP
+.br
 University of Wisconsin \- Milwaukee Physics Department
+.br
+\fBChristian Franke\fP (Windows interface, C++ redesign, most enhancements
+since 2009)
+.br
+\fBsmartmontools\-support@lists.sourceforge.net\fP
 
 .PP
 .SH CONTRIBUTORS
 The following have made large contributions to smartmontools:
 .nf
 \fBCasper Dik\fP (Solaris SCSI interface)
-\fBChristian Franke\fP (Windows interface, C++ redesign, USB support, ...)
 \fBDouglas Gilbert\fP (SCSI subsystem)
 \fBGuido Guenther\fP (Autoconf/Automake packaging)
 \fBGeoffrey Keating\fP (Darwin ATA interface)
@@ -747,7 +758,7 @@ Many other individuals have made smaller contributions and corrections.
 .fi
 This code was derived from the smartsuite package, written by Michael
 Cornwell, and from the previous UCSC smartsuite package.  It extends
-these to cover ATA\-5 disks.  This code was originally developed as a
+these to cover ATA-5 disks.  This code was originally developed as a
 Senior Thesis by Michael Cornwell at the Concurrent Systems Laboratory
 (now part of the Storage Systems Research Center), Jack Baskin School
 of Engineering, University of California, Santa
@@ -768,18 +779,18 @@ REFERENCES FOR SMART
 .fi
 An introductory article about smartmontools is \fIMonitoring Hard
 Disks with SMART\fP, by Bruce Allen, Linux Journal, January 2004,
-pages 74\-77. This is \fBhttp://www.linuxjournal.com/article/6983\fP
+pages 74-77. This is \fBhttp://www.linuxjournal.com/article/6983\fP
 online.
 
 If you would like to understand better how SMART works, and what it
 does, a good place to start is with Sections 4.8 and 6.54 of the first
-volume of the \'AT Attachment with Packet Interface\-7\' (ATA/ATAPI\-7)
+volume of the \'AT Attachment with Packet Interface-7\' (ATA/ATAPI-7)
 specification Revision 4b.  This documents the SMART functionality which the
 \fBsmartmontools\fP utilities provide access to.
 
 .fi
-The functioning of SMART was originally defined by the SFF\-8035i
-revision 2 and the SFF\-8055i revision 1.4 specifications.  These are
+The functioning of SMART was originally defined by the SFF-8035i
+revision 2 and the SFF-8055i revision 1.4 specifications.  These are
 publications of the Small Form Factors (SFF) Committee.
 
 Links to these and other documents may be found on the Links page of the
@@ -788,4 +799,4 @@ Links to these and other documents may be found on the Links page of the
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartd.8.in 3561 2012-06-05 19:49:31Z chrfranke $
+$Id: smartd.8.in 3799 2013-03-15 17:47:25Z chrfranke $
index 7605d5c7c8126937e4fba1d2b1f8866832dbe561..5ef85b1bae0157361fdd2b19fbc47217e9c3c1b9 100644 (file)
@@ -2,7 +2,7 @@
 
 # Home page is: http://smartmontools.sourceforge.net
 
-# $Id: smartd.conf 3128 2010-07-27 13:08:31Z chrfranke $
+# $Id: smartd.conf 3651 2012-10-18 15:11:36Z samm2 $
 
 # smartd will re-read the configuration file if it receives a HUP
 # signal
@@ -83,10 +83,11 @@ DEVICESCAN
 #/dev/twa0 -d 3ware,1 -a -s L/../../2/03
 
 # Monitor 2 SATA (not SAS) disks connected to a 3ware 9000 controller which
-# uses the 3w-sas driver (Linux, FreeBSD). Start long self-tests Tuesdays
+# uses the 3w-sas driver (Linux). Start long self-tests Tuesdays
 # between 1-2 and 3-4 am.
+# On FreeBSD /dev/tws0 should be used instead
 #/dev/twl0 -d 3ware,0 -a -s L/../../2/01
-#/dev/twa0 -d 3ware,1 -a -s L/../../2/03
+#/dev/twl0 -d 3ware,1 -a -s L/../../2/03
 
 # Same as above for Windows. Option '-d 3ware,N' is not necessary,
 # disk (port) number is specified in device name.
index 06425eea68036db55374d2abfe5c1eaf60d73566..a4b093c05dfc2e8fd09e4119f334e2e34ae36ee9 100644 (file)
@@ -1,21 +1,22 @@
 .ig
 Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
+Copyright (C) 2004-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
 
-$Id: smartd.conf.5.in 3561 2012-06-05 19:49:31Z chrfranke $
+$Id: smartd.conf.5.in 3741 2013-01-02 17:06:54Z 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
-Software Foundation; either version 2, or (at your option) any later
-version.
+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, write to the Free Software Foundation, Inc., 675
-Mass Ave, Cambridge, MA 02139, USA.
+You should have received a copy of the GNU General Public License
+(for example COPYING); If not, see <http://www.gnu.org/licenses/>.
 
 This code was originally developed as a Senior Thesis by Michael Cornwell
 at the Concurrent Systems Laboratory (now part of the Storage Systems
 Research Center), Jack Baskin School of Engineering, University of
 California, Santa Cruz. http://ssrc.soe.ucsc.edu/
+
 ..
 .TH SMARTD.CONF 5 CURRENT_SVN_DATE CURRENT_SVN_VERSION CURRENT_SVN_DATE
 .SH NAME
@@ -36,9 +37,7 @@ CURRENT_SVN_VERSION CURRENT_SVN_DATE CURRENT_SVN_REV
 .\"! .PP
 .\" %ENDIF NOT OS ALL
 \fB/usr/local/etc/smartd.conf\fP is the configuration file for the \fBsmartd\fP
-daemon, which monitors the Self-Monitoring, Analysis and Reporting
-Technology (SMART) system built into many ATA-3 and later ATA, IDE and
-SCSI-3 hard drives.
+daemon.
 
 If the configuration file \fB/usr/local/etc/smartd.conf\fP is present,
 \fBsmartd\fP reads it at startup, before \fBfork\fP(2)ing into the
@@ -49,50 +48,16 @@ re-read the configuration file. This signal can be generated by typing
 \fB\<CONTROL-C\>\fP in the terminal window where \fBsmartd\fP is
 running.
 
-.SH CONFIGURATION FILE /usr/local/etc/smartd.conf
 In the absence of a configuration file
-\fBsmartd\fP will try to open all available devices.
-.\" %IF OS Linux
-Under linux \fBsmartd\fP will try to open the 20 ATA devices
-.B /dev/hd[a-t] 
-and the 26 SCSI devices
-.B /dev/sd[a-z].
-.\" %ENDIF OS Linux
-.\" %IF OS FreeBSD
-Under FreeBSD, 
-\fBsmartd\fP
-will try to open all existing ATA/SATA devices (using ATA subsystem)
-.B /dev/ad[0-9]+
-and all existing SCSI/SAS/AHCI devices (using CAM subsystem).
-.\" %ENDIF OS FreeBSD
-.\" %IF OS NetBSD OpenBSD
-Under NetBSD/OpenBSD, 
-\fBsmartd\fP
-will try to open all existing ATA devices (with entries in /dev)
-.B /dev/wd[0-9]+c
-and all existing SCSI devices
-.B /dev/sd[0-9]+c.
-.\" %ENDIF OS NetBSD OpenBSD
-.\" %IF OS Solaris
-Under Solaris \fBsmartd\fP will try to open all entries \fB"/dev/rdsk/c?t?d?s?"\fP for IDE/ATA and SCSI disk
-devices, and entries \fB"/dev/rmt/*"\fP for SCSI tape devices.
-.\" %ENDIF OS Solaris
-.\" %IF OS Windows
-Under Windows \fBsmartd\fP will try to open all entries \fB"/dev/hd[a-j]"\fP ("\\\\.\\PhysicalDrive[0-9]")
-for IDE/ATA devices on WinNT4/2000/XP, \fB"/dev/hd[a-d]"\fP
-(bitmask from "\\\\.\\SMARTVSD") for IDE/ATA devices on Win95/98/98SE/ME,
-and \fB"/dev/scsi[0-9][0-7]"\fP (ASPI adapter 0-9, ID 0-7) for SCSI
-devices on all versions of Windows.
-.\" %ENDIF OS Windows
-.\" %IF OS Darwin
-Under Darwin, \fBsmartd\fP will open any ATA block storage device.
-.\" %ENDIF OS Darwin
+\fBsmartd\fP will try to open all available devices
+(see \fBsmartd\fP(8) man page).
+A configuration file with a single line \fB\'DEVICESCAN \-a'\fP
+would have the same effect.
 
 This can be annoying if you have an ATA or SCSI device that hangs or
 misbehaves when receiving SMART commands.  Even if this causes no
-problems, you may be annoyed by the string of error log messages about
-block-major devices that can\'t be found, and SCSI devices that can\'t
-be opened.
+problems, you may be annoyed by the string of error log messages about devices
+that can\'t be opened.
 
 One can avoid this problem, and gain more control over the types of
 events monitored by
@@ -176,6 +141,7 @@ Section below!
 .B \ \ /dev/sda -d megaraid,0 -a -s S/../.././01
 .B \ \ /dev/sda -d megaraid,1 -a -s S/../.././02
 .B \ \ /dev/sda -d megaraid,2 -a -s S/../.././03
+.B \ \ /dev/bus/0 -d megaraid,2 -a -s S/../.././03
 .B
 .B #
 .\" %ENDIF OS Linux
@@ -202,8 +168,14 @@ Section below!
 .B # Two SATA (not SAS) disks on a 3ware 9750 controller.
 .B # Start long self-tests Sundays between midnight and
 .B # 1am and 2-3 am
+.\" %IF OS Linux
 .B \ \ /dev/twl0 -d 3ware,0 -a -s L/../../7/00
 .B \ \ /dev/twl0 -d 3ware,1 -a -s L/../../7/02
+.\" %ENDIF OS Linux
+.\" %IF OS FreeBSD
+.B \ \ /dev/tws0 -d 3ware,0 -a -s L/../../7/00
+.B \ \ /dev/tws0 -d 3ware,1 -a -s L/../../7/02
+.\" %ENDIF OS FreeBSD
 .B #
 .nf
 .B # Three SATA disks on a HighPoint RocketRAID controller.
@@ -341,7 +313,7 @@ status fails, or if new errors appear in the self-test log.
 
 .B If a 3ware controller is used
 then the corresponding SCSI (/dev/sd?) or character device (/dev/twe?,
-/dev/twa? or /dev/twl?) must be listed, along with the \'\-d 3ware,N\'
+/dev/twa?, /dev/twl? or /dev/tws?) must be listed, along with the \'\-d 3ware,N\'
 Directive (see below).  The individual ATA disks hosted by the 3ware
 controller appear to \fBsmartd\fP as normal ATA devices.  Hence all
 the ATA directives can be used for these disks (but see note below).
@@ -362,7 +334,7 @@ Specifies the type of the device.
 The valid arguments to this directive are:
 
 .I auto
-- attempt to guess the device type from the device name or from
+\- attempt to guess the device type from the device name or from
 controller type info provided by the operating system or from
 a matching USB ID entry in the drive database.
 This is the default.
@@ -386,8 +358,7 @@ SAT defines two ATA PASS THROUGH SCSI commands, one 12 bytes long and
 the other 16 bytes long.  The default is the 16 byte variant which can be
 overridden with either \'\-d sat,12\' or \'\-d sat,16\'.
 
-[NEW EXPERIMENTAL SMARTD FEATURE] If \'-d sat,auto\' is specified,
-device type SAT (for ATA/SATA disks) is
+If \'\-d sat,auto\' is specified, device type SAT (for ATA/SATA disks) is
 only used if the SCSI INQUIRY data reports a SATL (VENDOR: "ATA     ").
 Otherwise device type SCSI (for SCSI/SAS disks) is used.
 
@@ -398,8 +369,8 @@ The default SCSI operation code is 0x24, but although it can be overridden
 with \'\-d usbcypress,0xN\', where N is the scsi operation code,
 you're running the risk of damage to the device or filesystems on it.
 
-.I usbjmicron
-- this device type is for SATA disks that are behind a JMicron USB to
+.I usbjmicron[,p][,x][,PORT]
+\- this device type is for SATA disks that are behind a JMicron USB to
 PATA/SATA bridge.  The 48-bit ATA commands (required e.g. for \'\-l xerror\',
 see below) do not work with all of these bridges and are therefore disabled by
 default.  These commands can be enabled by \'\-d usbjmicron,x\'.
@@ -413,6 +384,13 @@ CAUTION: Specifying \',x\' for a device which does not support it results
 in I/O errors and may disconnect the drive.  The same applies if the specified
 PORT does not exist or is not connected to a disk.
 
+[NEW EXPERIMENTAL SMARTD FEATURE]
+The Prolific PL2507/3507 USB bridges with older firmware support a pass-through
+command similar to JMicron and work with \'\-d usbjmicron,0\'.
+Newer Prolific firmware requires a modified command which can be selected by
+\'\-d usbjmicron,p\'.
+Note that this does not yet support the SMART status command.
+
 .I usbsunplus
 \- this device type is for SATA disks that are behind a SunplusIT USB to SATA
 bridge.
@@ -430,6 +408,8 @@ to a MegaRAID controller.  The non-negative integer N (in the range of 0 to
 This interface will also work for Dell PERC controllers.
 In log files and email messages this disk will be identified as
 megaraid_disk_XXX with XXX in the range from 000 to 127 inclusive.
+It is possible to set RAID device name as /dev/bus/N, where N is a SCSI bus 
+number.
 Please see the \fBsmartctl\fP(8) man page for further details.
 
 .\" %ENDIF OS Linux
@@ -460,16 +440,15 @@ Please see the \fBsmartctl\fP(8) man page for further details.
 
 .I areca,N/E
 \- [FreeBSD, Linux, Windows and Cygwin only] [NEW EXPERIMENTAL SMARTD FEATURE] the
-device consists of one or more SATA disks connected to an Areca SAS RAID controller.
+device consists of one or more SATA or SAS disks connected to an Areca SAS RAID controller.
 The integer N (range 1 to 128) denotes the channel (slot) and E (range
 1 to 8) denotes the enclosure.
-Important: This requires upcoming Areca SAS controller firmware version 1.51 or a
-recent beta version.
+Important: This requires Areca SAS controller firmware version 1.51 or later.
 
 .\" %ENDIF OS FreeBSD Linux Windows Cygwin
 .\" %IF OS FreeBSD Linux
 .I cciss,N
-\- [FreeBSD and Linux only] the device consists of one or more SCSI/SAS disks
+\- [FreeBSD and Linux only] the device consists of one or more SCSI/SAS or SATA disks
 connected to a cciss RAID controller.  The non-negative integer N (in the range
 from 0 to 15 inclusive) denotes which disk on the controller is monitored.
 In log files and email messages this disk will be identified as cciss_disk_XX
@@ -490,6 +469,14 @@ to the default value 1.
 Please see the \fBsmartctl\fP(8) man page for further details.
 
 .\" %ENDIF OS FreeBSD Linux
+.I ignore
+\- [NEW EXPERIMENTAL SMARTD FEATURE]
+the device specified by this configuration entry should be ignored.
+This allows to ignore specific devices which are detected by a following
+DEVICESCAN configuration line.
+It may also be used to temporary disable longer multi-line configuration entries.
+This Directive may be used in conjunction with the other \'\-d\' Directives.
+
 .I removable
 \- the device or its media is removable.  This indicates to
 \fBsmartd\fP
@@ -507,25 +494,25 @@ power consumption they are: \'OFF\', \'SLEEP\', \'STANDBY\', \'IDLE\',
 and \'ACTIVE\'.  Typically in the OFF, SLEEP, and STANDBY modes the
 disk\'s platters are not spinning. But usually, in response to SMART
 commands issued by \fBsmartd\fP, the disk platters are spun up.  So if
-this option is not used, then a disk which is in a low\-power mode may
-be spun up and put into a higher\-power mode when it is periodically
+this option is not used, then a disk which is in a low-power mode may
+be spun up and put into a higher-power mode when it is periodically
 polled by \fBsmartd\fP.
 
 Note that if the disk is in SLEEP mode when \fBsmartd\fP is started,
 then it won't respond to \fBsmartd\fP commands, and so the disk won't
 be registered as a device for \fBsmartd\fP to monitor. If a disk is in
-any other low\-power mode, then the commands issued by \fBsmartd\fP to
-register the disk will probably cause it to spin\-up.
+any other low-power mode, then the commands issued by \fBsmartd\fP to
+register the disk will probably cause it to spin-up.
 
 The \'\fB\-n\fP\' (nocheck) Directive specifies if \fBsmartd\fP\'s
 periodic checks should still be carried out when the device is in a
-low\-power mode.  It may be used to prevent a disk from being spun\-up
+low-power mode.  It may be used to prevent a disk from being spun-up
 by periodic \fBsmartd\fP polling.  The allowed values of POWERMODE
 are:
 
 .I never
 \- \fBsmartd\fP will poll (check) the device regardless of its power
-mode. This may cause a disk which is spun\-down to be spun\-up when
+mode. This may cause a disk which is spun-down to be spun-up when
 \fBsmartd\fP checks it.  This is the default behavior if the '\-n'
 Directive is not given.
 
@@ -568,12 +555,8 @@ continue if an optional SMART command fails.  This is the default.
 .I permissive
 \- try to monitor the disk even if it appears to lack SMART
 capabilities.  This may be required for some old disks (prior to
-ATA\-3 revision 4) that implemented SMART before the SMART standards
-were incorporated into the ATA/ATAPI Specifications.  This may also be
-needed for some Maxtor disks which fail to comply with the ATA
-Specifications and don't properly indicate support for error\- or
-self\-test logging.
-
+ATA-3 revision 4) that implemented SMART before the SMART standards
+were incorporated into the ATA/ATAPI Specifications.
 [Please see the \fBsmartctl \-T\fP command-line option.]
 .TP
 .B \-o VALUE
@@ -638,9 +621,9 @@ command-line option.
 options.]
 
 [ATA only] Failed self-tests outdated by a newer successful extended
-self\-test are ignored.  The warning email counter is reset if the
+self-test are ignored.  The warning email counter is reset if the
 number of failed self tests dropped to 0.  This typically happens when
-an extended self\-test is run after all bad sectors have been reallocated.
+an extended self-test is run after all bad sectors have been reallocated.
 
 .I offlinests[,ns]
 \- [ATA only] report if the Offline Data Collection status has changed
@@ -686,9 +669,9 @@ not supported.  For RAID configurations, this is typically set to
 [Please see the \fBsmartctl \-l scterc\fP command-line option.]
 
 .TP
-.B -e NAME[,VALUE]
-[NEW EXPERIMENTAL SMARTD FEATURE] Sets non\-SMART device settings
-when \fBsmartd\fP starts up and has no further effect.
+.B \-e NAME[,VALUE]
+Sets non-SMART device settings when \fBsmartd\fP starts up and has no
+further effect.
 [Please see the \fBsmartctl \-\-set\fP command-line option.]
 Valid arguments are:
 
@@ -837,7 +820,7 @@ disk is active again.
 
 Unix users: please beware that the rules for extended regular
 expressions [regex(7)] are \fBnot\fP the same as the rules for
-file\-name pattern matching by the shell [glob(7)].  \fBsmartd\fP will
+file-name pattern matching by the shell [glob(7)].  \fBsmartd\fP will
 issue harmless informational warning messages if it detects characters
 in \fBREGEXP\fP that appear to indicate that you have made this
 mistake.
@@ -903,20 +886,32 @@ sending mail, this should help you to understand and fix them.  If
 you have mail problems, we recommend running \fBsmartd\fP in debug
 mode with the \'-d\' flag, using the \'-M test\' Directive described
 below.
+.\" %IF NOT OS Windows
+
+[NEW EXPERIMENTAL SMARTD FEATURE]
+If a word of the comma separated list has the form \'@plugin\', a custom
+script /usr/local/etc/smartd_warning.d/plugin is run and the word is
+removed from the list before sending mail. The string \'plugin\' may be any
+valid name except \'ALL\'.
+If \'@ALL\' is specified, all scripts in /usr/local/etc/smartd_warning.d/*
+are run instead.
+This is handled by the script /usr/local/etc/smartd_warning.sh
+(see also \'\-M exec\' below).
+.\" %ENDIF NOT OS Windows
 .\" %IF OS Windows
 
-The following extension is available on Windows:
-By specifying \'\fBmsgbox\fP\' as a mail address, a warning
-"email" is displayed as a message box on the screen.
-Using both \'\fBmsgbox\fP\' and regular mail addresses is possible,
-if \'\fBmsgbox\fP\' is the first word in the comma separated list.
-With \'\fBsysmsgbox\fP\', a system modal (always on top) message box
-is used.
-
-If running as a service, a service notification message box
-(always shown on current visible desktop) is used.  Please note that
-service notification message boxes are no longer supported on Windows
-Vista/2008 or later.
+[Windows only] [NEW EXPERIMENTAL SMARTD FEATURE]
+If one of the following words are used as the first address in the
+comma separated list, warning messages are sent via WTSSendMessage().
+This displays message boxes on the desktops of the selected sessions.
+Address \'\fBconsole\fP\' specifies the console session only,
+\'\fBactive\fP\' specifies the console session and all active remote
+sessions, and \'\fBconnected\fP\' specifies the console session and
+all connected (active or waiting for login) remote sessions.
+This is handled by the script EXEDIR/smartd_warning.cmd which runs
+the tool EXEDIR/wtssendmsg.exe (see also \'\-M exec\' below).
+The addresses \'\fBmsgbox\fP\' and \'\fBsysmsgbox\fP\' are now
+deprecated and have the same effect as \'\fBconsole\fP\'.
 .\" %ENDIF OS Windows
 .TP
 .B \-M TYPE
@@ -968,15 +963,22 @@ in addition to the single test email!
 \fBsmartd\fP
 needs to send email.  PATH must point to an executable binary file or
 script.
+.\" %IF OS Windows
+
+[Windows only] The PATH may contain space characters.
+Then it must be included in double quotes.
+.\" %ENDIF OS Windows
 
 By setting PATH to point to a customized script, you can make
 \fBsmartd\fP perform useful tricks when a disk problem is detected
 (beeping the console, shutting down the machine, broadcasting warnings
 to all logged-in users, etc.)  But please be careful. \fBsmartd\fP
 will \fBblock\fP until the executable PATH returns, so if your
-executable hangs, then \fBsmartd\fP will also hang. Some sample
-scripts are included in
+executable hangs, then \fBsmartd\fP will also hang.
+.\" %IF NOT OS Windows
+Some sample scripts are included in
 /usr/local/share/doc/smartmontools/examplescripts/.
+.\" %ENDIF NOT OS Windows
 
 The return status of the executable is recorded by \fBsmartd\fP in
 SYSLOG. The executable is not expected to write to STDOUT or
@@ -1008,6 +1010,11 @@ or \'/dev/hptrr [hpt_1/1/1]\' under FreeBSD.  For Areca controllers, the
 form is \'/dev/sg2 [areca_disk_09]\' on Linux or  \'/dev/arcmsr0 [areca_disk_09]\' on FreeBSD.  In these cases the device string
 contains a space and is NOT quoted.  So to use $SMARTD_DEVICESTRING in a
 bash script you should probably enclose it in double quotes.
+.IP \fBSMARTD_DEVICEINFO\fP 4
+is set to device identify information.  It includes most of the info printed
+by \fBsmartctl \-i\fP but uses a brief single line format.
+This device info is also logged when \fBsmartd\fP starts up.
+The string contains space characters and is NOT quoted.
 .IP \fBSMARTD_FAILTYPE\fP 4
 gives the reason for the warning or message email.  The possible values that
 it takes and their meanings are:
@@ -1032,7 +1039,7 @@ it takes and their meanings are:
 read and are marked to be reallocated (replaced with spare sectors).
 .nf
 .fi
-\fIOfflineUncorrectableSector\fP: during off\-line testing, or self\-testing,
+\fIOfflineUncorrectableSector\fP: during off-line testing, or self-testing,
 one or more disk sectors could not be read.
 .nf
 .fi
@@ -1061,18 +1068,32 @@ given by the argument ADD, with the commas replaced by spaces
 given, then this string will contain space characters and is NOT
 quoted, so to use it in a bash script you may want to enclose it in
 double quotes.
+.\" %IF OS Windows
+.IP \fBSMARTD_ADDRCSV\fP 4
+[Windows only] is set to a comma-separated list of the addresses from
+SMARTD_ADDRESS.
+.\" %ENDIF OS Windows
 .IP \fBSMARTD_MESSAGE\fP 4
 is set to the one sentence summary warning email message string from
 \fBsmartd\fP. 
 This message string contains space characters and is NOT quoted. So to
 use $SMARTD_MESSAGE in a bash script you should probably enclose it in
 double quotes.
+.\" %IF NOT OS Windows
 .IP \fBSMARTD_FULLMESSAGE\fP 4
 is set to the contents of the entire email warning message string from
 \fBsmartd\fP. 
 This message string contains space and return characters and is NOT quoted. So to
 use $SMARTD_FULLMESSAGE in a bash script you should probably enclose it in
 double quotes.
+.\" %ENDIF NOT OS Windows
+.\" %IF OS Windows
+.IP \fBSMARTD_FULLMSGFILE\fP 4
+[Windows only] is the path to a temporary file containing the full message.
+The path may contain space characters and is NOT quoted.
+The file is created by the smartd_warning.cmd script and removed when
+the mailer or command exits.
+.\" %ENDIF OS Windows
 .IP \fBSMARTD_TFIRST\fP 4
 is a text string giving the time and date at which the first problem
 of this type was reported. This text string contains space characters
@@ -1083,6 +1104,12 @@ Sun Feb  9 14:58:19 2003 CST
 .IP \fBSMARTD_TFIRSTEPOCH\fP 4
 is an integer, which is the unix epoch (number of seconds since Jan 1,
 1970) for \fBSMARTD_TFIRST\fP.
+.IP \fBSMARTD_PREVCNT\fP 4
+is an integer specifying the number of previous messages sent.
+It is set to \'0\' for the first message.
+.IP \fBSMARTD_NEXTDAYS\fP 4
+is an integer specifying the number of days until the next message will be sent.
+It it set to empty on \'\-M once\' and set to \'1\' on \'\-M daily\'.
 .RE
 .\"  The following two lines are a workaround for a man2html bug.  Please leave them.
 .\" They define a non-existent option; useful because man2html can't correctly reset the margins.
@@ -1107,10 +1134,10 @@ that would normally be provided to \'mail\'.  Examples include:
 .fi
 
 .\" %IF OS Windows
-Note that on Windows, the syntax of the \'\fBBlat\fP\' mailer is
+[Windows only] On Windows, the syntax of the \'\fBBlat\fP\' mailer is
 used:
 .nf
-- -q -subject "$SMARTD_SUBJECT" -to "$SMARTD_ADDRESS"
+- -q -subject "%SMARTD_SUBJECT%" -to %SMARTD_ADDRCSV%
 .fi
 
 .\" %ENDIF OS Windows
@@ -1130,8 +1157,36 @@ will be copied to SYSLOG.  The remainder of the output is then
 discarded.
 
 Some EXAMPLES of scripts that can be used with the \'\-M exec\'
-Directive are given below. Some sample scripts are also included in
+Directive are given below.
+.\" %IF NOT OS Windows
+Some sample scripts are also included in
 /usr/local/share/doc/smartmontools/examplescripts/.
+.\" %ENDIF NOT OS Windows
+
+[NEW EXPERIMENTAL SMARTD FEATURE] The executable is run by the script
+.\" %IF NOT OS Windows
+/usr/local/etc/smartd_warning.sh.
+.\" %ENDIF NOT OS Windows
+.\" %IF OS ALL
+(Windows: EXEDIR/smartd_warning.cmd)
+.\" %ENDIF OS ALL
+.\" %IF OS Windows
+.\"! EXEDIR/smartd_warning.cmd.
+.\" %ENDIF OS Windows
+This script formats subject and full message based on SMARTD_MESSAGE and other
+environment variables set by \fBsmartd\fP.
+The environment variables
+.\" %IF NOT OS Windows
+SMARTD_SUBJECT and SMARTD_FULLMESSAGE
+.\" %ENDIF NOT OS Windows
+.\" %IF OS ALL
+(Windows: SMARTD_SUBJECT, SMARTD_FULLMSGFILE and SMARTD_ADDRCSV)
+.\" %ENDIF OS ALL
+.\" %IF OS Windows
+.\"! SMARTD_SUBJECT, SMARTD_FULLMSGFILE and SMARTD_ADDRCSV
+.\" %ENDIF OS Windows
+are set by the script before running the executable.
+
 .TP
 .B \-f
 [ATA only] Check for \'failure\' of any Usage Attributes.  If these
@@ -1193,7 +1248,7 @@ A common use of this Directive is to track the device Temperature
 
 If the optional flag \'!\' is appended, a change of the Normalized
 value is considered critical.  The report will be logged as LOG_CRIT
-and a warning email will be sent if \'-m\' is specified.
+and a warning email will be sent if \'\-m\' is specified.
 .TP
 .B \-R ID[!]
 [ATA only] When tracking, report whenever the \fIRaw\fP value of Attribute
@@ -1215,7 +1270,7 @@ Attributes.
 
 If the optional flag \'!\' is appended, a change of the Raw
 value is considered critical.  The report will be logged as
-LOG_CRIT and a warning email will be sent if \'-m\' is specified.
+LOG_CRIT and a warning email will be sent if \'\-m\' is specified.
 An example is \'-R 5!\' to warn when new sectors are reallocated.
 .TP
 .B \-C ID[+]
@@ -1271,7 +1326,7 @@ sectors dropped to 0.  This typically happens when all offline uncorrectable
 sectors have been reallocated or could be read again.
 
 An offline uncorrectable sector is a disk sector which was not
-readable during an off\-line scan or a self\-test.  This is important
+readable during an off-line scan or a self-test.  This is important
 to know, because if you have data stored in this disk sector, and you
 need to read it, the read will fail.  Please see the previous \'\-C\'
 option for more details.
@@ -1283,7 +1338,7 @@ Report or Warn if the temperature is greater or equal than one of
 \fBINFO\fP or \fBCRIT\fP degrees Celsius.
 If the limit \fBCRIT\fP is reached, a message with loglevel
 \fB\'LOG_CRIT\'\fP will be logged to syslog and a warning email
-will be send if '-m' is specified. If only the limit \fBINFO\fP is
+will be send if \'\-m\' is specified. If only the limit \fBINFO\fP is
 reached, a message with loglevel \fB\'LOG_INFO\'\fP will be logged.
 
 The warning email counter is reset if the temperature dropped below
@@ -1315,50 +1370,53 @@ To combine all of the above reports, use:
 .B \-W 2,40,45
 .fi
 
-For ATA devices, smartd interprets Attribute 194 as Temperature Celsius
+For ATA devices, smartd interprets Attribute 194 or 190 as Temperature Celsius
 by default. This can be changed to Attribute 9 or 220 by the drive
-database or by the \'-v\' directive, see below.
+database or by the \'\-v 9,temp\' or \'\-v 220,temp\' directive.
 .TP
 .B \-F TYPE
-[ATA only] Modifies the behavior of \fBsmartd\fP to compensate for
-some known and understood device firmware bug.  The arguments to this
-Directive are exclusive, so that only the final Directive given is
-used.  The valid values are:
+[ATA only] Modifies the behavior of \fBsmartd\fP to compensate for some
+known and understood device firmware bug.  This directive may be used
+multiple times.  The valid arguments are:
 
 .I none
 \- Assume that the device firmware obeys the ATA specifications.  This
 is the default, unless the device has presets for \'\-F\' in the
-device database.
+drive database.  Using this directive will over-ride any preset values.
+
+.I nologdir
+\- Suppresses read attempts of SMART or GP Log Directory.
+Support for all standard logs is assumed without an actual check.
+Some Intel SSDs may freeze if log address 0 is read.
 
 .I samsung
 \- In some Samsung disks (example: model SV4012H Firmware Version:
-RM100\-08) some of the two\- and four\-byte quantities in the SMART data
-structures are byte\-swapped (relative to the ATA specification).
+RM100-08) some of the two- and four-byte quantities in the SMART data
+structures are byte-swapped (relative to the ATA specification).
 Enabling this option tells \fBsmartd\fP to evaluate these quantities
-in byte\-reversed order.  Some signs that your disk needs this option
-are (1) no self\-test log printed, even though you have run self\-tests;
+in byte-reversed order.  Some signs that your disk needs this option
+are (1) no self-test log printed, even though you have run self-tests;
 (2) very large numbers of ATA errors reported in the ATA error log;
 (3) strange and impossible values for the ATA error log timestamps.
 
 .I samsung2
 \- In some Samsung disks the number of ATA errors reported is byte swapped.
 Enabling this option tells \fBsmartd\fP to evaluate this quantity in
-byte\-reversed order.
+byte-reversed order.
 
 .I samsung3
-\- Some Samsung disks (at least SP2514N with Firmware VF100\-37) report
-a self\-test still in progress with 0% remaining when the test was already
+\- Some Samsung disks (at least SP2514N with Firmware VF100-37) report
+a self-test still in progress with 0% remaining when the test was already
 completed. If this directive is specified, \fBsmartd\fP will not skip the
-next scheduled self\-test (see Directive \'\-s\' above) in this case.
-
-Note that an explicit \'\-F\' Directive will over\-ride any preset
-values for \'\-F\' (see the \'\-P\' option below).
+next scheduled self-test (see Directive \'\-s\' above) in this case.
 
+.I xerrorlba
+\- This only affects \fBsmartctl\fP.
 
 [Please see the \fBsmartctl \-F\fP command-line option.]
 .TP
 .B \-v ID,FORMAT[:BYTEORDER][,NAME]
-[ATA only] Sets a vendor\-specific raw value print FORMAT, an optional
+[ATA only] Sets a vendor-specific raw value print FORMAT, an optional
 BYTEORDER and an optional NAME for Attribute ID.
 This directive may be used multiple times.
 Please see \fBsmartctl -v\fP command-line option for further details.
@@ -1444,10 +1502,7 @@ If you want more frequent information, use:
 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.
-
-Configuration entries for devices not found by the platform\-specific
-device scanning may precede the \fBDEVICESCAN\fP entry.
+for devices (see also \fBsmartd\fP(8) man page).
 
 If \fBDEVICESCAN\fP is not followed by any Directives, then smartd
 will scan for both ATA and SCSI devices, and will monitor all possible
@@ -1472,6 +1527,20 @@ will do the same, but only monitors the SMART health status of the
 devices, (rather than the default \-a, which monitors all SMART
 properties).
 
+[NEW EXPERIMENTAL SMARTD FEATURE]
+Configuration entries for specific devices may precede the \fBDEVICESCAN\fP entry.
+For example
+.nf
+.B  DEFAULT -m root@example.com
+.B  /dev/sda -s S/../.././02
+.B  /dev/sdc -d ignore
+.B  DEVICESCAN -s L/../.././02
+.fi
+will scan for all devices except /dev/sda and /dev/sdc, monitor them, and run a long
+test between 2-3am every morning.  Device /dev/sda will also be monitored, but
+only a short test will be run.  Device /dev/sdc will be ignored.
+Warning emails will be sent for all monitored devices.
+
 .TP
 .B EXAMPLES OF SHELL SCRIPTS FOR \'\-M exec\'
 These are two examples of shell scripts that can be used with the \'\-M
@@ -1534,17 +1603,21 @@ within the script, and a snippet of STDOUT/STDERR is logged to SYSLOG.
 The remainder is flushed.
 
 .PP
-.SH AUTHOR
-\fBBruce Allen\fP smartmontools\-support@lists.sourceforge.net
-.fi
+.SH AUTHORS
+\fBBruce Allen\fP
+.br
 University of Wisconsin \- Milwaukee Physics Department
+.br
+\fBChristian Franke\fP (Windows interface, C++ redesign, most enhancements
+since 2009)
+.br
+\fBsmartmontools\-support@lists.sourceforge.net\fP
 
 .PP
 .SH CONTRIBUTORS
 The following have made large contributions to smartmontools:
 .nf
 \fBCasper Dik\fP (Solaris SCSI interface)
-\fBChristian Franke\fP (Windows interface, C++ redesign, USB support, ...)
 \fBDouglas Gilbert\fP (SCSI subsystem)
 \fBGuido Guenther\fP (Autoconf/Automake packaging)
 \fBGeoffrey Keating\fP (Darwin ATA interface)
@@ -1565,7 +1638,7 @@ Many other individuals have made smaller contributions and corrections.
 .fi
 This code was derived from the smartsuite package, written by Michael
 Cornwell, and from the previous UCSC smartsuite package.  It extends
-these to cover ATA\-5 disks.  This code was originally developed as a
+these to cover ATA-5 disks.  This code was originally developed as a
 Senior Thesis by Michael Cornwell at the Concurrent Systems Laboratory
 (now part of the Storage Systems Research Center), Jack Baskin School
 of Engineering, University of California, Santa
@@ -1583,4 +1656,4 @@ SEE ALSO:
 
 .SH
 SVN ID OF THIS PAGE:
-$Id: smartd.conf.5.in 3561 2012-06-05 19:49:31Z chrfranke $
+$Id: smartd.conf.5.in 3741 2013-01-02 17:06:54Z chrfranke $
index 0e124ecc3ad6ae91cea1454201094adccbbeee69..fec123552e8cbcbf0676f90a348bfba878068156 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
  * Copyright (C) 2000    Michael Cornwell <cornwell@acm.org>
  * Copyright (C) 2008    Oliver Bock <brevilo@users.sourceforge.net>
- * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-13 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
  *
  */
 
-#ifndef _GNU_SOURCE
-// TODO: Why is this define necessary?
-#define _GNU_SOURCE
-#endif
+#include "config.h"
+#include "int64.h"
 
 // unconditionally included files
 #include <stdio.h>
@@ -46,9 +44,6 @@
 #include <vector>
 #include <algorithm> // std::replace()
 
-// see which system files to conditionally include
-#include "config.h"
-
 // conditionally included files
 #ifndef _WIN32
 #include <sys/wait.h>
@@ -79,7 +74,6 @@ typedef int pid_t;
 #endif // LIBCAP_NG
 
 // locally included files
-#include "int64.h"
 #include "atacmds.h"
 #include "dev_interface.h"
 #include "knowndrives.h"
@@ -95,9 +89,6 @@ typedef int pid_t;
 #endif
 
 #ifdef _WIN32
-#include "hostname_win32.h" // gethost/domainname()
-#define HAVE_GETHOSTNAME   1
-#define HAVE_GETDOMAINNAME 1
 // fork()/signal()/initd simulation for native Windows
 #include "daemon_win32.h" // daemon_main/detach/signal()
 #undef SIGNALFN
@@ -115,9 +106,7 @@ typedef int pid_t;
 extern "C" int getdomainname(char *, int); // no declaration in header files!
 #endif
 
-#define ARGUSED(x) ((void)(x))
-
-const char * smartd_cpp_cvsid = "$Id: smartd.cpp 3513 2012-02-15 21:57:21Z chrfranke $"
+const char * smartd_cpp_cvsid = "$Id: smartd.cpp 3802 2013-03-24 18:36:21Z chrfranke $"
   CONFIG_H_CVSID;
 
 // smartd exit codes
@@ -168,6 +157,9 @@ static const char * const configfile_stdin = "<stdin>";
 // path of alternate configuration file
 static std::string configfile_alt;
 
+// warning script file
+static std::string warning_script;
+
 // command-line: when should we exit?
 static int quit=0;
 
@@ -184,10 +176,8 @@ static bool do_fork=true;
 static bool enable_capabilities = false;
 #endif
 
-#if defined(_WIN32) || defined(__CYGWIN__)
 // TODO: This smartctl only variable is also used in os_win32.cpp
 unsigned char failuretest_permissive = 0;
-#endif
 
 // set to one if we catch a USR1 (check devices now)
 static volatile int caughtsigUSR1=0;
@@ -248,8 +238,10 @@ struct dev_config
   std::string name;                       // Device name (with optional extra info)
   std::string dev_name;                   // Device name (plain, for SMARTD_DEVICE variable)
   std::string dev_type;                   // Device type argument from -d directive, empty if none
+  std::string dev_idinfo;                 // Device identify info for warning emails
   std::string state_file;                 // Path of the persistent state file, empty if none
   std::string attrlog_file;               // Path of the persistent attrlog file, empty if none
+  bool ignore;                            // Ignore this entry
   bool smartcheck;                        // Check SMART status
   bool usagefailed;                       // Check for failed Usage Attributes
   bool prefail;                           // Track changes in Prefail Attributes
@@ -264,7 +256,7 @@ struct dev_config
   bool permissive;                        // Ignore failed SMART commands
   char autosave;                          // 1=disable, 2=enable Autosave Attributes
   char autoofflinetest;                   // 1=disable, 2=enable Auto Offline Test
-  unsigned char fix_firmwarebug;          // FIX_*, see atacmds.h
+  firmwarebug_defs firmwarebugs;          // -F directives from drivedb or smartd.conf
   bool ignorepresets;                     // Ignore database of -v options
   bool showpresets;                       // Show database entry for this device
   bool removable;                         // Device may disappear (not be present)
@@ -282,6 +274,7 @@ struct dev_config
   bool emailtest;                         // Send test email?
 
   // ATA ONLY
+  int dev_rpm; // rotation rate, 0 = unknown, 1 = SSD, >1 = HDD
   int set_aam; // disable(-1), enable(1..255->0..254) Automatic Acoustic Management
   int set_apm; // disable(-1), enable(2..255->1..254) Advanced Power Management
   int set_lookahead; // disable(-1), enable(1) read look-ahead
@@ -307,6 +300,7 @@ struct dev_config
 
 dev_config::dev_config()
 : lineno(0),
+  ignore(false),
   smartcheck(false),
   usagefailed(false),
   prefail(false),
@@ -319,7 +313,6 @@ dev_config::dev_config()
   permissive(false),
   autosave(0),
   autoofflinetest(0),
-  fix_firmwarebug(FIX_NOTSPECIFIED),
   ignorepresets(false),
   showpresets(false),
   removable(false),
@@ -330,6 +323,7 @@ dev_config::dev_config()
   tempinfo(0), tempcrit(0),
   emailfreq(0),
   emailtest(false),
+  dev_rpm(0),
   set_aam(0), set_apm(0),
   set_lookahead(0),
   set_standby(0),
@@ -388,6 +382,22 @@ struct persistent_dev_state
     ata_attribute() : id(0), val(0), worst(0), raw(0), resvd(0) { }
   };
   ata_attribute ata_attributes[NUMBER_ATA_SMART_ATTRIBUTES];
+  
+  // SCSI ONLY
+
+  struct scsi_error_counter {
+    struct scsiErrorCounter errCounter;
+    unsigned char found;
+    scsi_error_counter() : found(0) { }
+  };
+  scsi_error_counter scsi_error_counters[3];
+
+  struct scsi_nonmedium_error {
+    struct scsiNonMediumError nme;
+    unsigned char found;
+    scsi_nonmedium_error() : found(0) { }
+  };
+  scsi_nonmedium_error scsi_nonmedium_error;
 
   persistent_dev_state();
 };
@@ -423,10 +433,13 @@ struct temp_dev_state
   // SCSI ONLY
   unsigned char SmartPageSupported;       // has log sense IE page (0x2f)
   unsigned char TempPageSupported;        // has log sense temperature page (0xd)
+  unsigned char ReadECounterPageSupported;
+  unsigned char WriteECounterPageSupported;
+  unsigned char VerifyECounterPageSupported;
+  unsigned char NonMediumErrorPageSupported;
   unsigned char SuppressReport;           // minimize nuisance reports
   unsigned char modese_len;               // mode sense/select cmd len: 0 (don't
                                           // know yet) 6 or 10
-
   // ATA ONLY
   uint64_t num_sectors;                   // Number of sectors
   ata_smart_values smartval;              // SMART data
@@ -450,6 +463,10 @@ temp_dev_state::temp_dev_state()
   powerskipcnt(0),
   SmartPageSupported(false),
   TempPageSupported(false),
+  ReadECounterPageSupported(false),
+  WriteECounterPageSupported(false),
+  VerifyECounterPageSupported(false),
+  NonMediumErrorPageSupported(false),
   SuppressReport(false),
   modese_len(0),
   num_sectors(0),
@@ -721,7 +738,7 @@ static bool write_dev_state(const char * path, const persistent_dev_state & stat
 }
 
 // Write to the attrlog file
-static bool write_dev_attrlog(const char * path, const persistent_dev_state & state)
+static bool write_dev_attrlog(const char * path, const dev_state & state)
 {
   stdio_file f(path, "a");
   if (!f) {
@@ -729,20 +746,48 @@ static bool write_dev_attrlog(const char * path, const persistent_dev_state & st
     return false;
   }
 
-  // ATA ONLY
+  
   time_t now = time(0);
   struct tm * tms = gmtime(&now);
   fprintf(f, "%d-%02d-%02d %02d:%02d:%02d;",
              1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
              tms->tm_hour, tms->tm_min, tms->tm_sec);
+  // ATA ONLY
   for (int i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) {
     const persistent_dev_state::ata_attribute & pa = state.ata_attributes[i];
     if (!pa.id)
       continue;
     fprintf(f, "\t%d;%d;%"PRIu64";", pa.id, pa.val, pa.raw);
   }
+  // SCSI ONLY
+  const struct scsiErrorCounter * ecp;
+  const char * pageNames[3] = {"read", "write", "verify"};
+  for (int k = 0; k < 3; ++k) {
+    if ( !state.scsi_error_counters[k].found ) continue;
+    ecp = &state.scsi_error_counters[k].errCounter;
+     fprintf(f, "\t%s-corr-by-ecc-fast;%"PRIu64";"
+       "\t%s-corr-by-ecc-delayed;%"PRIu64";"
+       "\t%s-corr-by-retry;%"PRIu64";"
+       "\t%s-total-err-corrected;%"PRIu64";"
+       "\t%s-corr-algorithm-invocations;%"PRIu64";"
+       "\t%s-gb-processed;%.3f;"
+       "\t%s-total-unc-errors;%"PRIu64";",
+       pageNames[k], ecp->counter[0],
+       pageNames[k], ecp->counter[1],
+       pageNames[k], ecp->counter[2],
+       pageNames[k], ecp->counter[3],
+       pageNames[k], ecp->counter[4],
+       pageNames[k], (ecp->counter[5] / 1000000000.0),
+       pageNames[k], ecp->counter[6]);
+  }
+  if(state.scsi_nonmedium_error.found && state.scsi_nonmedium_error.nme.gotPC0) {
+    fprintf(f, "\tnon-medium-errors;%"PRIu64";", state.scsi_nonmedium_error.nme.counterPC0);
+  }
+  // write SCSI current temperature if it is monitored
+  if(state.TempPageSupported && state.temperature)
+     fprintf(f, "\ttemperature;%d;", state.temperature);
+  // end of line
   fprintf(f, "\n");
-
   return true;
 }
 
@@ -849,56 +894,43 @@ static int Goodbye(int status)
   return status;
 }
 
-#define ENVLENGTH 1024
-
 // a replacement for setenv() which is not available on all platforms.
 // Note that the string passed to putenv must not be freed or made
 // invalid, since a pointer to it is kept by putenv(). This means that
 // it must either be a static buffer or allocated off the heap. The
-// string can be freed if the environment variable is redefined or
-// deleted via another call to putenv(). So we keep these on the stack
-// as long as the popen() call is underway.
-static int exportenv(char *stackspace, const char *name, const char *value)
+// string can be freed if the environment variable is redefined via
+// another call to putenv(). There is no portable way to unset a variable
+// with putenv(). So we manage the buffer in a static object.
+// Using setenv() if available is not considered because some
+// implementations may produce memory leaks.
+
+class env_buffer
 {
-  snprintf(stackspace,ENVLENGTH, "%s=%s", name, value);
-  return putenv(stackspace);
-}
+public:
+  env_buffer()
+    : m_buf((char *)0) { }
+
+  void set(const char * name, const char * value);
+
+private:
+  char * m_buf;
+
+  env_buffer(const env_buffer &);
+  void operator=(const env_buffer &);
+};
 
-static char *dnsdomain(const char *hostname)
+void env_buffer::set(const char * name, const char * value)
 {
-  char *p = NULL;
-#ifdef HAVE_GETADDRINFO
-  static char canon_name[NI_MAXHOST];
-  struct addrinfo *info = NULL;
-  struct addrinfo hints;
-  int err;
-
-  memset(&hints, 0, sizeof(hints));
-  hints.ai_flags = AI_CANONNAME;
-  if ((err = getaddrinfo(hostname, NULL, &hints, &info)) || (!info)) {
-    PrintOut(LOG_CRIT, "Error retrieving getaddrinfo(%s): %s\n", hostname, gai_strerror(err));
-    return NULL;
-  }
-  if (info->ai_canonname) {
-    strncpy(canon_name, info->ai_canonname, sizeof(canon_name));
-    canon_name[NI_MAXHOST - 1] = '\0';
-    p = canon_name;
-    if ((p = strchr(canon_name, '.')))
-      p++;
-  }
-  freeaddrinfo(info);
-#elif HAVE_GETHOSTBYNAME
-  struct hostent *hp;
-  if ((hp = gethostbyname(hostname))) {
-    // Does this work if gethostbyname() returns an IPv6 name in
-    // colon/dot notation?  [BA]
-    if ((p = strchr(hp->h_name, '.')))
-      p++; // skip "."
-  }
-#else
-  ARGUSED(hostname);
-#endif
-  return p;
+  int size = strlen(name) + 1 + strlen(value) + 1;
+  char * newbuf = new char[size];
+  snprintf(newbuf, size, "%s=%s", name, value);
+
+  if (putenv(newbuf))
+    throw std::runtime_error("putenv() failed");
+
+  // This assumes that the same NAME is passed on each call
+  delete [] m_buf;
+  m_buf = newbuf;
 }
 
 #define EBUFLEN 1024
@@ -908,15 +940,9 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
 
 // If either address or executable path is non-null then send and log
 // a warning email, or execute executable
-static void MailWarning(const dev_config & cfg, dev_state & state, int which, const char *fmt, ...){
-  char command[2048], message[256], hostname[256], domainname[256], additional[256],fullmessage[1024];
-  char original[256], further[256], nisdomain[256], subject[256],dates[DATEANDEPOCHLEN];
-  char environ_strings[11][ENVLENGTH];
-  time_t epoch;
-  va_list ap;
-  const int day=24*3600;
-  int days=0;
-  const char * const whichfail[]={
+static void MailWarning(const dev_config & cfg, dev_state & state, int which, const char *fmt, ...)
+{
+  static const char * const whichfail[] = {
     "EmailTest",                  // 0
     "Health",                     // 1
     "Usage",                      // 2
@@ -932,8 +958,6 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
     "Temperature"                 // 12
   };
   
-  const char *unknown="[Unknown]";
-
   // See if user wants us to send mail
   if (cfg.emailaddress.empty() && cfg.emailcmdline.empty())
     return;
@@ -964,15 +988,16 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
     return;
   
   // To decide if to send mail, we need to know what time it is.
-  epoch=time(NULL);
+  time_t epoch = time(0);
 
   // Return if less than one day has gone by
+  const int day = 24*3600;
   if (cfg.emailfreq==2 && mail->logged && epoch<(mail->lastsent+day))
     return;
 
   // Return if less than 2^(logged-1) days have gone by
   if (cfg.emailfreq==3 && mail->logged) {
-    days=0x01<<(mail->logged-1);
+    int days = 0x01 << (mail->logged - 1);
     days*=day;
     if  (epoch<(mail->lastsent+days))
       return;
@@ -990,125 +1015,57 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
   if (!mail->logged)
     mail->firstsent=epoch;
   mail->lastsent=epoch;
-  
-  // get system host & domain names (not null terminated if length=MAX) 
-#ifdef HAVE_GETHOSTNAME
-  if (gethostname(hostname, 256))
-    strcpy(hostname, unknown);
-  else {
-    char *p=NULL;
-    hostname[255]='\0';
-    p = dnsdomain(hostname);
-    if (p && *p) {
-      strncpy(domainname, p, 255);
-      domainname[255]='\0';
-    } else
-      strcpy(domainname, unknown);
-  }
-#else
-  strcpy(hostname, unknown);
-  strcpy(domainname, unknown);
-#endif
-  
-#ifdef HAVE_GETDOMAINNAME
-  if (getdomainname(nisdomain, 256))
-    strcpy(nisdomain, unknown);
-  else
-    nisdomain[255]='\0';
-#else
-  strcpy(nisdomain, unknown);
-#endif
-  
+
   // print warning string into message
+  char message[256];
+  va_list ap;
   va_start(ap, fmt);
-  vsnprintf(message, 256, fmt, ap);
+  vsnprintf(message, sizeof(message), fmt, ap);
   va_end(ap);
 
-  // appropriate message about further information
-  additional[0]=original[0]=further[0]='\0';
-  if (which) {
-    sprintf(further,"You can also use the smartctl utility for further investigation.\n");
-
-    switch (cfg.emailfreq) {
-    case 1:
-      sprintf(additional,"No additional email messages about this problem will be sent.\n");
-      break;
-    case 2:
-      sprintf(additional,"Another email message will be sent in 24 hours if the problem persists.\n");
-      break;
-    case 3:
-      sprintf(additional,"Another email message will be sent in %d days if the problem persists\n",
-              (0x01)<<mail->logged);
-      break;
-    }
-    if (cfg.emailfreq>1 && mail->logged) {
-      dateandtimezoneepoch(dates, mail->firstsent);
-      sprintf(original,"The original email about this issue was sent at %s\n", dates);
-    }
-  }
-  
-  snprintf(subject, 256,"SMART error (%s) detected on host: %s", whichfail[which], hostname);
-
-  // If the user has set cfg.emailcmdline, use that as mailer, else "mail" or "mailx".
-  if (!*executable)
-#ifdef DEFAULT_MAILER
-    executable = DEFAULT_MAILER ;
-#else
-#ifndef _WIN32
-    executable = "mail";
-#else
-    executable = "blat"; // http://blat.sourceforge.net/
-#endif
-#endif
-
-#ifndef _WIN32 // blat mailer needs comma
   // replace commas by spaces to separate recipients
   std::replace(address.begin(), address.end(), ',', ' ');
-#endif
+
   // Export information in environment variables that will be useful
   // for user scripts
-  exportenv(environ_strings[0], "SMARTD_MAILER", executable);
-  exportenv(environ_strings[1], "SMARTD_MESSAGE", message);
-  exportenv(environ_strings[2], "SMARTD_SUBJECT", subject);
+  static env_buffer env[12];
+  env[0].set("SMARTD_MAILER", executable);
+  env[1].set("SMARTD_MESSAGE", message);
+  char dates[DATEANDEPOCHLEN];
+  snprintf(dates, sizeof(dates), "%d", mail->logged);
+  env[2].set("SMARTD_PREVCNT", dates);
   dateandtimezoneepoch(dates, mail->firstsent);
-  exportenv(environ_strings[3], "SMARTD_TFIRST", dates);
+  env[3].set("SMARTD_TFIRST", dates);
   snprintf(dates, DATEANDEPOCHLEN,"%d", (int)mail->firstsent);
-  exportenv(environ_strings[4], "SMARTD_TFIRSTEPOCH", dates);
-  exportenv(environ_strings[5], "SMARTD_FAILTYPE", whichfail[which]);
-  if (!address.empty())
-    exportenv(environ_strings[6], "SMARTD_ADDRESS", address.c_str());
-  exportenv(environ_strings[7], "SMARTD_DEVICESTRING", cfg.name.c_str());
+  env[4].set("SMARTD_TFIRSTEPOCH", dates);
+  env[5].set("SMARTD_FAILTYPE", whichfail[which]);
+  env[6].set("SMARTD_ADDRESS", address.c_str());
+  env[7].set("SMARTD_DEVICESTRING", cfg.name.c_str());
 
   // Allow 'smartctl ... -d $SMARTD_DEVICETYPE $SMARTD_DEVICE'
-  exportenv(environ_strings[8], "SMARTD_DEVICETYPE",
-            (!cfg.dev_type.empty() ? cfg.dev_type.c_str() : "auto"));
-  exportenv(environ_strings[9], "SMARTD_DEVICE", cfg.dev_name.c_str());
-
-  snprintf(fullmessage, 1024,
-             "This email was generated by the smartd daemon running on:\n\n"
-             "   host name: %s\n"
-             "  DNS domain: %s\n"
-             "  NIS domain: %s\n\n"
-             "The following warning/error was logged by the smartd daemon:\n\n"
-             "%s\n\n"
-             "For details see host's SYSLOG.\n\n"
-             "%s%s%s",
-            hostname, domainname, nisdomain, message, further, original, additional);
-  exportenv(environ_strings[10], "SMARTD_FULLMESSAGE", fullmessage);
+  env[8].set("SMARTD_DEVICETYPE",
+             (!cfg.dev_type.empty() ? cfg.dev_type.c_str() : "auto"));
+  env[9].set("SMARTD_DEVICE", cfg.dev_name.c_str());
+
+  env[10].set("SMARTD_DEVICEINFO", cfg.dev_idinfo.c_str());
+  dates[0] = 0;
+  if (which) switch (cfg.emailfreq) {
+    case 2: dates[0] = '1'; dates[1] = 0; break;
+    case 3: snprintf(dates, sizeof(dates), "%d", (0x01)<<mail->logged);
+  }
+  env[11].set("SMARTD_NEXTDAYS", dates);
 
   // now construct a command to send this as EMAIL
-#ifndef _WIN32
-  if (!address.empty())
-    snprintf(command, 2048, 
-             "$SMARTD_MAILER -s '%s' %s 2>&1 << \"ENDMAIL\"\n"
-            "%sENDMAIL\n", subject, address.c_str(), fullmessage);
-  else
-    snprintf(command, 2048, "%s 2>&1", executable);
-  
-  // tell SYSLOG what we are about to do...
+  char command[2048];
+  if (!*executable)
+    executable = "<mail>";
   const char * newadd = (!address.empty()? address.c_str() : "<nomailer>");
   const char * newwarn = (which? "Warning via" : "Test of");
 
+#ifndef _WIN32
+  snprintf(command, sizeof(command), "%s 2>&1", warning_script.c_str());
+  
+  // tell SYSLOG what we are about to do...
   PrintOut(LOG_INFO,"%s %s to %s ...\n",
            which?"Sending warning via":"Executing test of", executable, newadd);
   
@@ -1182,65 +1139,15 @@ static void MailWarning(const dev_config & cfg, dev_state & state, int which, co
   }
   
 #else // _WIN32
+  {
+    snprintf(command, sizeof(command), "cmd /c \"%s\"", warning_script.c_str());
 
-  // No "here-documents" on Windows, so must use separate commandline and stdin
-  char stdinbuf[1024];
-  command[0] = stdinbuf[0] = 0;
-  int boxtype = -1, boxmsgoffs = 0;
-  const char * newadd = "<nomailer>";
-  if (!address.empty()) {
-    // address "[sys]msgbox ..." => show warning (also) as [system modal ]messagebox
-    char addr1[9+1+13] = ""; int n1 = -1, n2 = -1;
-    if (sscanf(address.c_str(), "%9[a-z]%n,%n", addr1, &n1, &n2) == 1 && (n1 == (int)address.size() || n2 > 0)) {
-      if (!strcmp(addr1, "msgbox"))
-        boxtype = 0;
-      else if (!strcmp(addr1, "sysmsgbox"))
-        boxtype = 1;
-      if (boxtype >= 0)
-        address.erase(0, (n2 > n1 ? n2 : n1));
-    }
-
-    if (!address.empty()) {
-      // Use "blat" parameter syntax (TODO: configure via -M for other mailers)
-      snprintf(command, sizeof(command),
-               "%s - -q -subject \"%s\" -to \"%s\"",
-               executable, subject, address.c_str());
-      newadd = address.c_str();
-    }
-
-    // Message for mail [0...] and messagebox [boxmsgoffs...]
-    snprintf(stdinbuf, sizeof(stdinbuf),
-             "This email was generated by the smartd daemon running on:\n\n"
-             "   host name: %s\n"
-             "  DNS domain: %s\n"
-//           "  NIS domain: %s\n"
-             "\n",
-             hostname, /*domainname, */ nisdomain);
-    boxmsgoffs = strlen(stdinbuf);
-    snprintf(stdinbuf+boxmsgoffs, sizeof(stdinbuf)-boxmsgoffs,
-             "The following warning/error was logged by the smartd daemon:\n\n"
-             "%s\n\n"
-             "For details see the event log or log file of smartd.\n\n"
-             "%s%s%s"
-             "\n",
-             message, further, original, additional);
-  }
-  else
-    snprintf(command, sizeof(command), "%s", executable);
-
-  const char * newwarn = (which ? "Warning via" : "Test of");
-  if (boxtype >= 0) {
-    // show message box
-    daemon_messagebox(boxtype, subject, stdinbuf+boxmsgoffs);
-    PrintOut(LOG_INFO,"%s message box\n", newwarn);
-  }
-  if (command[0]) {
     char stdoutbuf[800]; // < buffer in syslog_win32::vsyslog()
     int rc;
     // run command
     PrintOut(LOG_INFO,"%s %s to %s ...\n",
              (which?"Sending warning via":"Executing test of"), executable, newadd);
-    rc = daemon_spawn(command, stdinbuf, strlen(stdinbuf), stdoutbuf, sizeof(stdoutbuf));
+    rc = daemon_spawn(command, "", 0, stdoutbuf, sizeof(stdoutbuf));
     if (rc >= 0 && stdoutbuf[0])
       PrintOut(LOG_CRIT,"%s %s to %s produced unexpected output (%d bytes) to STDOUT/STDERR:\n%s\n",
         newwarn, executable, newadd, (int)strlen(stdoutbuf), stdoutbuf);
@@ -1321,13 +1228,15 @@ void pout(const char *fmt, ...){
   // initialize variable argument list 
   va_start(ap,fmt);
   // in debugmode==1 mode we will print the output from the ataprint.o functions!
-  if (debugmode && debugmode!=2)
+  if (debugmode && debugmode != 2) {
+    FILE * f = stdout;
 #ifdef _WIN32
-   if (facility == LOG_LOCAL1) // logging to stdout
-    vfprintf(stderr,fmt,ap);
-   else   
+    if (facility == LOG_LOCAL1) // logging to stdout
+      f = stderr;
 #endif
-    vprintf(fmt,ap);
+    vfprintf(f, fmt, ap);
+    fflush(f);
+  }
   // in debugmode==2 mode we print output from knowndrives.o functions
   else if (debugmode==2 || ata_debugmode || scsi_debugmode) {
     openlog("smartd", LOG_PID, facility);
@@ -1335,7 +1244,6 @@ void pout(const char *fmt, ...){
     closelog();
   }
   va_end(ap);
-  fflush(NULL);
   return;
 }
 
@@ -1347,13 +1255,15 @@ static void PrintOut(int priority, const char *fmt, ...){
   FixGlibcTimeZoneBug();
   // initialize variable argument list 
   va_start(ap,fmt);
-  if (debugmode) 
+  if (debugmode) {
+    FILE * f = stdout;
 #ifdef _WIN32
-   if (facility == LOG_LOCAL1) // logging to stdout
-    vfprintf(stderr,fmt,ap);
-   else   
+    if (facility == LOG_LOCAL1) // logging to stdout
+      f = stderr;
 #endif
-    vprintf(fmt,ap);
+    vfprintf(f, fmt, ap);
+    fflush(f);
+  }
   else {
     openlog("smartd", LOG_PID, facility);
     vsyslog_lines(priority, fmt, ap);
@@ -1506,7 +1416,8 @@ static void Directives()
 {
   PrintOut(LOG_INFO,
            "Configuration file (%s) Directives (after device name):\n"
-           "  -d TYPE Set the device type: %s, auto, removable\n"
+           "  -d TYPE Set the device type: auto, ignore, removable,\n"
+           "          %s\n"
            "  -T TYPE Set the tolerance to one of: normal, permissive\n"
            "  -o VAL  Enable/disable automatic offline tests (on/off)\n"
            "  -S VAL  Enable/disable attribute autosave (on/off)\n"
@@ -1534,14 +1445,16 @@ static void Directives()
            "  -v N,ST Modifies labeling of Attribute N (see man page)  \n"
            "  -P TYPE Drive-specific presets: use, ignore, show, showall\n"
            "  -a      Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
-           "  -F TYPE Firmware bug workaround: none, samsung, samsung2, samsung3\n"
+           "  -F TYPE Use firmware bug workaround:\n"
+           "          %s\n"
            "   #      Comment: text after a hash sign is ignored\n"
            "   \\      Line continuation character\n"
            "Attribute ID is a decimal integer 1 <= ID <= 255\n"
-          "Use ID = 0 to turn off -C and/or -U Directives\n"
-           "Example: /dev/hda -a\n", 
-           configfile, smi()->get_valid_dev_types_str().c_str());
-  return;
+           "Use ID = 0 to turn off -C and/or -U Directives\n"
+           "Example: /dev/sda -a\n",
+           configfile,
+           smi()->get_valid_dev_types_str().c_str(),
+           get_valid_firmwarebug_args());
 }
 
 /* Returns a pointer to a static string containing a formatted list of the valid
@@ -1562,6 +1475,7 @@ static const char *GetValidArgList(char opt)
     return "ioctl[,N], ataioctl[,N], scsiioctl[,N]";
   case 'B':
   case 'p':
+  case 'w':
     return "<FILE_NAME>";
   case 'i':
     return "<INTEGER_SECONDS>";
@@ -1626,6 +1540,13 @@ static void Usage()
   PrintOut(LOG_INFO,"        [default is "SMARTMONTOOLS_SAVESTATES"MODEL-SERIAL.TYPE.state]\n");
 #endif
   PrintOut(LOG_INFO,"\n");
+  PrintOut(LOG_INFO,"  -w NAME, --warnexec=NAME\n");
+  PrintOut(LOG_INFO,"        Run executable NAME on warnings\n");
+#ifndef _WIN32
+  PrintOut(LOG_INFO,"        [default is "SMARTMONTOOLS_SYSCONFDIR"/smartd_warning.sh]\n\n");
+#else
+  PrintOut(LOG_INFO,"        [default is %s/smartd_warning.cmd]\n\n", get_exe_dir().c_str());
+#endif
 #ifdef _WIN32
   PrintOut(LOG_INFO,"  --service\n");
   PrintOut(LOG_INFO,"        Running as windows service (see man page), install with:\n");
@@ -1658,11 +1579,11 @@ static bool not_allowed_in_filename(char c)
 // Read error count from Summary or Extended Comprehensive SMART error log
 // Return -1 on error
 static int read_ata_error_count(ata_device * device, const char * name,
-                                unsigned char fix_firmwarebug, bool extended)
+                                firmwarebug_defs firmwarebugs, bool extended)
 {
   if (!extended) {
     ata_smart_errorlog log;
-    if (ataReadErrorLog(device, &log, fix_firmwarebug)){
+    if (ataReadErrorLog(device, &log, firmwarebugs)){
       PrintOut(LOG_INFO,"Device: %s, Read Summary SMART Error Log failed\n",name);
       return -1;
     }
@@ -1670,7 +1591,7 @@ static int read_ata_error_count(ata_device * device, const char * name,
   }
   else {
     ata_smart_exterrlog logx;
-    if (!ataReadExtErrorLog(device, &logx, 1 /*first sector only*/)) {
+    if (!ataReadExtErrorLog(device, &logx, 1 /*first sector only*/, firmwarebugs)) {
       PrintOut(LOG_INFO,"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
       return -1;
     }
@@ -1682,17 +1603,17 @@ static int read_ata_error_count(ata_device * device, const char * name,
 // returns <0 if problem.  Otherwise, bottom 8 bits are the self test
 // error count, and top bits are the power-on hours of the last error.
 static int SelfTestErrorCount(ata_device * device, const char * name,
-                              unsigned char fix_firmwarebug)
+                              firmwarebug_defs firmwarebugs)
 {
   struct ata_smart_selftestlog log;
 
-  if (ataReadSelfTestLog(device, &log, fix_firmwarebug)){
+  if (ataReadSelfTestLog(device, &log, firmwarebugs)){
     PrintOut(LOG_INFO,"Device: %s, Read SMART Self Test Log Failed\n",name);
     return -1;
   }
   
   // return current number of self-test errors
-  return ataPrintSmartSelfTestlog(&log, false, fix_firmwarebug);
+  return ataPrintSmartSelfTestlog(&log, false, firmwarebugs);
 }
 
 #define SELFTEST_ERRORCOUNT(x) (x & 0xff)
@@ -1845,7 +1766,7 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
     return 2; 
   }
 
-  // Log drive identity and size
+  // Get drive identity, size and rotation rate (HDD/SSD)
   char model[40+1], serial[20+1], firmware[8+1];
   ata_format_id_string(model, drive.model, sizeof(model)-1);
   ata_format_id_string(serial, drive.serial_no, sizeof(serial)-1);
@@ -1854,6 +1775,7 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
   ata_size_info sizes;
   ata_get_size_info(&drive, sizes);
   state.num_sectors = sizes.sectors;
+  cfg.dev_rpm = ata_get_rotation_rate(&drive);
 
   char wwn[30]; wwn[0] = 0;
   unsigned oui = 0; uint64_t unique_id = 0;
@@ -1861,10 +1783,12 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
   if (naa >= 0)
     snprintf(wwn, sizeof(wwn), "WWN:%x-%06x-%09"PRIx64", ", naa, oui, unique_id);
 
+  // Format device id string for warning emails
   char cap[32];
-  PrintOut(LOG_INFO, "Device: %s, %s, S/N:%s, %sFW:%s, %s\n", name,
-           model, serial, wwn, firmware,
-           format_capacity(cap, sizeof(cap), sizes.capacity, "."));
+  cfg.dev_idinfo = strprintf("%s, S/N:%s, %sFW:%s, %s", model, serial, wwn, firmware,
+                     format_capacity(cap, sizeof(cap), sizes.capacity, "."));
+
+  PrintOut(LOG_INFO, "Device: %s, %s\n", name, cfg.dev_idinfo.c_str());
 
   // Show if device in database, and use preset vendor attribute
   // options unless user has requested otherwise.
@@ -1873,7 +1797,7 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
   else {
     // Apply vendor specific presets, print warning if present
     const drive_settings * dbentry = lookup_drive_apply_presets(
-      &drive, cfg.attribute_defs, cfg.fix_firmwarebug);
+      &drive, cfg.attribute_defs, cfg.firmwarebugs);
     if (!dbentry)
       PrintOut(LOG_INFO, "Device: %s, not found in smartd database.\n", name);
     else {
@@ -1997,7 +1921,8 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
 
     if (   (cfg.tempdiff || cfg.tempinfo || cfg.tempcrit)
         && !ata_return_temperature_value(&state.smartval, cfg.attribute_defs)) {
-      PrintOut(LOG_CRIT, "Device: %s, can't monitor Temperature, ignoring -W Directive\n", name);
+      PrintOut(LOG_INFO, "Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
+               name, cfg.tempdiff, cfg.tempinfo, cfg.tempcrit);
       cfg.tempdiff = cfg.tempinfo = cfg.tempcrit = 0;
     }
 
@@ -2044,12 +1969,13 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
   bool smart_logdir_ok = false, gp_logdir_ok = false;
 
   if (   isGeneralPurposeLoggingCapable(&drive)
-      && (cfg.errorlog || cfg.selftest)        ) {
+      && (cfg.errorlog || cfg.selftest)
+      && !cfg.firmwarebugs.is_set(BUG_NOLOGDIR)) {
       if (!ataReadLogDirectory(atadev, &smart_logdir, false))
         smart_logdir_ok = true;
   }
 
-  if (cfg.xerrorlog) {
+  if (cfg.xerrorlog && !cfg.firmwarebugs.is_set(BUG_NOLOGDIR)) {
     if (!ataReadLogDirectory(atadev, &gp_logdir, true))
       gp_logdir_ok = true;
   }
@@ -2064,7 +1990,7 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
       PrintOut(LOG_INFO, "Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
       cfg.selftest = false;
     }
-    else if ((retval = SelfTestErrorCount(atadev, name, cfg.fix_firmwarebug)) < 0) {
+    else if ((retval = SelfTestErrorCount(atadev, name, cfg.firmwarebugs)) < 0) {
       PrintOut(LOG_INFO, "Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
       cfg.selftest = false;
     }
@@ -2084,7 +2010,7 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
       PrintOut(LOG_INFO, "Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
       cfg.errorlog = false;
     }
-    else if ((errcnt1 = read_ata_error_count(atadev, name, cfg.fix_firmwarebug, false)) < 0) {
+    else if ((errcnt1 = read_ata_error_count(atadev, name, cfg.firmwarebugs, false)) < 0) {
       PrintOut(LOG_INFO, "Device: %s, no SMART Error Log, ignoring -l error\n", name);
       cfg.errorlog = false;
     }
@@ -2094,12 +2020,13 @@ static int ATADeviceScan(dev_config & cfg, dev_state & state, ata_device * atade
 
   if (cfg.xerrorlog) {
     int errcnt2;
-    if (!(cfg.permissive || (gp_logdir_ok && gp_logdir.entry[0x03-1].numsectors))) {
+    if (!(   cfg.permissive || cfg.firmwarebugs.is_set(BUG_NOLOGDIR)
+          || (gp_logdir_ok && gp_logdir.entry[0x03-1].numsectors)   )) {
       PrintOut(LOG_INFO, "Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
                name);
       cfg.xerrorlog = false;
     }
-    else if ((errcnt2 = read_ata_error_count(atadev, name, cfg.fix_firmwarebug, true)) < 0) {
+    else if ((errcnt2 = read_ata_error_count(atadev, name, cfg.firmwarebugs, true)) < 0) {
       PrintOut(LOG_INFO, "Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
       cfg.xerrorlog = false;
     }
@@ -2235,7 +2162,7 @@ static int SCSIDeviceScan(dev_config & cfg, dev_state & state, scsi_device * scs
   UINT8  tBuf[64];
   UINT8  inqBuf[96];
   UINT8  vpdBuf[252];
-  char lu_id[64];
+  char lu_id[64], serial[256], vendor[40], model[40];
 
   // Device must be open
   memset(inqBuf, 0, 96);
@@ -2249,7 +2176,8 @@ static int SCSIDeviceScan(dev_config & cfg, dev_state & state, scsi_device * scs
       return 2;
     }
   }
-  version = inqBuf[2];
+  version = (inqBuf[2] & 0x7f);        /* Accept old ISO/IEC 9316:1995 variants */
+
   avail_len = inqBuf[4] + 5;
   len = (avail_len < req_len) ? avail_len : req_len;
   if (len < 36) {
@@ -2266,28 +2194,50 @@ static int SCSIDeviceScan(dev_config & cfg, dev_state & state, scsi_device * scs
              "skip\n", device, pdt);
     return 2;
   }
+
+  if (supported_vpd_pages_p) {
+    delete supported_vpd_pages_p;
+    supported_vpd_pages_p = NULL;
+  }
+  supported_vpd_pages_p = new supported_vpd_pages(scsidev);
+
   lu_id[0] = '\0';
-  if ((version >= 0x4) && (version < 0x8)) {
-    /* SPC-2 to SPC-5 */
-    if (0 == (err = scsiInquiryVpd(scsidev, 0x83, vpdBuf, sizeof(vpdBuf)))) {
+  if ((version >= 0x3) && (version < 0x8)) {
+    /* SPC to SPC-5 */
+    if (0 == scsiInquiryVpd(scsidev, SCSI_VPD_DEVICE_IDENTIFICATION,
+                           vpdBuf, sizeof(vpdBuf))) {
       len = vpdBuf[3];
       scsi_decode_lu_dev_id(vpdBuf + 4, len, lu_id, sizeof(lu_id), NULL);
     }
-  } 
+  }
+  serial[0] = '\0';
+  if (0 == scsiInquiryVpd(scsidev, SCSI_VPD_UNIT_SERIAL_NUMBER,
+                         vpdBuf, sizeof(vpdBuf))) {
+         len = vpdBuf[3];
+         vpdBuf[4 + len] = '\0';
+         scsi_format_id_string(serial, (const unsigned char *)&vpdBuf[4], len);
+  }
 
   unsigned int lb_size;
   char si_str[64];
-  uint64_t capacity = scsiGetSize(scsidev, &lb_size);
+  uint64_t capacity = scsiGetSize(scsidev, &lb_size, NULL);
 
   if (capacity)
     format_capacity(si_str, sizeof(si_str), capacity);
   else
     si_str[0] = '\0';
-  PrintOut(LOG_INFO, "Device: %s, [%.8s %.16s %.4s]%s%s%s%s\n",
-          device, (char *)&inqBuf[8], (char *)&inqBuf[16],
-          (char *)&inqBuf[32],
-          (lu_id[0] ? ", lu id: " : ""), (lu_id[0] ? lu_id : ""),
-          (si_str[0] ? ", " : ""), (si_str[0] ? si_str : ""));
+
+  // Format device id string for warning emails
+  cfg.dev_idinfo = strprintf("[%.8s %.16s %.4s]%s%s%s%s%s%s",
+                     (char *)&inqBuf[8], (char *)&inqBuf[16], (char *)&inqBuf[32],
+                     (lu_id[0] ? ", lu id: " : ""), (lu_id[0] ? lu_id : ""),
+                     (serial[0] ? ", S/N: " : ""), (serial[0] ? serial : ""),
+                     (si_str[0] ? ", " : ""), (si_str[0] ? si_str : ""));
+  
+  // format "model" string
+  scsi_format_id_string(vendor, (const unsigned char *)&inqBuf[8], 8);
+  scsi_format_id_string(model, (const unsigned char *)&inqBuf[16], 16);
+  PrintOut(LOG_INFO, "Device: %s, %s\n", device, cfg.dev_idinfo.c_str());
 
   // check that device is ready for commands. IE stores its stuff on
   // the media.
@@ -2343,6 +2293,18 @@ static int SCSIDeviceScan(dev_config & cfg, dev_state & state, scsi_device * scs
       case IE_LPAGE:
         state.SmartPageSupported = 1;
         break;
+      case READ_ERROR_COUNTER_LPAGE:
+        state.ReadECounterPageSupported = 1;
+        break;
+      case WRITE_ERROR_COUNTER_LPAGE:
+        state.WriteECounterPageSupported = 1;
+        break;
+      case VERIFY_ERROR_COUNTER_LPAGE:
+        state.VerifyECounterPageSupported = 1;
+        break;
+      case NON_MEDIUM_ERROR_LPAGE:
+        state.NonMediumErrorPageSupported = 1;
+        break;
       default:
         break;
       }
@@ -2361,7 +2323,8 @@ static int SCSIDeviceScan(dev_config & cfg, dev_state & state, scsi_device * scs
       PrintOut(LOG_INFO, "Device: %s, unexpectedly failed to read SMART values\n", device);
       state.SuppressReport = 1;
       if (cfg.tempdiff || cfg.tempinfo || cfg.tempcrit) {
-        PrintOut(LOG_CRIT, "Device: %s, can't monitor Temperature, ignoring -W Directive\n", device);
+        PrintOut(LOG_INFO, "Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
+                 device, cfg.tempdiff, cfg.tempinfo, cfg.tempcrit);
         cfg.tempdiff = cfg.tempinfo = cfg.tempcrit = 0;
       }
     }
@@ -2403,21 +2366,29 @@ static int SCSIDeviceScan(dev_config & cfg, dev_state & state, scsi_device * scs
   // tell user we are registering device
   PrintOut(LOG_INFO, "Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
 
-  // TODO: Build file name for state file
-  if (!state_path_prefix.empty()) {
-    PrintOut(LOG_INFO, "Device: %s, persistence not yet supported for SCSI; ignoring -s option.\n", device);
-  }
-  // TODO: Build file name for attribute log file
-  if (!attrlog_path_prefix.empty()) {
-    PrintOut(LOG_INFO, "Device: %s, attribute log not yet supported for SCSI; ignoring -A option.\n", device);
-  }
-
   // Make sure that init_standby_check() ignores SCSI devices
   cfg.offlinests_ns = cfg.selfteststs_ns = false;
 
   // close file descriptor
   CloseDevice(scsidev, device);
 
+  if (!state_path_prefix.empty() || !attrlog_path_prefix.empty()) {
+    // Build file name for state file
+    std::replace_if(model, model+strlen(model), not_allowed_in_filename, '_');
+    std::replace_if(serial, serial+strlen(serial), not_allowed_in_filename, '_');
+    if (!state_path_prefix.empty()) {
+      cfg.state_file = strprintf("%s%s-%s-%s.scsi.state", state_path_prefix.c_str(), vendor, model, serial);
+      // Read previous state
+      if (read_dev_state(cfg.state_file.c_str(), state)) {
+        PrintOut(LOG_INFO, "Device: %s, state read from %s\n", device, cfg.state_file.c_str());
+        // Copy ATA attribute values to temp state
+        state.update_temp_state();
+      }
+    }
+    if (!attrlog_path_prefix.empty())
+      cfg.attrlog_file = strprintf("%s%s-%s-%s.scsi.csv", attrlog_path_prefix.c_str(), vendor, model, serial);
+  }
+
   finish_device_scan(cfg, state);
 
   return 0;
@@ -2461,7 +2432,7 @@ static void CheckSelfTestLogs(const dev_config & cfg, dev_state & state, int new
       // new failure.
       PrintOut(LOG_CRIT, "Device: %s, new Self-Test Log error at hour timestamp %d\n",
                name, newh);
-      MailWarning(cfg, state, 3, "Device: %s, new Self-Test Log error at hour timestamp %d\n",
+      MailWarning(cfg, state, 3, "Device: %s, new Self-Test Log error at hour timestamp %d",
                    name, newh);
       state.must_write = true;
     }
@@ -2755,7 +2726,7 @@ static int DoATASelfTest(const dev_config & cfg, dev_state & state, ata_device *
   
   // If currently running a self-test, do not interrupt it to start another.
   if (15==(data.self_test_exec_status >> 4)) {
-    if (cfg.fix_firmwarebug == FIX_SAMSUNG3 && data.self_test_exec_status == 0xf0) {
+    if (cfg.firmwarebugs.is_set(BUG_SAMSUNG3) && data.self_test_exec_status == 0xf0) {
       PrintOut(LOG_INFO, "Device: %s, will not skip scheduled %sTest "
                "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
     } else {
@@ -2834,17 +2805,16 @@ static void check_pending(const dev_config & cfg, dev_state & state,
     s += strprintf(" (changed %+"PRId64")", rawval - prev_rawval);
 
   PrintOut(LOG_CRIT, "%s\n", s.c_str());
-  MailWarning(cfg, state, mailtype, "%s\n", s.c_str());
+  MailWarning(cfg, state, mailtype, "%s", s.c_str());
   state.must_write = true;
 }
 
 // Format Temperature value
-static const char * fmt_temp(unsigned char x, char * buf)
+static const char * fmt_temp(unsigned char x, char (& buf)[20])
 {
   if (!x) // unset
-    strcpy(buf, "??");
-  else
-    sprintf(buf, "%u", x);
+    return "??";
+  snprintf(buf, sizeof(buf), "%u", x);
   return buf;
 }
 
@@ -2908,7 +2878,7 @@ static void CheckTemperature(const dev_config & cfg, dev_state & state, unsigned
   if (cfg.tempcrit && currtemp >= cfg.tempcrit) {
     PrintOut(LOG_CRIT, "Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
       cfg.name.c_str(), currtemp, cfg.tempcrit, fmt_temp(state.tempmin, buf), minchg, state.tempmax, maxchg);
-    MailWarning(cfg, state, 12, "Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
+    MailWarning(cfg, state, 12, "Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
       cfg.name.c_str(), currtemp, cfg.tempcrit, fmt_temp(state.tempmin, buf), minchg, state.tempmax, maxchg);
   }
   else if (cfg.tempinfo && currtemp >= cfg.tempinfo) {
@@ -2937,7 +2907,7 @@ static void check_attribute(const dev_config & cfg, dev_state & state,
   // If requested, check for usage attributes that have failed.
   if (   cfg.usagefailed && attrstate == ATTRSTATE_FAILED_NOW
       && !cfg.monitor_attr_flags.is_set(attr.id, MONITOR_IGN_FAILUSE)) {
-    std::string attrname = ata_get_smart_attr_name(attr.id, cfg.attribute_defs);
+    std::string attrname = ata_get_smart_attr_name(attr.id, cfg.attribute_defs, cfg.dev_rpm);
     PrintOut(LOG_CRIT, "Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.name.c_str(), attr.id, attrname.c_str());
     MailWarning(cfg, state, 2, "Device: %s, Failed SMART usage Attribute: %d %s.", cfg.name.c_str(), attr.id, attrname.c_str());
     state.must_write = true;
@@ -3004,7 +2974,7 @@ static void check_attribute(const dev_config & cfg, dev_state & state,
   // Format message
   std::string msg = strprintf("Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
                               cfg.name.c_str(), (prefail ? "Prefailure" : "Usage"), attr.id,
-                              ata_get_smart_attr_name(attr.id, cfg.attribute_defs).c_str(),
+                              ata_get_smart_attr_name(attr.id, cfg.attribute_defs, cfg.dev_rpm).c_str(),
                               prevstr.c_str(), currstr.c_str());
 
   // Report this change as critical ?
@@ -3195,16 +3165,16 @@ static int ATACheckDevice(const dev_config & cfg, dev_state & state, ata_device
   
   // check if number of selftest errors has increased (note: may also DECREASE)
   if (cfg.selftest)
-    CheckSelfTestLogs(cfg, state, SelfTestErrorCount(atadev, name, cfg.fix_firmwarebug));
+    CheckSelfTestLogs(cfg, state, SelfTestErrorCount(atadev, name, cfg.firmwarebugs));
 
   // check if number of ATA errors has increased
   if (cfg.errorlog || cfg.xerrorlog) {
 
     int errcnt1 = -1, errcnt2 = -1;
     if (cfg.errorlog)
-      errcnt1 = read_ata_error_count(atadev, name, cfg.fix_firmwarebug, false);
+      errcnt1 = read_ata_error_count(atadev, name, cfg.firmwarebugs, false);
     if (cfg.xerrorlog)
-      errcnt2 = read_ata_error_count(atadev, name, cfg.fix_firmwarebug, true);
+      errcnt2 = read_ata_error_count(atadev, name, cfg.firmwarebugs, true);
 
     // new number of errors is max of both logs
     int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
@@ -3251,6 +3221,7 @@ static int SCSICheckDevice(const dev_config & cfg, dev_state & state, scsi_devic
     UINT8 asc, ascq;
     UINT8 currenttemp;
     UINT8 triptemp;
+    UINT8  tBuf[252];
     const char * name = cfg.name.c_str();
     const char *cp;
 
@@ -3266,6 +3237,7 @@ static int SCSICheckDevice(const dev_config & cfg, dev_state & state, scsi_devic
       return 1;
     } else if (debugmode)
         PrintOut(LOG_INFO,"Device: %s, opened SCSI device\n", name);
+    reset_warning_mail(cfg, state, 9, "open device worked again");
     currenttemp = 0;
     asc = 0;
     ascq = 0;
@@ -3283,6 +3255,8 @@ static int SCSICheckDevice(const dev_config & cfg, dev_state & state, scsi_devic
         if (cp) {
             PrintOut(LOG_CRIT, "Device: %s, SMART Failure: %s\n", name, cp);
             MailWarning(cfg, state, 1,"Device: %s, SMART Failure: %s", name, cp);
+        } else if (asc == 4 && ascq == 9) {
+            PrintOut(LOG_INFO,"Device: %s, self-test in progress\n", name);  
         } else if (debugmode)
             PrintOut(LOG_INFO,"Device: %s, non-SMART asc,ascq: %d,%d\n",
                      name, (int)asc, (int)ascq);  
@@ -3290,7 +3264,7 @@ static int SCSICheckDevice(const dev_config & cfg, dev_state & state, scsi_devic
         PrintOut(LOG_INFO,"Device: %s, SMART health: passed\n", name);  
 
     // check temperature limits
-    if (cfg.tempdiff || cfg.tempinfo || cfg.tempcrit)
+    if (cfg.tempdiff || cfg.tempinfo || cfg.tempcrit || !cfg.attrlog_file.empty())
       CheckTemperature(cfg, state, currenttemp, triptemp);
 
     // check if number of selftest errors has increased (note: may also DECREASE)
@@ -3302,6 +3276,29 @@ static int SCSICheckDevice(const dev_config & cfg, dev_state & state, scsi_devic
       if (testtype)
         DoSCSISelfTest(cfg, state, scsidev, testtype);
     }
+    if (!cfg.attrlog_file.empty()){
+      // saving error counters to state
+      if (state.ReadECounterPageSupported && (0 == scsiLogSense(scsidev,
+          READ_ERROR_COUNTER_LPAGE, 0, tBuf, sizeof(tBuf), 0))) {
+          scsiDecodeErrCounterPage(tBuf, &state.scsi_error_counters[0].errCounter);
+          state.scsi_error_counters[0].found=1;
+      }
+      if (state.WriteECounterPageSupported && (0 == scsiLogSense(scsidev,
+          WRITE_ERROR_COUNTER_LPAGE, 0, tBuf, sizeof(tBuf), 0))) {
+          scsiDecodeErrCounterPage(tBuf, &state.scsi_error_counters[1].errCounter);
+          state.scsi_error_counters[1].found=1;
+      }
+      if (state.VerifyECounterPageSupported && (0 == scsiLogSense(scsidev,
+          VERIFY_ERROR_COUNTER_LPAGE, 0, tBuf, sizeof(tBuf), 0))) {
+          scsiDecodeErrCounterPage(tBuf, &state.scsi_error_counters[2].errCounter);
+          state.scsi_error_counters[2].found=1;
+      }
+      if (state.NonMediumErrorPageSupported && (0 == scsiLogSense(scsidev,
+          NON_MEDIUM_ERROR_LPAGE, 0, tBuf, sizeof(tBuf), 0))) {
+          scsiDecodeNonMediumErrPage(tBuf, &state.scsi_nonmedium_error.nme);
+          state.scsi_nonmedium_error.found=1;
+      }
+    }
     CloseDevice(scsidev, name);
     return 0;
 }
@@ -3561,7 +3558,8 @@ static void printoutvaliddirectiveargs(int priority, char d)
     PrintOut(priority, "use, ignore, show, showall");
     break;
   case 'F':
-    PrintOut(priority, "none, samsung, samsung2, samsung3");
+    PrintOut(priority, "%s", get_valid_firmwarebug_args());
+    break;
   case 'e':
     PrintOut(priority, "aam,[N|off], apm,[N|off], lookahead,[on|off], "
                        "security-freeze, standby,[N|off], wcache,[on|off]");
@@ -3627,6 +3625,35 @@ static int Get3Integers(const char *arg, const char *name, const char *token, in
 }
 
 
+#ifdef _WIN32
+
+// Concatenate strtok() results if quoted with "..."
+static const char * strtok_dequote(const char * delimiters)
+{
+  const char * t = strtok(0, delimiters);
+  if (!t || t[0] != '"')
+    return t;
+
+  static std::string token;
+  token = t+1;
+  for (;;) {
+    t = strtok(0, delimiters);
+    if (!t || !*t)
+      return "\"";
+    token += ' ';
+    int len = strlen(t);
+    if (t[len-1] == '"') {
+      token += std::string(t, len-1);
+      break;
+    }
+    token += t;
+  }
+  return token.c_str();
+}
+
+#endif // _WIN32
+
+
 // This function returns 1 if it has correctly parsed one token (and
 // any arguments), else zero if no tokens remain.  It returns -1 if an
 // error was encountered.
@@ -3696,6 +3723,8 @@ static int ParseToken(char * token, dev_config & cfg)
     // specify the device type
     if ((arg = strtok(NULL, delim)) == NULL) {
       missingarg = 1;
+    } else if (!strcmp(arg, "ignore")) {
+      cfg.ignore = true;
     } else if (!strcmp(arg, "removable")) {
       cfg.removable = true;
     } else if (!strcmp(arg, "auto")) {
@@ -3706,19 +3735,10 @@ static int ParseToken(char * token, dev_config & cfg)
     break;
   case 'F':
     // fix firmware bug
-    if ((arg = strtok(NULL, delim)) == NULL) {
+    if (!(arg = strtok(0, delim)))
       missingarg = 1;
-    } else if (!strcmp(arg, "none")) {
-      cfg.fix_firmwarebug = FIX_NONE;
-    } else if (!strcmp(arg, "samsung")) {
-      cfg.fix_firmwarebug = FIX_SAMSUNG;
-    } else if (!strcmp(arg, "samsung2")) {
-      cfg.fix_firmwarebug = FIX_SAMSUNG2;
-    } else if (!strcmp(arg, "samsung3")) {
-      cfg.fix_firmwarebug = FIX_SAMSUNG3;
-    } else {
+    else if (!parse_firmwarebug_def(arg, cfg.firmwarebugs))
       badarg = 1;
-    }
     break;
   case 'H':
     // check SMART status
@@ -3894,6 +3914,18 @@ static int ParseToken(char * token, dev_config & cfg)
       if (!cfg.emailaddress.empty())
         PrintOut(LOG_INFO, "File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
                  configfile, lineno, name, cfg.emailaddress.c_str());
+#ifdef _WIN32
+      if (   !strcmp(arg, "msgbox")          || !strcmp(arg, "sysmsgbox")
+          || str_starts_with(arg, "msgbox,") || str_starts_with(arg, "sysmsgbox,")) {
+        cfg.emailaddress = "console";
+        const char * arg2 = strchr(arg, ',');
+        if (arg2)
+          cfg.emailaddress += arg2;
+        PrintOut(LOG_INFO, "File %s line %d (drive %s): Deprecated -m %s changed to -m %s\n",
+                 configfile, lineno, name, arg, cfg.emailaddress.c_str());
+      }
+      else
+#endif
       cfg.emailaddress = arg;
     }
     break;
@@ -3911,7 +3943,18 @@ static int ParseToken(char * token, dev_config & cfg)
       cfg.emailtest = 1;
     else if (!strcmp(arg, "exec")) {
       // Get the next argument (the command line)
-      if (!(arg = strtok(NULL, delim))) {
+#ifdef _WIN32
+      // Allow "/path name/with spaces/..." on Windows
+      arg = strtok_dequote(delim);
+      if (arg && arg[0] == '"') {
+        PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
+                 configfile, lineno, name, token);
+        return -1;
+      }
+#else
+      arg = strtok(0, delim);
+#endif
+      if (!arg) {
         PrintOut(LOG_CRIT, "File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
                  configfile, lineno, name, token);
         return -1;
@@ -4166,7 +4209,7 @@ static int ParseConfigLine(dev_config_vector & conf_entries, dev_config & defaul
                cfg.name.c_str(), cfg.lineno, configfile);
       return -2;
     }
-    // From here on the sign of <nomailer> is address.empty() and !cfg.emailcmdline.empty()
+    // From here on the sign of <nomailer> is cfg.emailaddress.empty() and !cfg.emailcmdline.empty()
     cfg.emailaddress.clear();
   }
 
@@ -4289,7 +4332,7 @@ static int ParseConfigFile(dev_config_vector & conf_entries)
     }
     
     // copy string so far into fullline, and increment length
-    strcpy(fullline+cont,line);
+    snprintf(fullline+cont, sizeof(fullline)-cont, "%s" ,line);
     cont+=len;
 
     // is this a continuation line.  If so, replace \ by space and look at next line
@@ -4350,16 +4393,19 @@ static void check_abs_path(char option, const std::string & path)
 // version/license/copyright messages
 static void ParseOpts(int argc, char **argv)
 {
-  // Init default configfile path
+  // Init default path names
 #ifndef _WIN32
   configfile = SMARTMONTOOLS_SYSCONFDIR"/smartd.conf";
+  warning_script = SMARTMONTOOLS_SYSCONFDIR"/smartd_warning.sh";
 #else
-  static std::string configfile_str = get_exe_dir() + "/smartd.conf";
+  std::string exedir = get_exe_dir();
+  static std::string configfile_str = exedir + "/smartd.conf";
   configfile = configfile_str.c_str();
+  warning_script = exedir + "/smartd_warning.cmd";
 #endif
 
   // Please update GetValidArgList() if you edit shortopts
-  static const char shortopts[] = "c:l:q:dDni:p:r:s:A:B:Vh?"
+  static const char shortopts[] = "c:l:q:dDni:p:r:s:A:B:w:Vh?"
 #ifdef HAVE_LIBCAP_NG
                                                           "C"
 #endif
@@ -4382,6 +4428,7 @@ static void ParseOpts(int argc, char **argv)
     { "savestates",     required_argument, 0, 's' },
     { "attributelog",   required_argument, 0, 'A' },
     { "drivedb",        required_argument, 0, 'B' },
+    { "warnexec",       required_argument, 0, 'w' },
     { "version",        no_argument,       0, 'V' },
     { "license",        no_argument,       0, 'V' },
     { "copyright",      no_argument,       0, 'V' },
@@ -4543,6 +4590,9 @@ static void ParseOpts(int argc, char **argv)
         debugmode = savedebug;
       }
       break;
+    case 'w':
+      warning_script = optarg;
+      break;
     case 'V':
       // print version and CVS info
       debugmode = 1;
@@ -4744,6 +4794,43 @@ static int ReadOrMakeConfigEntries(dev_config_vector & conf_entries, smart_devic
   return conf_entries.size();
 }
 
+// Return true if TYPE contains a RAID drive number
+static bool is_raid_type(const char * type)
+{
+  if (str_starts_with(type, "sat,"))
+    return false;
+  int i;
+  if (sscanf(type, "%*[^,],%d", &i) != 1)
+    return false;
+  return true;
+}
+
+// Return true if DEV is already in DEVICES[0..NUMDEVS) or IGNORED[*]
+static bool is_duplicate_device(const smart_device * dev,
+                                const smart_device_list & devices, unsigned numdevs,
+                                const dev_config_vector & ignored)
+{
+  const smart_device::device_info & info1 = dev->get_info();
+  bool is_raid1 = is_raid_type(info1.dev_type.c_str());
+
+  for (unsigned i = 0; i < numdevs; i++) {
+    const smart_device::device_info & info2 = devices.at(i)->get_info();
+    // -d TYPE options must match if RAID drive number is specified
+    if (   info1.dev_name == info2.dev_name
+        && (   info1.dev_type == info2.dev_type
+            || !is_raid1 || !is_raid_type(info2.dev_type.c_str())))
+      return true;
+  }
+
+  for (unsigned i = 0; i < ignored.size(); i++) {
+    const dev_config & cfg2 = ignored.at(i);
+    if (   info1.dev_name == cfg2.dev_name
+        && (   info1.dev_type == cfg2.dev_type
+            || !is_raid1 || !is_raid_type(cfg2.dev_type.c_str())))
+      return true;
+  }
+  return false;
+}
 
 // This function tries devices from conf_entries.  Each one that can be
 // registered is moved onto the [ata|scsi]devices lists and removed
@@ -4757,10 +4844,22 @@ static void RegisterDevices(const dev_config_vector & conf_entries, smart_device
   states.clear();
 
   // Register entries
+  dev_config_vector ignored_entries;
+  unsigned numnoscan = 0;
   for (unsigned i = 0; i < conf_entries.size(); i++){
 
     dev_config cfg = conf_entries[i];
 
+    if (cfg.ignore) {
+      // Store for is_duplicate_device() check and ignore
+      PrintOut(LOG_INFO, "Device: %s%s%s%s, ignored\n", cfg.name.c_str(),
+               (!cfg.dev_type.empty() ? " [" : ""),
+               cfg.dev_type.c_str(),
+               (!cfg.dev_type.empty() ? "]" : ""));
+      ignored_entries.push_back(cfg);
+      continue;
+    }
+
     // get device of appropriate type
     smart_device_auto_ptr dev;
     bool scanning = false;
@@ -4768,8 +4867,15 @@ static void RegisterDevices(const dev_config_vector & conf_entries, smart_device
     // Device may already be detected during devicescan
     if (i < scanned_devs.size()) {
       dev = scanned_devs.release(i);
-      if (dev)
+      if (dev) {
+        // Check for a preceding non-DEVICESCAN entry for the same device
+        if (  (numnoscan || !ignored_entries.empty())
+            && is_duplicate_device(dev.get(), devices, numnoscan, ignored_entries)) {
+          PrintOut(LOG_INFO, "Device: %s, duplicate, ignored\n", dev->get_info_name());
+          continue;
+        }
         scanning = true;
+      }
     }
 
     if (!dev) {
@@ -4834,6 +4940,8 @@ static void RegisterDevices(const dev_config_vector & conf_entries, smart_device
       configs.push_back(cfg);
       states.push_back(state);
       devices.push_back(dev);
+      if (!scanning)
+        numnoscan = devices.size();
     }
     // if device is explictly listed and we can't register it, then
     // exit unless the user has specified that the device is removable
index 7e0fe60c04d67805430109329e9f5496e64ffa85..0c1e52c6de9df214d9455c650a3ee03137621eba 100644 (file)
@@ -2,7 +2,7 @@
 
 # smartmontools init file for smartd
 # Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-# $Id: smartd.initd.in 3360 2011-06-06 19:25:36Z chrfranke $
+# $Id: smartd.initd.in 3727 2012-12-13 17:23:06Z samm2 $
 
 # For RedHat and cousins:
 # chkconfig: 2345 40 40
@@ -27,8 +27,8 @@
 # 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, write to the Free Software Foundation, Inc., 675
-# Mass Ave, Cambridge, MA 02139, USA.
+# example COPYING); if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 # This code was originally developed as a Senior Thesis by Michael Cornwell
 # at the Concurrent Systems Laboratory (now part of the Storage Systems
 # Research Center), Jack Baskin School of Engineering, University of
@@ -227,6 +227,15 @@ elif [ -f /etc/SuSE-release ] ; then
     if test -n "$SMARTD_DRIVEDB" ; then
        smartd_opts="$smartd_opts -B $SMARTD_DRIVEDB"
     fi
+    if test "$SMARTD_SAVESTATES" = "no" ; then
+       smartd_opts="$smartd_opts -s \"\""
+    fi
+    if test "$SMARTD_ATTRLOG" = "no" ; then
+       smartd_opts="$smartd_opts -A \"\""
+    fi
+    if test -n "$SMARTD_EXTRA_OPTS" ; then
+       smartd_opts="$smartd_opts $SMARTD_EXTRA_OPTS"
+    fi
 
     # Shell functions sourced from /etc/rc.status:
     #      rc_check         check and set local and overall rc status
@@ -269,7 +278,7 @@ elif [ -f /etc/SuSE-release ] ; then
 
            # We don't use startproc - we need to check for return code 17.
            if ! /sbin/checkproc $SMARTD_BIN ; then
-               $SMARTD_BIN $smartd_opts
+               eval $SMARTD_BIN$smartd_opts
                # Remember status and be verbose
                if test $? -ne 17 ; then
                    rc_status -v
diff --git a/smartd_warning.sh.in b/smartd_warning.sh.in
new file mode 100644 (file)
index 0000000..a077255
--- /dev/null
@@ -0,0 +1,209 @@
+#! /bin/sh
+#
+# smartd warning script
+#
+# Copyright (C) 2012-13 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: smartd_warning.sh.in 3809 2013-04-18 19:41:40Z chrfranke $
+#
+
+set -e
+
+# Set by config.status
+PACKAGE="@PACKAGE@"
+VERSION="@VERSION@"
+prefix="@prefix@"
+sysconfdir="@sysconfdir@"
+
+# Default mailer
+os_mailer="@os_mailer@"
+
+# Plugin directory
+plugindir="$sysconfdir/smartd_warning.d"
+
+# Parse options
+dryrun=
+case $1 in
+  --dryrun) dryrun=t; shift ;;
+esac
+
+if [ $# != 0 ]; then
+  cat <<EOF
+smartd $VERSION warning message script
+
+Usage:
+  export SMARTD_MAILER='Path to external script, empty for "$os_mailer"'
+  export SMARTD_ADDRESS='Space separated mail adresses, empty if none'
+  export SMARTD_MESSAGE='Error Message'
+  export SMARTD_FAILTYPE='Type of failure, "EMailTest" for tests'
+  export SMARTD_TFIRST='Date of first message sent, empty if none'
+  #export SMARTD_TFIRSTEPOCH='time_t format of above'
+  export SMARTD_PREVCNT='Number of previous messages, 0 if none'
+  export SMARTD_NEXTDAYS='Number of days until next message, empty if none'
+  export SMARTD_DEVICEINFO='Device identify information'
+  #export SMARTD_DEVICE='Device name'
+  #export SMARTD_DEVICESTRING='Annotated device name'
+  #export SMARTD_DEVICETYPE='Device type from -d directive, "auto" if none'
+  $0 [--dryrun]
+EOF
+  exit 1
+fi
+
+if [ -z "${SMARTD_ADDRESS}${SMARTD_MAILER}" ]; then
+  echo "$0: SMARTD_ADDRESS or SMARTD_MAILER must be set" >&2
+  exit 1
+fi
+
+# Get host and domain names
+for cmd in @os_hostname@ 'echo "[Unknown]"'; do
+  hostname=`eval $cmd 2>/dev/null` || continue
+  test -n "$hostname" || continue
+  break
+done
+
+dnsdomain=${hostname#*.}
+if [ "$dnsdomain" != "$hostname" ]; then
+  # hostname command printed FQDN
+  hostname=${hostname%%.*}
+else
+  for cmd in @os_dnsdomainname@ 'echo'; do
+    dnsdomain=`eval $cmd 2>/dev/null` || continue
+    break
+  done
+  test "$dnsdomain" != "(none)" || dnsdomain=
+fi
+
+for cmd in @os_nisdomainname@ 'echo'; do
+  nisdomain=`eval $cmd 2>/dev/null` || continue
+  break
+done
+test "$nisdomain" != "(none)" || nisdomain=
+
+# Format subject
+export SMARTD_SUBJECT="SMART error (${SMARTD_FAILTYPE-[SMARTD_FAILTYPE]}) detected on host: $hostname"
+
+# Format message
+fullmessage=`
+  echo "This message was generated by the smartd daemon running on:"
+  echo
+  echo "   host name:  $hostname"
+  echo "   DNS domain: ${dnsdomain:-[Empty]}"
+  test -z "$nisdomain" ||
+    echo "   NIS domain: $nisdomain"
+  @OS_WIN32_TRUE@test -z "$USERDOMAIN" ||
+  @OS_WIN32_TRUE@  echo "   Win domain: $USERDOMAIN"
+  echo
+  echo "The following warning/error was logged by the smartd daemon:"
+  echo
+  echo "${SMARTD_MESSAGE-[SMARTD_MESSAGE]}"
+  echo
+  echo "Device info:"
+  echo "${SMARTD_DEVICEINFO-[SMARTD_DEVICEINFO]}"
+  echo
+  echo "For details see host's SYSLOG."
+  if [ "$SMARTD_FAILTYPE" != "EmailTest" ]; then
+    echo
+    echo "You can also use the smartctl utility for further investigation."
+    test "$SMARTD_PREVCNT" = "0" ||
+      echo "The original message about this issue was sent at ${SMARTD_TFIRST-[SMARTD_TFIRST]}"
+    case $SMARTD_NEXTDAYS in
+      '') echo "No additional messages about this problem will be sent." ;;
+      1)  echo "Another message will be sent in 24 hours if the problem persists." ;;
+      *)  echo "Another message will be sent in $SMARTD_NEXTDAYS days if the problem persists." ;;
+    esac
+  fi
+`
+
+# Export message with trailing newline
+export SMARTD_FULLMESSAGE="$fullmessage
+"
+
+# Run plugin scripts if requested
+case " $SMARTD_ADDRESS" in
+  *\ @*)
+    if [ -n "$dryrun" ]; then
+      echo "export SMARTD_SUBJECT='$SMARTD_SUBJECT'"
+      echo "export SMARTD_FULLMESSAGE='$SMARTD_FULLMESSAGE'"
+    fi
+
+    # Run ALL scripts if requested
+    case " $SMARTD_ADDRESS " in
+      *\ @ALL\ *)
+        for cmd in "$plugindir"/*; do
+          if [ -f "$cmd" ] && [ -x "$cmd" ]; then
+            if [ -n "$dryrun" ]; then
+              echo "$cmd </dev/null"
+            else
+              "$cmd" </dev/null
+            fi
+          fi
+        done
+        ;;
+    esac
+
+    # Run selected scripts
+    addrs=$SMARTD_ADDRESS
+    SMARTD_ADDRESS=
+    for ad in $addrs; do
+      case $ad in
+        @ALL)
+          ;;
+        @?*)
+          cmd="$plugindir/${ad#@}"
+          if [ -f "$cmd" ] && [ -x "$cmd" ]; then
+            if [ -n "$dryrun" ]; then
+              echo "$cmd </dev/null"
+            else
+              "$cmd" </dev/null
+            fi
+          elif [ ! -e "$cmd" ]; then
+            echo "$cmd: Not found" >&2
+          fi
+          ;;
+        *)
+          SMARTD_ADDRESS="${SMARTD_ADDRESS:+ }$ad"
+          ;;
+      esac
+    done
+
+    # Send email to remaining addresses
+    test -n "$SMARTD_ADDRESS" || exit 0
+    ;;
+esac
+
+# Send mail or run command
+if [ -n "$SMARTD_ADDRESS" ]; then
+
+  # Send mail, use platform mailer by default
+  test -n "$SMARTD_MAILER" || SMARTD_MAILER=$os_mailer
+  if [ -n "$dryrun" ]; then
+    echo "exec '$SMARTD_MAILER' -s '$SMARTD_SUBJECT' $SMARTD_ADDRESS <<EOF
+$fullmessage
+EOF"
+  else
+    exec "$SMARTD_MAILER" -s "$SMARTD_SUBJECT" $SMARTD_ADDRESS <<EOF
+$fullmessage
+EOF
+  fi
+
+elif [ -n "$SMARTD_MAILER" ]; then
+
+  # Run command
+  if [ -n "$dryrun" ]; then
+    echo "export SMARTD_SUBJECT='$SMARTD_SUBJECT'"
+    echo "export SMARTD_FULLMESSAGE='$SMARTD_FULLMESSAGE'"
+    echo "exec '$SMARTD_MAILER' </dev/null"
+  else
+    unset SMARTD_ADDRESS
+    exec "$SMARTD_MAILER" </dev/null
+  fi
+
+fi
index d7bb7bde3535dc3f7dc7fbf31f3d33ee1564296b..e1454cc2f45cce057130169d0ca8f25af85d17c9 100644 (file)
@@ -4,7 +4,7 @@
  * Home page of code is: http://smartmontools.sourceforge.net
  *
  * Copyright (C) 2002-12 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -53,7 +52,7 @@
 #include "atacmds.h"
 #include "dev_interface.h"
 
-const char * utility_cpp_cvsid = "$Id: utility.cpp 3500 2012-01-01 18:03:36Z chrfranke $"
+const char * utility_cpp_cvsid = "$Id: utility.cpp 3739 2013-01-01 16:32:48Z chrfranke $"
                                  UTILITY_H_CVSID INT64_H_CVSID;
 
 const char * packet_types[] = {
@@ -91,7 +90,7 @@ std::string format_version_info(const char * prog_name, bool full /*= false*/)
       "(build date "__DATE__")" // checkout without expansion of Id keywords
 #endif
       " [%s] "BUILD_INFO"\n"
-    "Copyright (C) 2002-12 by Bruce Allen, http://smartmontools.sourceforge.net\n",
+    "Copyright (C) 2002-13, Bruce Allen, Christian Franke, www.smartmontools.org\n",
     prog_name, smi()->get_os_version_str().c_str()
   );
   if (!full)
@@ -503,27 +502,6 @@ int split_report_arg(char *s, int *i)
   return 0;
 }
 
-// same as above but sets *i to -1 if missing , argument
-int split_report_arg2(char *s, int *i){
-  char *tailptr;
-  s+=6;
-
-  if (*s=='\0' || !isdigit((int)*s)) { 
-    // What's left must be integer
-    *i=-1;
-    return 1;
-  }
-
-  errno = 0;
-  *i = (int) strtol(s, &tailptr, 10);
-  if (errno || *tailptr != '\0') {
-    *i=-1;
-    return 1;
-  }
-
-  return 0;
-}
-
 #ifndef HAVE_STRTOULL
 // Replacement for missing strtoull() (Linux with libc < 6, MSVC)
 // Functionality reduced to requirements of smartd and split_selective_arg().
@@ -617,6 +595,8 @@ int split_selective_arg(char *s, uint64_t *start,
       return 0;
     }
   }
+
+  errno = 0;
   *stop = strtoull(s+1, &tailptr, 0);
   if (errno || *tailptr != '\0')
     return 1;
@@ -704,33 +684,6 @@ bool nonempty(const void * data, int size)
   return false;
 }
 
-
-// This routine converts an integer number of milliseconds into a test
-// string of the form Xd+Yh+Zm+Ts.msec.  The resulting text string is
-// written to the array.
-void MsecToText(unsigned int msec, char *txt){
-  unsigned int days, hours, min, sec;
-
-  days       = msec/86400000U;
-  msec      -= days*86400000U;
-
-  hours      = msec/3600000U; 
-  msec      -= hours*3600000U;
-
-  min        = msec/60000U;
-  msec      -= min*60000U;
-
-  sec        = msec/1000U;
-  msec      -= sec*1000U;
-
-  if (days) {
-    txt += sprintf(txt, "%2dd+", (int)days);
-  }
-
-  sprintf(txt, "%02d:%02d:%02d.%03d", (int)hours, (int)min, (int)sec, (int)msec);  
-  return;
-}
-
 // Format integer with thousands separator
 const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
                                        const char * thousands_sep /* = 0 */)
index 13d5ac9a424062338cf0a7cd136b61e08a5c2e7c..72764ee57614eed61ba2f96d55cfa811f8297b8a 100644 (file)
--- a/utility.h
+++ b/utility.h
@@ -13,8 +13,7 @@
  * any later version.
  *
  * You should have received a copy of the GNU General Public License
- * (for example COPYING); if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
  *
  * This code was originally developed as a Senior Thesis by Michael Cornwell
  * at the Concurrent Systems Laboratory (now part of the Storage Systems
@@ -26,7 +25,7 @@
 #ifndef UTILITY_H_
 #define UTILITY_H_
 
-#define UTILITY_H_CVSID "$Id: utility.h 3558 2012-06-05 16:42:05Z chrfranke $"
+#define UTILITY_H_CVSID "$Id: utility.h 3719 2012-12-03 21:19:33Z chrfranke $"
 
 #include <time.h>
 #include <sys/types.h> // for regex.h (according to POSIX)
@@ -95,8 +94,6 @@ void syserror(const char *message);
 
 // Function for processing -r option in smartctl and smartd
 int split_report_arg(char *s, int *i);
-// Function for processing -c option in smartctl and smartd
-int split_report_arg2(char *s, int *i);
 
 // Function for processing -t selective... option in smartctl
 int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode);
@@ -183,9 +180,6 @@ bool nonempty(const void * data, int size);
 // needed to fix glibc bug
 void FixGlibcTimeZoneBug();
 
-// convert time in msec to a text string
-void MsecToText(unsigned int msec, char *txt);
-
 // Format integer with thousands separator
 const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
                                        const char * thousands_sep = 0);