diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 685131491b57eb9ca48e4300eb3288a963663c97..127448b82bfd8ae1a713b98894d37fd1e4b36d29 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.712 2008/08/23 15:38:20 chrfranke Exp $ +$Id: CHANGELOG,v 1.713 2008/08/23 17:07:16 chrfranke Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -39,6 +39,9 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [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 diff --git a/sm5/dev_ata_cmd_set.cpp b/sm5/dev_ata_cmd_set.cpp index 73bf83daeec22ac0db9b0683da2004a0502a6b08..aa0b4f8fee2b83328498aa08ded49ee326a39f49 100644 --- a/sm5/dev_ata_cmd_set.cpp +++ b/sm5/dev_ata_cmd_set.cpp @@ -22,7 +22,7 @@ #include <errno.h> -const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp,v 1.2 2008/08/16 16:49:15 chrfranke Exp $" +const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp,v 1.3 2008/08/23 17:07:16 chrfranke Exp $" DEV_ATA_CMD_SET_H_CVSID; @@ -31,10 +31,10 @@ const char * dev_ata_cmd_set_cpp_cvsid = "$Id: dev_ata_cmd_set.cpp,v 1.2 2008/08 // Adapter routine to implement new ATA pass through with old interface -bool ata_device_with_command_set::ata_pass_through_28bit(const ata_cmd_in & in, ata_cmd_out & out) +bool ata_device_with_command_set::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) { - if (!(in.size == 0 || in.size == 512)) - return set_err(ENOSYS, "Multi sector I/O not implemented"); + if (!ata_cmd_is_ok(in, true)) // data_out_support + return false; smart_command_set command = (smart_command_set)-1; int select = 0; diff --git a/sm5/dev_ata_cmd_set.h b/sm5/dev_ata_cmd_set.h index dfe963f4741a04811f573f53e52a3abd48faa3dc..8f73d267c3f09dc6c5a977509fc6684959e4491a 100644 --- a/sm5/dev_ata_cmd_set.h +++ b/sm5/dev_ata_cmd_set.h @@ -18,7 +18,7 @@ #ifndef DEV_ATA_CMD_SET_H #define DEV_ATA_CMD_SET_H -#define DEV_ATA_CMD_SET_H_CVSID "$Id: dev_ata_cmd_set.h,v 1.1 2008/07/25 21:16:00 chrfranke Exp $\n" +#define DEV_ATA_CMD_SET_H_CVSID "$Id: dev_ata_cmd_set.h,v 1.2 2008/08/23 17:07:16 chrfranke Exp $\n" #include "atacmds.h" // smart_command_set #include "dev_interface.h" @@ -32,10 +32,10 @@ class ata_device_with_command_set : public /*implements*/ ata_device { protected: - /// 28-bit ATA pass through mapped to ata_command_interface(). - virtual bool ata_pass_through_28bit(const ata_cmd_in & in, ata_cmd_out & out); + /// ATA pass through mapped to ata_command_interface(). + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); - /// Old ATA interface called by ata_pass_through_28bit. + /// Old ATA interface called by ata_pass_through() virtual int ata_command_interface(smart_command_set command, int select, char * data) = 0; ata_device_with_command_set() diff --git a/sm5/dev_interface.cpp b/sm5/dev_interface.cpp index 7d657d0a0c3c677fa827ce8d75ed1b8b174279b0..65417fb002612c66603079e6ff52f2519810a1ef 100644 --- a/sm5/dev_interface.cpp +++ b/sm5/dev_interface.cpp @@ -25,7 +25,7 @@ #include <stdexcept> -const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp,v 1.1 2008/07/25 21:16:00 chrfranke Exp $" +const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp,v 1.2 2008/08/23 17:07:16 chrfranke Exp $" DEV_INTERFACE_H_CVSID; ///////////////////////////////////////////////////////////////////////////// @@ -95,23 +95,48 @@ ata_cmd_out::ata_cmd_out() { } -bool ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) -{ - if (!in.in_regs.is_48bit_cmd()) - return ata_pass_through_28bit(in, out); - else - return ata_pass_through_48bit(in, out); -} - bool ata_device::ata_pass_through(const ata_cmd_in & in) { ata_cmd_out dummy; return ata_pass_through(in, dummy); } -bool ata_device::ata_pass_through_48bit(const ata_cmd_in & /*in*/, ata_cmd_out & /*out*/) +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*/) { - return set_err(ENOSYS, "48-bit ATA commands not supported"); + // Check DATA IN/OUT + switch (in.direction) { + case ata_cmd_in::no_data: break; + case ata_cmd_in::data_in: break; + case ata_cmd_in::data_out: break; + default: + return set_err(EINVAL, "Invalid data direction %d", (int)in.direction); + } + + // Check buffer size + if (in.direction == ata_cmd_in::no_data) { + if (in.size) + return set_err(EINVAL, "Buffer size %u > 0 for NO DATA command", in.size); + } + else { + if (!in.buffer) + return set_err(EINVAL, "Buffer not set for DATA IN/OUT command"); + unsigned count = (in.in_regs.prev.sector_count<<16)|in.in_regs.sector_count; + // TODO: Add check for sector count == 0 + if (count * 512 != in.size) + return set_err(EINVAL, "Sector count %u does not match buffer size %u", count, in.size); + } + + // 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"); + return true; } bool ata_device::ata_identify_is_cached() const diff --git a/sm5/dev_interface.h b/sm5/dev_interface.h index b1485baff3a82dc89125a8d4002e9bb9d691d76d..70cbcd9a109fb09d3a232d3df20f29b3be476a2b 100644 --- a/sm5/dev_interface.h +++ b/sm5/dev_interface.h @@ -18,7 +18,7 @@ #ifndef DEV_INTERFACE_H #define DEV_INTERFACE_H -#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h,v 1.3 2008/08/16 16:49:15 chrfranke Exp $\n" +#define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h,v 1.4 2008/08/23 17:07:16 chrfranke Exp $\n" #include <stdarg.h> #include <string> @@ -404,8 +404,8 @@ class ata_device public: /// ATA pass through. /// Return false on error. - /// Default implementation calls ata_pass_through_28bit or _48bit. - virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); + /// Must be implemented in derived class. + virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0; /// ATA pass through without output registers. /// Return false on error. @@ -417,13 +417,12 @@ public: virtual bool ata_identify_is_cached() const; protected: - /// 28-bit ATA pass through. - /// Must be implemented in derived class. - virtual bool ata_pass_through_28bit(const ata_cmd_in & in, ata_cmd_out & out) = 0; - - /// 48-bit ATA pass through. - /// Default implementation returns false and sets errno to ENOSYS. - virtual bool ata_pass_through_48bit(const ata_cmd_in & in, ata_cmd_out & out); + /// Check command input parameters. + /// Calls set_err(...) accordingly. + 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); /// Default constructor, registers device as ATA. ata_device() diff --git a/sm5/os_win32.cpp b/sm5/os_win32.cpp index 2e7310614294ca36f5f171510676aabd18046482..7d97b2ff7e511c4c31ea020630bfeab94aac4cee 100644 --- a/sm5/os_win32.cpp +++ b/sm5/os_win32.cpp @@ -48,7 +48,7 @@ extern smartmonctrl * con; // con->permissive,reportataioctl // Needed by '-V' option (CVS versioning) of smartd/smartctl -const char *os_XXXX_c_cvsid="$Id: os_win32.cpp,v 1.67 2008/08/20 21:19:08 chrfranke Exp $" +const char *os_XXXX_c_cvsid="$Id: os_win32.cpp,v 1.68 2008/08/23 17:07:16 chrfranke Exp $" ATACMDS_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID UTILITY_H_CVSID; @@ -106,9 +106,6 @@ public: virtual bool ata_identify_is_cached() const; -protected: - virtual bool ata_pass_through_28bit(const ata_cmd_in & in, ata_cmd_out & out); - private: bool open(int phydrive, int logdrive, const char * options, int port); @@ -2327,6 +2324,13 @@ bool winnt_smart_interface::ata_scan(smart_device_list & devlist) // Interface to ATA devices bool win_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 + ) + return false; + // Determine ioctl functions valid for this ATA cmd const char * valid_options = 0; @@ -2633,12 +2637,6 @@ bool win_ata_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) return true; } -// Dummy, never called because above implements 28-bit and 48-bit commands. -bool win_ata_device::ata_pass_through_28bit(const ata_cmd_in & /*in*/, ata_cmd_out & /*out*/) -{ - return set_err(ENOSYS); -} - // Return true if OS caches the ATA identify sector bool win_ata_device::ata_identify_is_cached() const { diff --git a/sm5/scsiata.cpp b/sm5/scsiata.cpp index e16935ecc5a5f18bd1b1a3fa0adb7ebc3d2c2a71..34f74d826fc37d3f2cb17aac019ffc51f1ca14c7 100644 --- a/sm5/scsiata.cpp +++ b/sm5/scsiata.cpp @@ -50,7 +50,7 @@ #include "dev_ata_cmd_set.h" // ata_device_with_command_set #include "dev_tunnelled.h" // tunnelled_device<> -const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.15 2008/08/16 16:49:16 chrfranke Exp $" +const char *scsiata_c_cvsid="$Id: scsiata.cpp,v 1.16 2008/08/23 17:07:17 chrfranke Exp $" CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIATA_H_CVSID UTILITY_H_CVSID; /* for passing global control variables */ @@ -78,9 +78,7 @@ public: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out); -protected: - virtual bool ata_pass_through_28bit(const ata_cmd_in & in, ata_cmd_out & out); - +private: int m_passthrulen; }; @@ -174,6 +172,13 @@ 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 + ) + return false; + struct scsi_cmnd_io io_hdr; struct scsi_sense_disect sinfo; struct sg_scsi_sense_hdr ssh; @@ -226,15 +231,6 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) extend = 1; } - // Check buffer size - if (t_length == 2) { - // TODO: Add this as utility member function to ata_in_regs - unsigned count = (in.in_regs.prev.sector_count<<16)|in.in_regs.sector_count; - // TODO: Add check for sector count == 0 - if (!(in.buffer && (count * 512 == in.size))) - return set_err(EINVAL, "sector_count %u does not match buffer size %u", count, in.size); - } - cdb[0] = (SAT_ATA_PASSTHROUGH_12LEN == passthru_size) ? SAT_ATA_PASSTHROUGH_12 : SAT_ATA_PASSTHROUGH_16; @@ -379,15 +375,6 @@ bool sat_device::ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) return true; } - -// Dummy, never called because above implements 28-bit and 48-bit commands. - -bool sat_device::ata_pass_through_28bit(const ata_cmd_in & /*in*/, ata_cmd_out & /*out*/) -{ - return set_err(ENOSYS); -} - - } // namespace /////////////////////////////////////////////////////////////////////////////