smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
dev_interface.cpp
Go to the documentation of this file.
00001 /*
00002  * dev_interface.cpp
00003  *
00004  * Home page of code is: http://smartmontools.sourceforge.net
00005  *
00006  * Copyright (C) 2008-13 Christian Franke <smartmontools-support@lists.sourceforge.net>
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012  *
00013  * You should have received a copy of the GNU General Public License
00014  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
00015  *
00016  */
00017 
00018 #include "config.h"
00019 #include "int64.h"
00020 #include "dev_interface.h"
00021 #include "dev_tunnelled.h"
00022 #include "atacmds.h" // ATA_SMART_CMD/STATUS
00023 #include "utility.h"
00024 
00025 #include <errno.h>
00026 #include <stdarg.h>
00027 #include <stdexcept>
00028 
00029 #if defined(HAVE_GETTIMEOFDAY)
00030 #include <sys/time.h>
00031 #elif defined(HAVE_FTIME)
00032 #include <sys/timeb.h>
00033 #endif
00034 
00035 const char * dev_interface_cpp_cvsid = "$Id: dev_interface.cpp 3741 2013-01-02 17:06:54Z chrfranke $"
00036   DEV_INTERFACE_H_CVSID;
00037 
00038 /////////////////////////////////////////////////////////////////////////////
00039 // smart_device
00040 
00041 smart_device::smart_device(smart_interface * intf, const char * dev_name,
00042     const char * dev_type, const char * req_type)
00043 : m_intf(intf), m_info(dev_name, dev_type, req_type),
00044   m_ata_ptr(0), m_scsi_ptr(0)
00045 {
00046 }
00047 
00048 smart_device::smart_device(do_not_use_in_implementation_classes)
00049 : m_intf(0), m_ata_ptr(0), m_scsi_ptr(0)
00050 {
00051   throw std::logic_error("smart_device: wrong constructor called in implementation class");
00052 }
00053 
00054 smart_device::~smart_device() throw()
00055 {
00056 }
00057 
00058 bool smart_device::is_syscall_unsup() const
00059 {
00060   if (get_errno() == ENOSYS)
00061     return true;
00062 #ifdef ENOTSUP
00063   if (get_errno() == ENOTSUP)
00064     return true;
00065 #endif
00066   return false;
00067 }
00068 
00069 bool smart_device::set_err(int no, const char * msg, ...)
00070 {
00071   if (!msg)
00072     return set_err(no);
00073   m_err.no = no;
00074   va_list ap; va_start(ap, msg);
00075   m_err.msg = vstrprintf(msg, ap);
00076   va_end(ap);
00077   return false;
00078 }
00079 
00080 bool smart_device::set_err(int no)
00081 {
00082   return smi()->set_err_var(&m_err, no);
00083 }
00084 
00085 smart_device * smart_device::autodetect_open()
00086 {
00087   open();
00088   return this;
00089 }
00090 
00091 bool smart_device::owns(const smart_device * /*dev*/) const
00092 {
00093   return false;
00094 }
00095 
00096 void smart_device::release(const smart_device * /*dev*/)
00097 {
00098 }
00099 
00100 
00101 /////////////////////////////////////////////////////////////////////////////
00102 // ata_device
00103 
00104 ata_in_regs_48bit::ata_in_regs_48bit()
00105 : features_16(features, prev.features),
00106   sector_count_16(sector_count, prev.sector_count),
00107   lba_low_16(lba_low, prev.lba_low),
00108   lba_mid_16(lba_mid, prev.lba_mid),
00109   lba_high_16(lba_high, prev.lba_high),
00110   lba_48(     lba_low,      lba_mid,      lba_high,
00111          prev.lba_low, prev.lba_mid, prev.lba_high)
00112 {
00113 }
00114 
00115 ata_out_regs_48bit::ata_out_regs_48bit()
00116 : sector_count_16(sector_count, prev.sector_count),
00117   lba_low_16(lba_low, prev.lba_low),
00118   lba_mid_16(lba_mid, prev.lba_mid),
00119   lba_high_16(lba_high, prev.lba_high),
00120   lba_48(     lba_low,      lba_mid,      lba_high,
00121          prev.lba_low, prev.lba_mid, prev.lba_high)
00122 {
00123 }
00124 
00125 ata_cmd_in::ata_cmd_in()
00126 : direction(no_data),
00127   buffer(0),
00128   size(0)
00129 {
00130 }
00131 
00132 ata_cmd_out::ata_cmd_out()
00133 {
00134 }
00135 
00136 bool ata_device::ata_pass_through(const ata_cmd_in & in)
00137 {
00138   ata_cmd_out dummy;
00139   return ata_pass_through(in, dummy);
00140 }
00141 
00142 bool ata_device::ata_cmd_is_supported(const ata_cmd_in & in,
00143   unsigned flags, const char * type /* = 0 */)
00144 {
00145   // Check DATA IN/OUT
00146   switch (in.direction) {
00147     case ata_cmd_in::no_data:  break;
00148     case ata_cmd_in::data_in:  break;
00149     case ata_cmd_in::data_out: break;
00150     default:
00151       return set_err(EINVAL, "Invalid data direction %d", (int)in.direction);
00152   }
00153 
00154   // Check buffer size
00155   if (in.direction == ata_cmd_in::no_data) {
00156     if (in.size)
00157       return set_err(EINVAL, "Buffer size %u > 0 for NO DATA command", in.size);
00158   }
00159   else {
00160     if (!in.buffer)
00161       return set_err(EINVAL, "Buffer not set for DATA IN/OUT command");
00162     unsigned count = (in.in_regs.prev.sector_count<<16)|in.in_regs.sector_count;
00163     // TODO: Add check for sector count == 0
00164     if (count * 512 != in.size)
00165       return set_err(EINVAL, "Sector count %u does not match buffer size %u", count, in.size);
00166   }
00167 
00168   // Check features
00169   const char * errmsg = 0;
00170   if (in.direction == ata_cmd_in::data_out && !(flags & supports_data_out))
00171     errmsg = "DATA OUT ATA commands not implemented";
00172   else if (   in.out_needed.is_set() && !(flags & supports_output_regs)
00173            && !(   in.in_regs.command == ATA_SMART_CMD
00174                 && in.in_regs.features == ATA_SMART_STATUS
00175                 && (flags & supports_smart_status)))
00176     errmsg = "Read of ATA output registers not implemented";
00177   else if (!(in.size == 0 || in.size == 512) && !(flags & supports_multi_sector))
00178     errmsg = "Multi-sector ATA commands not implemented";
00179   else if (in.in_regs.is_48bit_cmd() && !(flags & (supports_48bit_hi_null|supports_48bit)))
00180     errmsg = "48-bit ATA commands not implemented";
00181   else if (in.in_regs.is_real_48bit_cmd() && !(flags & supports_48bit))
00182     errmsg = "48-bit ATA commands not fully implemented";
00183 
00184   if (errmsg)
00185     return set_err(ENOSYS, "%s%s%s%s", errmsg,
00186                    (type ? " [" : ""), (type ? type : ""), (type ? "]" : ""));
00187 
00188   return true;
00189 }
00190 
00191 bool ata_device::ata_identify_is_cached() const
00192 {
00193   return false;
00194 }
00195 
00196 
00197 /////////////////////////////////////////////////////////////////////////////
00198 // tunnelled_device_base
00199 
00200 tunnelled_device_base::tunnelled_device_base(smart_device * tunnel_dev)
00201 : smart_device(never_called),
00202   m_tunnel_base_dev(tunnel_dev)
00203 {
00204 }
00205 
00206 tunnelled_device_base::~tunnelled_device_base() throw()
00207 {
00208   delete m_tunnel_base_dev;
00209 }
00210 
00211 bool tunnelled_device_base::is_open() const
00212 {
00213   return (m_tunnel_base_dev && m_tunnel_base_dev->is_open());
00214 }
00215 
00216 bool tunnelled_device_base::open()
00217 {
00218   if (!m_tunnel_base_dev)
00219     return set_err(ENOSYS);
00220   if (!m_tunnel_base_dev->open())
00221     return set_err(m_tunnel_base_dev->get_err());
00222   return true;
00223 }
00224 
00225 bool tunnelled_device_base::close()
00226 {
00227   if (!m_tunnel_base_dev)
00228     return true;
00229   if (!m_tunnel_base_dev->close())
00230     return set_err(m_tunnel_base_dev->get_err());
00231   return true;
00232 }
00233 
00234 bool tunnelled_device_base::owns(const smart_device * dev) const
00235 {
00236   return (m_tunnel_base_dev && (m_tunnel_base_dev == dev));
00237 }
00238 
00239 void tunnelled_device_base::release(const smart_device * dev)
00240 {
00241   if (m_tunnel_base_dev == dev)
00242     m_tunnel_base_dev = 0;
00243 }
00244 
00245 
00246 /////////////////////////////////////////////////////////////////////////////
00247 // smart_interface
00248 
00249 // Pointer to (usually singleton) interface object returned by ::smi()
00250 smart_interface * smart_interface::s_instance;
00251 
00252 std::string smart_interface::get_os_version_str()
00253 {
00254   return SMARTMONTOOLS_BUILD_HOST;
00255 }
00256 
00257 std::string smart_interface::get_valid_dev_types_str()
00258 {
00259   // default
00260   std::string s =
00261     "ata, scsi, sat[,auto][,N][+TYPE], usbcypress[,X], usbjmicron[,p][,x][,N], usbsunplus";
00262   // append custom
00263   std::string s2 = get_valid_custom_dev_types_str();
00264   if (!s2.empty()) {
00265     s += ", "; s += s2;
00266   }
00267   return s;
00268 }
00269 
00270 std::string smart_interface::get_app_examples(const char * /*appname*/)
00271 {
00272   return "";
00273 }
00274 
00275 int64_t smart_interface::get_timer_usec()
00276 {
00277 #if defined(HAVE_GETTIMEOFDAY)
00278  #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
00279   {
00280     static bool have_clock_monotonic = true;
00281     if (have_clock_monotonic) {
00282       struct timespec ts;
00283       if (!clock_gettime(CLOCK_MONOTONIC, &ts))
00284         return ts.tv_sec * 1000000LL + ts.tv_nsec/1000;
00285       have_clock_monotonic = false;
00286     }
00287   }
00288  #endif
00289   {
00290     struct timeval tv;
00291     gettimeofday(&tv, 0);
00292     return tv.tv_sec * 1000000LL + tv.tv_usec;
00293   }
00294 #elif defined(HAVE_FTIME)
00295   {
00296     struct timeb tb;
00297     ftime(&tb);
00298     return tb.time * 1000000LL + tb.millitm * 1000;
00299   }
00300 #else
00301   return -1;
00302 #endif
00303 }
00304 
00305 bool smart_interface::disable_system_auto_standby(bool /*disable*/)
00306 {
00307   return set_err(ENOSYS);
00308 }
00309 
00310 bool smart_interface::set_err(int no, const char * msg, ...)
00311 {
00312   if (!msg)
00313     return set_err(no);
00314   m_err.no = no;
00315   va_list ap; va_start(ap, msg);
00316   m_err.msg = vstrprintf(msg, ap);
00317   va_end(ap);
00318   return false;
00319 }
00320 
00321 bool smart_interface::set_err(int no)
00322 {
00323   return set_err_var(&m_err, no);
00324 }
00325 
00326 bool smart_interface::set_err_var(smart_device::error_info * err, int no)
00327 {
00328   err->no = no;
00329   err->msg = get_msg_for_errno(no);
00330   if (err->msg.empty() && no != 0)
00331     err->msg = strprintf("Unknown error %d", no);
00332   return false;
00333 }
00334 
00335 const char * smart_interface::get_msg_for_errno(int no)
00336 {
00337   return strerror(no);
00338 }
00339 
00340 
00341 /////////////////////////////////////////////////////////////////////////////
00342 // Default device factory
00343 
00344 smart_device * smart_interface::get_smart_device(const char * name, const char * type)
00345 {
00346   clear_err();
00347 
00348   // Call platform specific autodetection if no device type specified
00349   smart_device * dev;
00350   if (!type || !*type) {
00351     dev = autodetect_smart_device(name);
00352     if (!dev && !get_errno())
00353       set_err(EINVAL, "Unable to detect device type");
00354     return dev;
00355   }
00356 
00357   // First check for platform specific device types
00358   dev = get_custom_smart_device(name, type);
00359   if (dev || get_errno())
00360     return dev;
00361 
00362   if (!strcmp(type, "ata"))
00363     dev = get_ata_device(name, type);
00364   else if (!strcmp(type, "scsi"))
00365     dev = get_scsi_device(name, type);
00366 
00367   else if (  ((!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3])))
00368            || (!strncmp(type, "usb", 3)))) {
00369     // Split "sat...+base..." -> ("sat...", "base...")
00370     unsigned satlen = strcspn(type, "+");
00371     std::string sattype(type, satlen);
00372     const char * basetype = (type[satlen] ? type+satlen+1 : "");
00373     // Recurse to allocate base device, default is standard SCSI
00374     if (!*basetype)
00375       basetype = "scsi";
00376     smart_device_auto_ptr basedev( get_smart_device(name, basetype) );
00377     if (!basedev) {
00378       set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg());
00379       return 0;
00380     }
00381     // Result must be SCSI
00382     if (!basedev->is_scsi()) {
00383       set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype);
00384       return 0;
00385     }
00386     // Attach SAT tunnel
00387     ata_device * satdev = get_sat_device(sattype.c_str(), basedev->to_scsi());
00388     if (!satdev)
00389       return 0;
00390     basedev.release();
00391     return satdev;
00392   }
00393 
00394   else {
00395     set_err(EINVAL, "Unknown device type '%s'", type);
00396     return 0;
00397   }
00398   if (!dev && !get_errno())
00399     set_err(EINVAL, "Not a device of type '%s'", type);
00400   return dev;
00401 }
00402 
00403 smart_device * smart_interface::get_custom_smart_device(const char * /*name*/, const char * /*type*/)
00404 {
00405   return 0;
00406 }
00407 
00408 std::string smart_interface::get_valid_custom_dev_types_str()
00409 {
00410   return "";
00411 }