CHANGELOG for smartmontools
-$Id: CHANGELOG 3539 2012-05-01 19:57:02Z chrfranke $
+$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
<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:
Smartmontools installation instructions
=======================================
-$Id: INSTALL 3537 2012-04-28 13:22:41Z chrfranke $
+$Id: INSTALL 3555 2012-06-01 21:07:33Z chrfranke $
Please also see the smartmontools home page:
http://smartmontools.sourceforge.net/
hard drive comes with the offline test switched on by default, so
even that works.
+ The OS X SAT SMART Driver provides access to SMART data for SAT capable
+ USB and Firewire devices:
+ https://github.com/kasbert/OS-X-SAT-SMART-Driver
+ https://github.com/RJVB/OS-X-SAT-SMART-Driver
+ This does not require any smartctl -d TYPE option and should work also
+ with older smartmontools releases.
+
H) OS/2, eComStation
The code was tested on eComStation 1.1, but it should work on all versions
It is also possible to (cross-)build the installer on Linux.
This was successfully tested on Debian with package "nsis".
+To create a combined 32-/64-bit installer, use this in 32-bit build
+directory if 64-build directory is at ../build64:
+
+ make builddir_win64=../build64 installer_win32
+
To both create and run the (interactive) installer, use:
make install-win32
## Process this file with automake to produce Makefile.in
#
-# $Id: Makefile.am 3527 2012-03-25 16:42:24Z chrfranke $
+# $Id: Makefile.am 3545 2012-05-25 21:19:03Z chrfranke $
#
@SET_MAKE@
$(docdir_win32)/README.txt \
$(docdir_win32)/TODO.txt \
$(docdir_win32)/WARNINGS.txt \
- $(docdir_win32)/checksums.txt \
+ $(docdir_win32)/checksums$(win_bits).txt \
$(docdir_win32)/smartd.conf \
$(docdir_win32)/smartctl.8.html \
$(docdir_win32)/smartctl.8.txt \
# Build NSIS installer
# Note: Only option character '-' is also compatible with Linux version of makensis
$(distinst_win32): os_win32/installer.nsi distdir.mkdir $(FILES_WIN32)
+ test -z '$(builddir_win64)' || ( cd $(builddir_win64) && make distdir-win32 )
@date=`sed -n 's,^.*DATE[^"]*"\([^"]*\)".*$$,\1,p' svnversion.h`; \
rev=`sed -n 's,^.*REV[^"]*"\([^"]*\)".*$$,r\1,p' svnversion.h`; \
verstr="$(PACKAGE_VERSION) $$date $$rev "$(BUILD_INFO); \
- echo "'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) -DOUTFILE=$@ -DVERSTR='$$verstr' $<"; \
- '$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) -DOUTFILE=$@ -DVERSTR="$$verstr" $<
+ d64=; test -z '$(builddir_win64)' || d64='-DINPDIR64=$(builddir_win64)/$(PACKAGE)-$(VERSION).win64'; \
+ echo "'$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSTR='$$verstr' $<"; \
+ '$(MAKENSIS)' -V2 -NOCD -DINPDIR=$(distdir_win32) $$d64 -DOUTFILE=$@ -DVERSTR="$$verstr" $<
md5sum $@ > $@.md5
sha1sum $@ > $@.sha1
sha256sum $@ > $@.sha256
$(UNIX2DOS) < $< > $@
touch -r $< $@
-$(docdir_win32)/checksums.txt: $(EXEFILES_WIN32)
+$(docdir_win32)/checksums$(win_bits).txt: $(EXEFILES_WIN32)
(cd $(exedir_win32) && md5sum *.exe && sha1sum *.exe && sha256sum *.exe) \
| $(UNIX2DOS) > $@
smartmontools NEWS
------------------
-$Id: NEWS 3530 2012-03-27 19:54:06Z chrfranke $
+$Id: NEWS 3557 2012-06-04 19:50:21Z chrfranke $
The most up-to-date version of this file is:
http://smartmontools.svn.sourceforge.net/viewvc/smartmontools/trunk/smartmontools/NEWS?view=markup
already running. Override with new option '-t force'.
- smartctl supports extended self-test polling times
greater than 255 minutes.
+- 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.
+- Windows: Support for SATA disks behind Areca controllers.
- Windows smartd: directives '-l offlinests,ns' and
'-l selfteststs,ns'.
+- Windows installer: Combined 32-/64-bit support.
- FreeBSD: fixed crash on SCSI devices with FreeBSD9-RC1
Date 2011-10-20
#include "utility.h"
#include "knowndrives.h"
-const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3539 2012-05-01 19:57:02Z chrfranke $"
+const char * ataprint_cpp_cvsid = "$Id: ataprint.cpp 3554 2012-06-01 20:11:46Z chrfranke $"
ATAPRINT_H_CVSID;
int powermode = ataCheckPowerMode(device);
switch (powermode) {
case -1:
- if (device->get_errno() == ENOSYS) {
+ if (device->is_syscall_unsup()) {
pout("CHECK POWER MODE not implemented, ignoring -n option\n"); break;
}
powername = "SLEEP"; powerlimit = 2;
#include <sys/timeb.h>
#endif
-const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 3524 2012-03-21 22:19:31Z chrfranke $"
+const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 3554 2012-06-01 20:11:46Z chrfranke $"
DEV_INTERFACE_H_CVSID;
/////////////////////////////////////////////////////////////////////////////
{
}
+bool smart_device::is_syscall_unsup() const
+{
+ if (get_errno() == ENOSYS)
+ return true;
+#ifdef ENOTSUP
+ if (get_errno() == ENOTSUP)
+ return true;
+#endif
+ return false;
+}
+
bool smart_device::set_err(int no, const char * msg, ...)
{
if (!msg)
#ifndef DEV_INTERFACE_H
#define DEV_INTERFACE_H
-#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3524 2012-03-21 22:19:31Z chrfranke $\n"
+#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3554 2012-06-01 20:11:46Z chrfranke $\n"
#include "utility.h"
const char * get_errmsg() const
{ return m_err.msg.c_str(); }
+ /// Return true if last error indicates an unsupported system call.
+ /// Default implementation returns true on ENOSYS and ENOTSUP.
+ virtual bool is_syscall_unsup() const;
+
/// Set last error number and message.
/// Printf()-like formatting is supported.
/// Returns false always to allow use as a return expression.
/// Open device with autodetection support.
/// May return another device for further access.
/// In this case, the original pointer is no longer valid.
- /// Default Implementation calls 'open()' and returns 'this'.
+ /// Default implementation calls 'open()' and returns 'this'.
virtual smart_device * autodetect_open();
///////////////////////////////////////////////
/*
const drive_settings builtin_knowndrives[] = {
*/
- { "$Id: drivedb.h 3538 2012-05-01 19:45:49Z chrfranke $",
+ { "$Id: drivedb.h 3559 2012-06-05 18:35:10Z chrfranke $",
"-", "-",
"This is a dummy entry to hold the SVN-Id of drivedb.h",
""
"KINGSTON SH100S3(120|240)G|" // Hyper-X, SF-2281, tested with SH100S3240G/320ABBF0
"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
"OCZ-REVODRIVE3?( X2)?|" // PCIe, SF-1200/2281, tested with
// OCZ-REVODRIVE( X2)?/1.20, OCZ-REVODRIVE3 X2/2.11
"OCZ[ -](VELO|VERTEX2[ -](EX|PRO))( [123]\\..*)?|" // SF-1500, tested with
"-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",
+ "", "",
+ //"-v 5,raw16(raw16),Reallocated_Sector_Ct "
+ "-v 9,msec24hour32,Power_On_Hours_and_Msec "
+ //"-v 12,raw48,Power_Cycle_Count "
+ //"-v 181,raw48,Program_Fail_Cnt_Total " // ] Missing in 330 specification from April 2012
+ //"-v 182,raw48,Erase_Fail_Count_Total " // ]
+ //"-v 192,raw48,Power-Off_Retract_Count "
+ "-v 225,raw48,Host_Writes_32MiB "
+ //"-v 232,raw48,Available_Reservd_Space "
+ //"-v 233,raw48,Media_Wearout_Indicator "
+ "-v 241,raw48,Host_Writes_32MiB "
+ "-v 242,raw48,Host_Reads_32MiB "
+ "-v 249,raw48,NAND_Writes_1GiB"
+ },
{ "Kingston branded X25-V SSDs", // fixed firmware
"KINGSTON SSDNow 40GB",
"2CV102(J[89A-Z]|[K-Z].)", // >= "2CV102J8"
// USB ID entries
////////////////////////////////////////////////////
+ // Hewlett-Packard
+ { "USB: HP Desktop HD BD07; ", // 2TB
+ "0x03f0:0xbd07",
+ "",
+ "",
+ "-d sat"
+ },
// ALi
{ "USB: ; ALi M5621", // USB->PATA
"0x0402:0x5621",
"-d usbsunplus"
},
// Iomega
+ { "USB: Iomega Prestige Desktop USB 3.0; ",
+ "0x059b:0x0070",
+ "", // 0x0004
+ "",
+ "-d sat" // ATA output registers missing
+ },
{ "USB: Iomega LPHD080-0; ",
"0x059b:0x0272",
"",
"0x067b:0x2507",
"",
"",
- "" // unsupported
+ "-d usbjmicron,0" // Port number is required
},
{ "USB: ; Prolific PL3507", // USB+IEE1394->PATA
"0x067b:0x3507",
"",
"-d sat"
},
+ { "USB: WD My Passport USB 3.0; ",
+ "0x1058:0x0748",
+ "",
+ "",
+ "-d sat"
+ },
{ "USB: WD My Book ES; ",
"0x1058:0x0906",
"", // 0x0012
"-d sat"
},
{ "USB: WD My Book Essential USB 3.0; ", // 3TB
- "0x1058:0x1130",
- "", // 0x1012
+ "0x1058:0x11[34]0",
+ "", // 0x1012/0x1003
"",
"-d sat"
},
"",
"-d usbsunplus"
},
+ // Unknown: 0x1f75
+ { "USB: Sharkoon SATA QuickDeck Pro; ", // USB 2.0/3.0
+ "0x1f75:0x0888",
+ "", // 0x0034
+ "",
+ "" // unsupported
+ },
// Hitachi/SimpleTech
{ "USB: Hitachi Touro Desk; JMicron", // 3TB
"0x4971:0x1011",
"",
"-d usbjmicron"
},
+ { "USB: Hitachi Touro Desk 3.0; ", // 2TB
+ "0x4971:0x1015",
+ "", // 0x0000
+ "",
+ "-d sat" // ATA output registers missing
+ },
{ "USB: Hitachi/SimpleTech; JMicron", // 1TB
"0x4971:0xce17",
"",
#define PATHINQ_SETTINGS_SIZE 128
#endif
-const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3525 2012-03-22 08:54:52Z samm2 $" \
+const char *os_XXXX_c_cvsid="$Id: os_freebsd.cpp 3542 2012-05-18 18:18:45Z 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
" smartctl -a --device=cciss,0 /dev/ciss0\n"
" (Prints all SMART information for first disk \n"
" on Common Interface for SCSI-3 Support driver)\n"
- " smartctl -a --device=areca,1 /dev/arcmsr0\n"
- " (Prints all SMART information for first disk \n"
+ " smartctl -a --device=areca,3/1 /dev/arcmsr0\n"
+ " (Prints all SMART information for 3rd disk in the 1st enclosure \n"
" on first ARECA RAID controller)\n"
;
public /*extends*/ freebsd_smart_device
{
public:
- freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum);
+ 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_device::freebsd_areca_device(smart_interface * intf, const char * dev_name, int disknum)
+freebsd_areca_device::freebsd_areca_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_disknum(disknum),
+ m_encnum(encnum)
{
- set_info().info_name = strprintf("%s [areca_%02d]", dev_name, disknum);
+ set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
}
// Areca RAID Controller
return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type");
}
- areca_packet[11] = m_disknum - 1; // drive number
+ 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++ )
#endif
// Areca?
disknum = n1 = n2 = -1;
- if (sscanf(type, "areca,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
- if (n2 != (int)strlen(type)) {
- set_err(EINVAL, "Option -d areca,N requires N to be a non-negative integer");
+ int encnum = 1;
+ if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
+ if (!(1 <= disknum && disknum <= 128)) {
+ set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
return 0;
}
- if (!(1 <= disknum && disknum <= 24)) {
- set_err(EINVAL, "Option -d areca,N (N=%d) must have 1 <= N <= 24", disknum);
+ if (!(1 <= encnum && encnum <= 8)) {
+ 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);
std::string freebsd_smart_interface::get_valid_custom_dev_types_str()
{
- return "3ware,N, hpt,L/M/N, cciss,N, areca,N"
+ return "3ware,N, hpt,L/M/N, cciss,N, areca,N/E"
#if FREEBSDVER > 800100
", atacam"
#endif
*
* Copyright (C) 2003-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
* Copyright (C) 2003-11 Doug Gilbert <dgilbert@interlog.com>
- * Copyright (C) 2008 Hank Wu <hank@areca.com.tw>
+ * Copyright (C) 2008-12 Hank Wu <hank@areca.com.tw>
* Copyright (C) 2008 Oliver Bock <brevilo@users.sourceforge.net>
- * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
* Copyright (C) 2008 Jordan Hargrave <jordan_hargrave@dell.com>
*
* Parts of this file are derived from code that was
#define ARGUSED(x) ((void)(x))
-const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3441 2011-10-12 17:22:15Z chrfranke $"
+const char * os_linux_cpp_cvsid = "$Id: os_linux.cpp 3558 2012-06-05 16:42:05Z chrfranke $"
OS_LINUX_H_CVSID;
" smartctl --all --device=hpt,1/1/3 /dev/sda\n"
" (Prints all SMART info for the SATA disk attached to the 3rd PMPort\n"
" of the 1st channel on the 1st HighPoint RAID controller)\n"
- " smartctl --all --device=areca,3 /dev/sg2\n"
- " (Prints all SMART info for 3rd ATA disk on Areca RAID controller)\n"
+ " smartctl --all --device=areca,3/1 /dev/sg2\n"
+ " (Prints all SMART info for 3rd ATA disk of the 1st enclosure\n"
+ " on Areca RAID controller)\n"
;
}
}
- if (io_hdr.info | SG_INFO_CHECK) { /* error or warning */
+ if (io_hdr.info & SG_INFO_CHECK) { /* error or warning */
int masked_driver_status = (LSCSI_DRIVER_MASK & io_hdr.driver_status);
if (0 != io_hdr.host_status) {
public /*extends*/ linux_smart_device
{
public:
- linux_areca_device(smart_interface * intf, const char * dev_name, int disknum);
+ 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_device::linux_areca_device(smart_interface * intf, const char * dev_name, int disknum)
+linux_areca_device::linux_areca_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_disknum(disknum),
+ m_encnum(encnum)
{
- set_info().info_name = strprintf("%s [areca_%02d]", dev_name, disknum);
+ set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
}
// Areca RAID Controller
return set_err(ENOTSUP, "DATA OUT not supported for this Areca controller type");
}
- areca_packet[11] = m_disknum - 1; // drive number
+ 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++ )
return 0;
}
-// Return true if STR starts with PREFIX.
-static inline bool str_starts_with(const char * str, const char * prefix)
-{
- return !strncmp(str, prefix, strlen(prefix));
-}
-
// Return kernel release as integer ("2.6.31" -> 206031)
static unsigned get_kernel_release()
{
// Areca?
disknum = n1 = n2 = -1;
- if (sscanf(type, "areca,%n%d%n", &n1, &disknum, &n2) == 1 || n1 == 6) {
- if (n2 != (int)strlen(type)) {
- set_err(EINVAL, "Option -d areca,N requires N to be a non-negative integer");
+ int encnum = 1;
+ if (sscanf(type, "areca,%n%d/%d%n", &n1, &disknum, &encnum, &n2) >= 1 || n1 == 6) {
+ if (!(1 <= disknum && disknum <= 128)) {
+ set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
return 0;
}
- if (!(1 <= disknum && disknum <= 24)) {
- set_err(EINVAL, "Option -d areca,N (N=%d) must have 1 <= N <= 24", disknum);
+ if (!(1 <= encnum && encnum <= 8)) {
+ 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);
+ return new linux_areca_device(this, name, disknum, encnum);
}
// Highpoint ?
std::string linux_smart_interface::get_valid_custom_dev_types_str()
{
- return "marvell, areca,N, 3ware,N, hpt,L/M/N, megaraid,N"
+ return "marvell, areca,N/E, 3ware,N, hpt,L/M/N, megaraid,N"
#ifdef HAVE_LINUX_CCISS_IOCTL_H
", cciss,N"
#endif
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2004-12 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
* it under the terms of the GNU General Public License as published by
#define SELECT_WIN_32_64(x32, x64) (x64)
#endif
-const char * os_win32_cpp_cvsid = "$Id: os_win32.cpp 3524 2012-03-21 22:19:31Z chrfranke $";
+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
};
+/////////////////////////////////////////////////////////////////////////////
+/// 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,
+ 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:
+ virtual bool open();
+
+ virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
+
+ bool arcmsr_ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out);
+
+private:
+ int m_disknum; ///< Disk number.
+ int m_encnum; ///< Enclosure number.
+};
+
+
//////////////////////////////////////////////////////////////////////
// Platform specific interfaces
virtual scsi_device * get_scsi_device(const char * name, const char * type);
virtual smart_device * autodetect_smart_device(const char * name);
+
+ virtual smart_device * get_custom_smart_device(const char * name, const char * type);
+
+ virtual std::string get_valid_custom_dev_types_str();
};
return 0;
}
+
+smart_device * winnt_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) {
+ if (!(1 <= disknum && disknum <= 128)) {
+ set_err(EINVAL, "Option -d areca,N/E (N=%d) must have 1 <= N <= 128", disknum);
+ return 0;
+ }
+ if (!(1 <= encnum && encnum <= 8)) {
+ set_err(EINVAL, "Option -d areca,N/E (E=%d) must have 1 <= E <= 8", encnum);
+ return 0;
+ }
+
+ name = skipdev(name);
+#define ARECA_MAX_CTLR_NUM 16
+ n1 = -1;
+ int ctlrindex = 0;
+ if (sscanf(name, "arcmsr%d%n", &ctlrindex, &n1) >= 1 && n1 == (int)strlen(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++) {
+ 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);
+ }
+ }
+ CloseHandle(fh);
+ }
+ }
+ set_err(ENOENT, "No Areca controller found");
+ }
+ else
+ set_err(EINVAL, "Option -d areca,N/E requires device name /dev/arcmsrX");
+ }
+
+ return 0;
+}
+
+std::string winnt_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 * dev = win_smart_interface::autodetect_smart_device(name);
" (Prints Attributes for physical drive 3 on 3ware 9000 RAID)\n"
" smartctl -A /dev/tw_cli/c0/p1\n"
" (Prints Attributes for 3ware controller 0, port 1 using tw_cli)\n"
+ " smartctl --all --device=areca,3/1 /dev/arcmsr0\n"
+ " (Prints all SMART info for 3rd ATA disk of the 1st enclosure\n"
+ " on 1st Areca RAID controller)\n"
"\n"
" ATA SMART access methods and ordering may be specified by modifiers\n"
" following the device name: /dev/hdX:[saicm], where\n"
/////////////////////////////////////////////////////////////////////////////
// USB ID detection using WMI
-// Return true if STR starts with PREFIX.
-static inline bool str_starts_with(const std::string & str, const char * prefix)
-{
- return !strncmp(str.c_str(), prefix, strlen(prefix));
-}
-
// Get USB ID for a physical drive number
static bool get_usb_id(int drive, unsigned short & vendor_id, unsigned short & product_id)
{
return true;
}
+// 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)
+{
+ int report = scsi_debugmode; // TODO
+
+ if (report > 0) {
+ 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);
+ }
+
+ SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER sb;
+ if (iop->cmnd_len > (int)sizeof(sb.spt.Cdb)) {
+ return EINVAL;
+ }
+
+ memset(&sb, 0, sizeof(sb));
+ sb.spt.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
+ //sb.spt.PathId = 0;
+ sb.spt.TargetId = 127;
+ //sb.spt.Lun = 0;
+ sb.spt.CdbLength = iop->cmnd_len;
+ memcpy(sb.spt.Cdb, iop->cmnd, iop->cmnd_len);
+ sb.spt.SenseInfoLength = sizeof(sb.ucSenseBuf);
+ sb.spt.SenseInfoOffset =
+ offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, ucSenseBuf);
+ sb.spt.TimeOutValue = (iop->timeout ? iop->timeout : 60);
+
+ bool direct = true;
+ switch (iop->dxfer_dir) {
+ case DXFER_NONE:
+ sb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
+ break;
+ case DXFER_FROM_DEVICE:
+ sb.spt.DataIn = SCSI_IOCTL_DATA_IN;
+ sb.spt.DataTransferLength = iop->dxfer_len;
+ sb.spt.DataBuffer = iop->dxferp;
+ // IOCTL_SCSI_PASS_THROUGH_DIRECT does not support single byte
+ // transfers (needed for SMART STATUS check of JMicron USB bridges)
+ if (sb.spt.DataTransferLength == 1)
+ direct = false;
+ break;
+ case DXFER_TO_DEVICE:
+ sb.spt.DataIn = SCSI_IOCTL_DATA_OUT;
+ sb.spt.DataTransferLength = iop->dxfer_len;
+ sb.spt.DataBuffer = iop->dxferp;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ long err = 0;
+ if (direct) {
+ DWORD num_out;
+ if (!DeviceIoControl(fd, IOCTL_SCSI_PASS_THROUGH_DIRECT,
+ &sb, sizeof(sb), &sb, sizeof(sb), &num_out, 0))
+ err = GetLastError();
+ }
+ else
+ err = scsi_pass_through_indirect(fd, &sb);
+
+ if (err)
+ {
+ return err;
+ }
+
+ iop->scsi_status = sb.spt.ScsiStatus;
+ if (SCSI_STATUS_CHECK_CONDITION & iop->scsi_status) {
+ int slen = sb.ucSenseBuf[7] + 8;
+
+ if (slen > (int)sizeof(sb.ucSenseBuf))
+ slen = sizeof(sb.ucSenseBuf);
+ if (slen > (int)iop->max_sense_len)
+ slen = iop->max_sense_len;
+ memcpy(iop->sensep, sb.ucSenseBuf, slen);
+ iop->resp_sense_len = slen;
+ if (report) {
+ if (report > 1) {
+ pout(" >>> Sense buffer, len=%d:\n", slen);
+ dStrHex(iop->sensep, slen , 1);
+ }
+ if ((iop->sensep[0] & 0x7f) > 0x71)
+ pout(" status=%x: [desc] sense_key=%x asc=%x ascq=%x\n",
+ iop->scsi_status, iop->sensep[1] & 0xf,
+ iop->sensep[2], iop->sensep[3]);
+ else
+ pout(" status=%x: sense_key=%x asc=%x ascq=%x\n",
+ iop->scsi_status, iop->sensep[2] & 0xf,
+ iop->sensep[12], iop->sensep[13]);
+ }
+ } else
+ iop->resp_sense_len = 0;
+
+ if ((iop->dxfer_len > 0) && (sb.spt.DataTransferLength > 0))
+ iop->resid = iop->dxfer_len - sb.spt.DataTransferLength;
+ else
+ iop->resid = 0;
+
+ 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 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");
+}
+
+#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)
+{
+ 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;
+
+ 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:
+ // 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;
+ }
+
+ cdb[1] = 0x01;
+ cdb[2] = 0xf0;
+
+ 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 = scsi_pass_through_direct(fd, &io_hdr);
+ 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;
+ }
+ }
+ }
+
+ // Deal with the different error cases
+ if ( arcmsr_cmd == ARCMSR_IOCTL_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 ( io_hdr.scsi_status )
+ {
+ pout("io_hdr.scsi_status with write buffer failed code = %x\n", io_hdr.scsi_status);
+ return -3;
+ }
+
+ if ( data )
+ {
+ memcpy(data, return_buff, total);
+ }
+
+ return total;
+}
+
+
+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)
+{
+ set_fh(fh);
+ set_info().info_name = strprintf("%s [areca_disk#%02d_enc#%02d]", dev_name, disknum, encnum);
+}
+
+bool win_areca_device::open()
+{
+ HANDLE hFh;
+
+ if( is_open() )
+ {
+ 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;
+ }
+
+ set_fh(hFh);
+ return true;
+}
+
+// Areca RAID Controller
+bool win_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 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 & 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] = 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_fh(), ARCMSR_IOCTL_CLEAR_RQBUFFER, NULL, 0);
+ if (expected==-3) {
+ return set_err(EIO);
+ }
+
+ 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);
+ }
+
+ // ----- 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 & 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 win_areca_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out)
+{
+#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) )
+ {
+ 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);
+
+ if(hmutex)
+ {
+ CloseHandle(hmutex);
+ }
+
+ if ( (HLOCAL)pSD )
+ {
+ LocalFree((HLOCAL)pSD);
+ }
+
+ return ok;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////////////
;
; Home page of code is: http://smartmontools.sourceforge.net
;
-; Copyright (C) 2006-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+; Copyright (C) 2006-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
; 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 3457 2011-10-20 16:36:47Z chrfranke $
+; $Id: installer.nsi 3545 2012-05-25 21:19:03Z chrfranke $
;
;--------------------------------------------------------------------
; Command line arguments:
-; makensis -DINPDIR=<input-dir> -DOUTFILE=<output-file> -DVERSTR=<version-string> installer.nsi
+; makensis -DINPDIR=<input-dir> -DINPDIR64=<input-dir-64-bit> \
+; -DOUTFILE=<output-file> -DVERSTR=<version-string> installer.nsi
!ifndef INPDIR
!define INPDIR "."
XPStyle on
InstallColors /windows
-InstallDir "$PROGRAMFILES\smartmontools"
-InstallDirRegKey HKLM "Software\smartmontools" "Install_Dir"
+; Set in .onInit
+;InstallDir "$PROGRAMFILES\smartmontools"
+;InstallDirRegKey HKLM "Software\smartmontools" "Install_Dir"
Var EDITOR
-Var UBCDDIR
+
+!ifdef INPDIR64
+ Var X64
+ Var INSTDIR32
+ Var INSTDIR64
+!endif
LicenseData "${INPDIR}\doc\COPYING.txt"
Page license
Page components
-Page directory SkipProgPath "" ""
-PageEx directory
- PageCallbacks SkipUBCDPath "" ""
- DirText "Setup will install the UBCD4Win plugin in the following folder."
- DirVar $UBCDDIR
-PageExEnd
+!ifdef INPDIR64
+ Page directory CheckX64
+!else
+ Page directory
+!endif
Page instfiles
UninstPage uninstConfirm
InstType "Full"
InstType "Extract files only"
InstType "Drive menu"
-InstType "UBCD4Win plugin"
;--------------------------------------------------------------------
; Sections
+!ifdef INPDIR64
+ Section "64-bit version (EXPERIMENTAL)" X64_SECTION
+ ; Handled in Function CheckX64
+ SectionEnd
+!endif
+
SectionGroup "!Program files"
+ !macro FileExe path option
+ !ifdef INPDIR64
+ ; Use dummy SetOutPath to control archive location of executables
+ StrCmp $X64 "" +5
+ Goto +2
+ SetOutPath "$INSTDIR\bin64"
+ File ${option} '${INPDIR64}\${path}'
+ GoTo +4
+ Goto +2
+ SetOutPath "$INSTDIR\bin"
+ File ${option} '${INPDIR}\${path}'
+ !else
+ File ${option} '${INPDIR}\${path}'
+ !endif
+ !macroend
+
Section "smartctl" SMARTCTL_SECTION
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
- File "${INPDIR}\bin\smartctl.exe"
+ !insertmacro FileExe "bin\smartctl.exe" ""
SectionEnd
StrCmp $0 "" nosrv
ExecWait "net stop smartd" $1
nosrv:
- File "${INPDIR}\bin\smartd.exe"
+ !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
File "${INPDIR}\doc\smartd.conf"
- IfFileExists "$WINDIR\system32\cmd.exe" 0 +2
- File /nonfatal "${INPDIR}\bin\syslogevt.exe"
+ IfFileExists "$WINDIR\system32\cmd.exe" 0 nosysl
+ !insertmacro FileExe "bin\syslogevt.exe" /nonfatal
+ nosysl:
; Restart service ?
StrCmp $1 "0" 0 +3
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
- File "${INPDIR}\bin\smartctl-nc.exe"
+ !insertmacro FileExe "bin\smartctl-nc.exe" ""
SectionEnd
File "${INPDIR}\doc\README.txt"
File "${INPDIR}\doc\TODO.txt"
File "${INPDIR}\doc\WARNINGS.txt"
- File "${INPDIR}\doc\checksums.txt"
+!ifdef INPDIR64
+ StrCmp $X64 "" +3
+ File "${INPDIR64}\doc\checksums64.txt"
+ GoTo +2
+ File "${INPDIR}\doc\checksums32.txt"
+!else
+ File "${INPDIR}\doc\checksums??.txt"
+!endif
File "${INPDIR}\doc\smartctl.8.html"
File "${INPDIR}\doc\smartctl.8.txt"
File "${INPDIR}\doc\smartd.8.html"
Section "Uninstaller" UNINST_SECTION
SectionIn 1
- AddSize 35
+ AddSize 40
CreateDirectory "$INSTDIR"
; runcmdu
IfFileExists "$INSTDIR\bin\smartctl.exe" 0 +2
- IfFileExists "$INSTDIR\bin\smartd.exe" 0 +4
+ IfFileExists "$INSTDIR\bin\smartd.exe" 0 noruncmd
SetOutPath "$INSTDIR\bin"
- File "${INPDIR}\bin\runcmdu.exe"
+ !insertmacro FileExe "bin\runcmdu.exe" ""
File "${INPDIR}\bin\runcmdu.exe.manifest"
+ noruncmd:
; smartctl
IfFileExists "$INSTDIR\bin\smartctl.exe" 0 noctl
SectionGroupEnd
-Section "UBCD4Win Plugin" UBCD_SECTION
-
- SectionIn 4
-
- SetOutPath "$UBCDDIR"
- DetailPrint "Create file: smartmontools.inf"
- FileOpen $0 "$UBCDDIR\smartmontools.inf" "w"
- FileWrite $0 '; smartmontools.inf$\r$\n; PE Builder v3 plug-in INF file$\r$\n'
- FileWrite $0 '; Created by smartmontools installer$\r$\n'
- FileWrite $0 '; http://smartmontools.sourceforge.net/$\r$\n$\r$\n'
- FileWrite $0 '[Version]$\r$\nSignature= "$$Windows NT$$"$\r$\n$\r$\n'
- FileWrite $0 '[PEBuilder]$\r$\nName="Disk -Diagnostic: smartmontools"$\r$\n'
- FileWrite $0 'Enable=1$\r$\nHelp="files\smartctl.8.html"$\r$\n$\r$\n'
- FileWrite $0 '[WinntDirectories]$\r$\na=Programs\smartmontools,2$\r$\n$\r$\n'
- FileWrite $0 '[SourceDisksFolders]$\r$\nfiles=a,,1$\r$\n$\r$\n'
- FileWrite $0 '[Append]$\r$\nnu2menu.xml, smartmontools_nu2menu.xml$\r$\n'
- FileClose $0
-
- DetailPrint "Create file: smartmontools_nu2menu.xml"
- FileOpen $0 "$UBCDDIR\smartmontools_nu2menu.xml" "w"
- FileWrite $0 '<!-- Nu2Menu entry for smartmontools -->$\r$\n<NU2MENU>$\r$\n'
- FileWrite $0 '$\t<MENU ID="Programs">$\r$\n$\t$\t<MITEM TYPE="POPUP" MENUID="Disk Tools">'
- FileWrite $0 'Disk Tools</MITEM>$\r$\n$\t</MENU>$\r$\n$\t<MENU ID="Disk Tools">$\r$\n'
- FileWrite $0 '$\t$\t<MITEM TYPE="POPUP" MENUID="Diagnostic">Diagnostic</MITEM>$\r$\n$\t</MENU>'
- FileWrite $0 '$\r$\n$\t<MENU ID="Diagnostic">$\r$\n$\t$\t<MITEM TYPE="ITEM" DISABLED="'
- FileWrite $0 '@Not(@FileExists(@GetProgramDrive()\Programs\smartmontools\smartctl.exe))" '
- FileWrite $0 'CMD="RUN" FUNC="cmd.exe /k cd /d @GetProgramDrive()\Programs\smartmontools&'
- FileWrite $0 'set PATH=@GetProgramDrive()\Programs\smartmontools;%PATH% ">'
- FileWrite $0 'smartctl</MITEM>$\r$\n$\t</MENU>$\r$\n</NU2MENU>$\r$\n'
- FileClose $0
-
- SetOutPath "$UBCDDIR\files"
- File "${INPDIR}\bin\smartctl.exe"
- File "${INPDIR}\bin\smartd.exe"
- File "${INPDIR}\doc\smartctl.8.html"
- File "${INPDIR}\doc\smartctl.8.txt"
- File "${INPDIR}\doc\smartd.8.html"
- File "${INPDIR}\doc\smartd.8.txt"
- File "${INPDIR}\doc\smartd.conf"
-
-SectionEnd
-
-
;--------------------------------------------------------------------
Section "Uninstall"
Delete "$INSTDIR\doc\README.txt"
Delete "$INSTDIR\doc\TODO.txt"
Delete "$INSTDIR\doc\WARNINGS.txt"
- Delete "$INSTDIR\doc\checksums.txt"
+ Delete "$INSTDIR\doc\checksums*.txt"
Delete "$INSTDIR\doc\smartctl.8.html"
Delete "$INSTDIR\doc\smartctl.8.txt"
Delete "$INSTDIR\doc\smartd.8.html"
;--------------------------------------------------------------------
; Functions
+!macro AdjustSectionSize section
+ SectionGetSize ${section} $0
+ IntOp $0 $0 / 2
+ SectionSetSize ${section} $0
+!macroend
+
Function .onInit
+ ; Set default install directories
+ StrCmp $INSTDIR "" 0 endinst ; /D=PATH option specified ?
+ ReadRegStr $INSTDIR HKLM "Software\smartmontools" "Install_Dir"
+ StrCmp $INSTDIR "" 0 endinst ; Already installed ?
+ StrCpy $INSTDIR "$PROGRAMFILES\smartmontools"
+!ifdef INPDIR64
+ StrCpy $INSTDIR32 $INSTDIR
+ StrCpy $INSTDIR64 "$PROGRAMFILES64\smartmontools"
+!endif
+ endinst:
+
+!ifdef INPDIR64
+ ; Sizes of binary sections include 32-bit and 64-bit executables
+ !insertmacro AdjustSectionSize ${SMARTCTL_SECTION}
+ !insertmacro AdjustSectionSize ${SMARTD_SECTION}
+ !insertmacro AdjustSectionSize ${SMARTCTL_NC_SECTION}
+!endif
+
; Use Notepad++ if installed
StrCpy $EDITOR "$PROGRAMFILES\Notepad++\notepad++.exe"
IfFileExists "$EDITOR" +2 0
StrCpy $EDITOR "notepad.exe"
- ; Get UBCD4Win install location
- ReadRegStr $0 HKLM "Software\UBCD4Win" "InstallPath"
- StrCmp $0 "" 0 +2
- StrCpy $0 "C:\UBCD4Win"
- StrCpy $UBCDDIR "$0\plugin\Disk\Diagnostic\smartmontools"
-
; Hide "Add install dir to PATH" on 9x/ME
IfFileExists "$WINDIR\system32\cmd.exe" +2 0
SectionSetText ${PATH_SECTION} ""
Call ParseCmdLine
FunctionEnd
+; Check x64 section and update INSTDIR accordingly
+
+!ifdef INPDIR64
+Function CheckX64
+ SectionGetFlags ${X64_SECTION} $0
+ IntOp $0 $0 & ${SF_SELECTED}
+ IntCmp $0 ${SF_SELECTED} x64
+ StrCpy $X64 ""
+ StrCmp $INSTDIR32 "" +3
+ StrCpy $INSTDIR $INSTDIR32
+ StrCpy $INSTDIR32 ""
+ Goto done
+ x64:
+ StrCpy $X64 "t"
+ StrCmp $INSTDIR64 "" +3
+ StrCpy $INSTDIR $INSTDIR64
+ StrCpy $INSTDIR64 ""
+ done:
+FunctionEnd
+!endif
+
; Command line parsing
!macro CheckCmdLineOption name section
StrCpy $allopts "$allopts,${name}"
Var /global nomatch
StrCpy $nomatch "t"
; turn sections on or off
+!ifdef INPDIR64
+ !insertmacro CheckCmdLineOption "x64" ${X64_SECTION}
+ Call CheckX64
+ StrCmp $opts "x64" 0 +2
+ Return ; leave sections unchanged if only "x64" is specified
+!endif
!insertmacro CheckCmdLineOption "smartctl" ${SMARTCTL_SECTION}
!insertmacro CheckCmdLineOption "smartd" ${SMARTD_SECTION}
!insertmacro CheckCmdLineOption "smartctlnc" ${SMARTCTL_NC_SECTION}
!insertmacro CheckCmdLineOption "drive3" ${DRIVE_3_SECTION}
!insertmacro CheckCmdLineOption "drive4" ${DRIVE_4_SECTION}
!insertmacro CheckCmdLineOption "drive5" ${DRIVE_5_SECTION}
- !insertmacro CheckCmdLineOption "ubcd" ${UBCD_SECTION}
StrCmp $opts "-" done
StrCmp $nomatch "" done
StrCpy $0 "$allopts,-" "" 1
done:
FunctionEnd
-; Directory page callbacks
-
-!macro CheckSection section
- SectionGetFlags ${section} $0
- IntOp $0 $0 & 1
- IntCmp $0 1 done
-!macroend
-
-Function SkipProgPath
- !insertmacro CheckSection ${SMARTCTL_SECTION}
- !insertmacro CheckSection ${SMARTCTL_NC_SECTION}
- !insertmacro CheckSection ${SMARTD_SECTION}
- !insertmacro CheckSection ${DRIVEDB_SECTION}
- !insertmacro CheckSection ${DOC_SECTION}
- !insertmacro CheckSection ${MENU_SECTION}
- !insertmacro CheckSection ${PATH_SECTION}
- !insertmacro CheckSection ${DRIVE_0_SECTION}
- !insertmacro CheckSection ${DRIVE_1_SECTION}
- !insertmacro CheckSection ${DRIVE_2_SECTION}
- !insertmacro CheckSection ${DRIVE_3_SECTION}
- !insertmacro CheckSection ${DRIVE_4_SECTION}
- !insertmacro CheckSection ${DRIVE_5_SECTION}
- Abort
-done:
-FunctionEnd
-
-Function SkipUBCDPath
- !insertmacro CheckSection ${UBCD_SECTION}
- Abort
-done:
-FunctionEnd
-
-
; Install runcmda.exe if missing
Function CheckRunCmdA
IfFileExists "$INSTDIR\bin\runcmda.exe" done 0
SetOutPath "$INSTDIR\bin"
- File "${INPDIR}\bin\runcmda.exe"
+ !insertmacro FileExe "bin\runcmda.exe" ""
File "${INPDIR}\bin\runcmda.exe.manifest"
done:
FunctionEnd
!endif
Function ShellLinkSetRunAs
+ ; Set archive location of $PLUGINSDIR
+ Goto +2
+ SetOutPath "$INSTDIR"
+
System::Store S ; push $0-$9, $R0-$R9
pop $9
; $0 = CoCreateInstance(CLSID_ShellLink, 0, CLSCTX_INPROC_SERVER, IID_IShellLink, &$1)
.ig
Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- $Id: smartctl.8.in 3530 2012-03-27 19:54:06Z chrfranke $
+ $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
Use the forms \fB/dev/disk[0\-9]\fP or equivalently \fBdisk[0\-9]\fP or equivalently
\fB/dev/rdisk[0\-9]\fP. Long forms are also available: please use \'\-h\' to see some
examples. Note that there is currently no Darwin SCSI support.
+
+Use the OS X SAT SMART Driver to access SMART data on SAT capable USB and
+Firewire devices (see INSTALL file).
.\" %ENDIF OS Darwin
.\" %IF OS FreeBSD
.IP \fBFREEBSD\fP: 9
to parse CLI or 3DM output from standard input or clipboard.
The option \'\-d 3ware,N\' is not necessary on Windows.
-[NEW EXPERIMENTAL SMARTCTL FEATURE] For disks behind Intel Matrix RAID
-driver use \fB"/dev/csmi[0\-9],N"\fP where N specifies the port behind
-the logical scsi controller "\\\\.\\Scsi[0\-9]:".
+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.
+
The prefix \fB"/dev/"\fP is optional.
.\" %ENDIF OS Windows Cygwin
.\" %IF OS Cygwin
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\'.
-If \'-d sat,auto\' is specified, device type SAT (for ATA/SATA disks) is
+[NEW EXPERIMENTAL SMARTCTL FEATURE] 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.
interface.
.\" %ENDIF OS FreeBSD Linux
-.\" %IF OS Linux FreeBSD
+.\" %IF OS FreeBSD Linux Windows Cygwin
.I areca,N
-\- [Linux and FreeBSD only] the device consists of one or more SATA disks connected to an
-Areca SATA RAID controller. The positive integer N (in the range from 1 to
-24 inclusive) denotes which disk on the controller is monitored.
-.\" %ENDIF OS Linux FreeBSD
+\- [FreeBSD, Linux, Windows and Cygwin only] the device consists of one or more SATA disks
+connected to an Areca SATA RAID controller. The positive integer N (in the range
+from 1 to 24 inclusive) denotes which disk on the controller is monitored.
+.\" %ENDIF OS FreeBSD Linux Windows Cygwin
.\" %IF OS Linux
On Linux use syntax such as:
.nf
\fBsmartctl \-a \-d areca,3 /dev/arcmsr2\fP
.fi
.\" %ENDIF OS FreeBSD
+.\" %IF OS Windows Cygwin
+[NEW EXPERIMENTAL SMARTCTL FEATURE] On Windows and Cygwin use syntax such as:
+.nf
+\fBsmartctl \-a \-d areca,2 /dev/arcmsr0\fP
+.fi
+.nf
+\fBsmartctl \-a \-d areca,3 /dev/arcmsr1\fP
+.fi
+.\" %ENDIF OS Windows Cygwin
+.\" %IF OS FreeBSD Linux Windows Cygwin
The first line above addresses the second disk on the first Areca RAID controller.
The second line addresses the third disk on the second Areca RAID
controller.
+.\" %ENDIF OS FreeBSD Linux Windows Cygwin
.\" %IF OS Linux
-To help identify the correct device on Linus, use the command:
+To help identify the correct device on Linux, use the command:
.nf
\fBcat /proc/scsi/sg/device_hdr /proc/scsi/sg/devices\fP
.fi
incorrect device is addressed, please read the warning/error messages
carefully. They should provide hints about what devices to use.
.\" %ENDIF OS Linux
+.\" %IF OS FreeBSD Linux Windows Cygwin
-.\" %IF OS Linux FreeBSD
Important: the Areca controller must have firmware version 1.46 or
later. Lower-numbered firmware versions will give (harmless) SCSI
error messages and no SMART information.
-.\" %ENDIF OS Linux FreeBSD
+.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.
+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.
+
+.\" %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
If ',error' is appended and the Extended Comprehensive SMART error
log is not supported, the Summary SMART self-test log is printed.
-Please note that some recent (e.g. Samsung) drives report errors only
-in the Extended Comprehensive SMART error log. The Summary SMART error
-log can be read but is always empty.
+Please note that recent drives may report errors only in the Extended
+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
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. Intel 320 and 710 Series SSDs).
+(e.g. Hitachi 7K3000, Intel 320, 330 and 710 Series SSDs, Crucial/Micron
+m4 SSDs).
.I sataphy[,reset]
\- [SATA only] prints values and descriptions of the SATA Phy Event
\fBWARNING: Only run subcommands documented by the vendor of the
device.\fP
-Example for Intel (X18\-M/X25\-M G2 and 320 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
.SH
SVN ID OF THIS PAGE:
-$Id: smartctl.8.in 3530 2012-03-27 19:54:06Z chrfranke $
+$Id: smartctl.8.in 3561 2012-06-05 19:49:31Z chrfranke $
.ig
Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-$Id: smartd.8.in 3529 2012-03-25 17:26:10Z chrfranke $
+$Id: smartd.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
.\" %ENDIF OS NetBSD OpenBSD
.\" %IF OS Solaris
.IP \fBSOLARIS:\fP 9
-Examine all entries \fB"/dev/rdsk/c?t?d?s?"\fP for IDE/ATA and SCSI disk
+Examine all entries \fB"/dev/rdsk/*s0"\fP for IDE/ATA and SCSI disk
devices, and entries \fB"/dev/rmt/*"\fP for SCSI tape devices.
.\" %ENDIF OS Solaris
.\" %IF OS Darwin
\fB"/dev/sdX"\fP) and all physical disks (\'ports\' \fB",N"\fP)
detected behind this controller. Same for a second controller if present.
-[NEW EXPERIMENTAL SMARTD FEATURE] If directive \'\-d csmi\' is specified,
-examine all entries \fB"/dev/csmi[0\-9],N"\fP for drives behind Intel
-Matrix RAID driver.
+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.
.\" %ENDIF OS Windows Cygwin
.\" %IF OS Cygwin
.IP \fBCYGWIN\fP: 9
.\" %IF OS Windows
(Windows: CONTROL\-Break).
-Windows only: The "debug" mode can be toggled by the command
+[Windows only] The "debug" mode can be toggled by the command
\fBsmartd sigusr2\fP. A new console for debug output is opened when
debug mode is enabled.
.\" %ENDIF OS Windows
.\" %IF OS Windows
.TP
.B \-\-service
-Windows only: Enables \fBsmartd\fP to run as a Windows service.
+[Windows only] Enables \fBsmartd\fP to run as a Windows service.
The option must be specified in the service command line as the first
argument. It should not be used from console.
See NOTES below for details.
excessive number of disks, or by lines in \fB /usr/local/etc/smartd.conf\fP that are too long.
Please report this problem to \fB smartmontools-support@lists.sourceforge.net\fP.
.TP
-.B 10
+.B 10:
An inconsistency was found in \fBsmartd\fP\'s internal data
structures. This should never happen. It must be due to either a
coding or compiler bug. \fIPlease\fP report such failures to
.SH
SVN ID OF THIS PAGE:
-$Id: smartd.8.in 3529 2012-03-25 17:26:10Z chrfranke $
+$Id: smartd.8.in 3561 2012-06-05 19:49:31Z chrfranke $
.ig
Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
-$Id: smartd.conf.5.in 3519 2012-03-06 20:01:44Z chrfranke $
+$Id: smartd.conf.5.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
In the absence of a configuration file
\fBsmartd\fP will try to open all available devices.
.\" %IF OS Linux
-Ubder linux will try to open the 20 ATA devices
+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].
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\'.
-If \'-d sat,auto\' is specified, device type SAT (for ATA/SATA disks) is
+[NEW EXPERIMENTAL SMARTD FEATURE] 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.
Please see the \fBsmartctl\fP(8) man page for further details.
.\" %ENDIF OS FreeBSD Linux
-.\" %IF OS Linux FreeBSD
+.\" %IF OS FreeBSD Linux Windows Cygwin
.I areca,N
-\- [Linux and FreeBSD only] the device consists of one or more SATA disks connected to an
-Areca SATA RAID controller. The positive integer N (in the range from 1 to
-24 inclusive) denotes which disk on the controller is monitored.
+\- [FreeBSD, Linux, Windows and Cygwin only] the device consists of one or more SATA disks
+connected to an Areca SATA RAID controller. The positive integer N (in the range
+from 1 to 24 inclusive) denotes which disk on the controller is monitored.
In log files and email messages this disk will be identifed as
areca_disk_XX with XX in the range from 01 to 24 inclusive.
Please see the \fBsmartctl\fP(8) man page for further details.
-.\" %ENDIF OS Linux FreeBSD
+.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.
+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.
+
+.\" %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
.\" %ENDIF OS Cygwin Windows
.I scterc,READTIME,WRITETIME
-\- [ATA only] [NEW EXPERIMENTAL SMARTD FEATURE] sets the SCT Error
-Recovery Control settings to the specified values (deciseconds)
-when \fBsmartd\fP starts up and has no further effect.
+\- [ATA only] sets the SCT Error Recovery Control settings to the specified
+values (deciseconds) when \fBsmartd\fP starts up and has no further effect.
Values of 0 disable the feature, other values less than 65 are probably
not supported. For RAID configurations, this is typically set to
70,70 deciseconds.
See the \fBsmartctl \-t select,[next|redo|cont]\fP options for
further info.
-[NEW EXPERIMENTAL SMARTD FEATURE] Some disks (e.g. WD) do not preserve
-the selective self test log accross power cycles. If state persistence
-(\'\-s\' option) is enabled, the last test span is preserved by smartd
-and used if (and only if) the selective self test log is empty.
+Some disks (e.g. WD) do not preserve the selective self test log accross
+power cycles. If state persistence (\'\-s\' option) is enabled, the last
+test span is preserved by smartd and used if (and only if) the selective
+self test log is empty.
.IP \fBMM\fP 4
is the month of the year, expressed with two decimal digits. The
.TP
.B \-p
[ATA only] Report anytime that a Prefail Attribute has changed
-its value since the last check, 30 minutes ago. [Please see the
+its value since the last check. [Please see the
.B smartctl \-A
command-line option.]
.TP
.B \-u
[ATA only] Report anytime that a Usage Attribute has changed its value
-since the last check, 30 minutes ago. [Please see the
+since the last check. [Please see the
.B smartctl \-A
command-line option.]
.TP
To track temperature changes of at least 2 degrees, use:
.nf
-\fB \-W 2
+.B \-W 2
.fi
To log informal messages on temperatures of at least 40 degrees, use:
.nf
-\fB \-W 0,40
+.B \-W 0,40
.fi
For warning messages/mails on temperatures of at least 45 degrees, use:
.nf
-\fB \-W 0,0,45
+.B \-W 0,0,45
.fi
To combine all of the above reports, use:
.nf
-\fB \-W 2,40,45
+.B \-W 2,40,45
.fi
For ATA devices, smartd interprets Attribute 194 as Temperature Celsius
.SH
SVN ID OF THIS PAGE:
-$Id: smartd.conf.5.in 3519 2012-03-06 20:01:44Z chrfranke $
+$Id: smartd.conf.5.in 3561 2012-06-05 19:49:31Z chrfranke $
After=syslog.target
[Service]
-EnvironmentFile=/usr/local/etc/sysconfig/smartmontools
+EnvironmentFile=-/usr/local/etc/sysconfig/smartmontools
ExecStart=/usr/local/sbin/smartd -n $smartd_opts
+ExecReload=/bin/kill -HUP $MAINPID
+StandardOutput=syslog
[Install]
WantedBy=multi-user.target
* Home page of code is: http://smartmontools.sourceforge.net
*
* Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
- * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
+ * Copyright (C) 2008-12 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
#ifndef UTILITY_H_
#define UTILITY_H_
-#define UTILITY_H_CVSID "$Id: utility.h 3475 2011-11-10 21:43:40Z chrfranke $"
+#define UTILITY_H_CVSID "$Id: utility.h 3558 2012-06-05 16:42:05Z chrfranke $"
#include <time.h>
#include <sys/types.h> // for regex.h (according to POSIX)
__attribute_format_printf(1, 2);
std::string vstrprintf(const char * fmt, va_list ap);
+// Return true if STR starts with PREFIX
+inline bool str_starts_with(const char * str, const char * prefix)
+ { return !strncmp(str, prefix, strlen(prefix)); }
+
+inline bool str_starts_with(const std::string & str, const char * prefix)
+ { return !strncmp(str.c_str(), prefix, strlen(prefix)); }
+
#ifndef HAVE_WORKING_SNPRINTF
// Substitute by safe replacement functions
int safe_snprintf(char *buf, int size, const char *fmt, ...)