File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / smartmontools / dev_legacy.cpp
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:32:16 2012 UTC (12 years, 3 months ago) by misho
Branches: smartmontools, elwix, MAIN
CVS tags: v6_2, v6_1p0, v6_1, v5_43, v5_42, HEAD
smartmontools

    1: /*
    2:  * dev_legacy.cpp
    3:  *
    4:  * Home page of code is: http://smartmontools.sourceforge.net
    5:  *
    6:  * Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net>
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify
    9:  * it under the terms of the GNU General Public License as published by
   10:  * the Free Software Foundation; either version 2, or (at your option)
   11:  * any later version.
   12:  *
   13:  * You should have received a copy of the GNU General Public License
   14:  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
   15:  *
   16:  */
   17: 
   18: #include "config.h"
   19: #include "int64.h"
   20: #include "utility.h"
   21: #include "atacmds.h"
   22: #include "scsicmds.h"
   23: #include "dev_interface.h"
   24: #include "dev_ata_cmd_set.h"
   25: 
   26: #include <errno.h>
   27: 
   28: const char * dev_legacy_cpp_cvsid = "$Id: dev_legacy.cpp,v 1.1.1.1 2012/02/21 16:32:16 misho Exp $"
   29:   DEV_INTERFACE_H_CVSID;
   30: 
   31: /////////////////////////////////////////////////////////////////////////////
   32: 
   33: // Legacy interface declarations (now commented out globally):
   34: 
   35: // from utility.h:
   36: int guess_device_type(const char * dev_name);
   37: int make_device_names (char ***devlist, const char* name);
   38: int deviceopen(const char *pathname, char *type);
   39: int deviceclose(int fd);
   40: 
   41: // from atacmds.h:
   42: int ata_command_interface(int device, smart_command_set command, int select, char *data);
   43: 
   44: // from scsicmds.h:
   45: int do_scsi_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report);
   46: 
   47: // from smartctl.h:
   48: void print_smartctl_examples();
   49: 
   50: /////////////////////////////////////////////////////////////////////////////
   51: 
   52: namespace os { // No need to publish anything, name provided for Doxygen
   53: 
   54: /////////////////////////////////////////////////////////////////////////////
   55: /// Implement shared open/close routines with old functions.
   56: 
   57: class legacy_smart_device
   58: : virtual public /*implements*/ smart_device
   59: {
   60: public:
   61:   explicit legacy_smart_device(const char * mode)
   62:     : smart_device(never_called),
   63:       m_fd(-1), m_mode(mode) { }
   64: 
   65:   virtual ~legacy_smart_device() throw();
   66: 
   67:   virtual bool is_open() const;
   68: 
   69:   virtual bool open();
   70: 
   71:   virtual bool close();
   72: 
   73: protected:
   74:   /// Return filedesc for derived classes.
   75:   int get_fd() const
   76:     { return m_fd; }
   77: 
   78: private:
   79:   int m_fd; ///< filedesc, -1 if not open.
   80:   const char * m_mode; ///< Mode string for deviceopen().
   81: };
   82: 
   83: 
   84: legacy_smart_device::~legacy_smart_device() throw()
   85: {
   86:   if (m_fd >= 0)
   87:     ::deviceclose(m_fd);
   88: }
   89: 
   90: bool legacy_smart_device::is_open() const
   91: {
   92:   return (m_fd >= 0);
   93: }
   94: 
   95: bool legacy_smart_device::open()
   96: {
   97:   m_fd = ::deviceopen(get_dev_name(), const_cast<char*>(m_mode));
   98:   if (m_fd < 0) {
   99:     set_err((errno==ENOENT || errno==ENOTDIR) ? ENODEV : errno);
  100:     return false;
  101:   }
  102:   return true;
  103: }
  104: 
  105: bool legacy_smart_device::close()
  106: {
  107:   int fd = m_fd; m_fd = -1;
  108:   if (::deviceclose(fd) < 0) {
  109:     set_err(errno);
  110:     return false;
  111:   }
  112:   return true;
  113: }
  114: 
  115: /////////////////////////////////////////////////////////////////////////////
  116: /// Implement standard ATA support with old functions
  117: 
  118: class legacy_ata_device
  119: : public /*implements*/ ata_device_with_command_set,
  120:   public /*extends*/ legacy_smart_device
  121: {
  122: public:
  123:   legacy_ata_device(smart_interface * intf, const char * dev_name, const char * req_type);
  124: 
  125: protected:
  126:   virtual int ata_command_interface(smart_command_set command, int select, char * data);
  127: };
  128: 
  129: legacy_ata_device::legacy_ata_device(smart_interface * intf, const char * dev_name, const char * req_type)
  130: : smart_device(intf, dev_name, "ata", req_type),
  131:   legacy_smart_device("ATA")
  132: {
  133: }
  134: 
  135: int legacy_ata_device::ata_command_interface(smart_command_set command, int select, char * data)
  136: {
  137:   return ::ata_command_interface(get_fd(), command, select, data);
  138: }
  139: 
  140: 
  141: /////////////////////////////////////////////////////////////////////////////
  142: /// Implement standard SCSI support with old functions
  143: 
  144: class legacy_scsi_device
  145: : public /*implements*/ scsi_device,
  146:   public /*extends*/ legacy_smart_device
  147: {
  148: public:
  149:   legacy_scsi_device(smart_interface * intf, const char * dev_name, const char * req_type);
  150: 
  151:   virtual smart_device * autodetect_open();
  152: 
  153:   virtual bool scsi_pass_through(scsi_cmnd_io * iop);
  154: };
  155: 
  156: legacy_scsi_device::legacy_scsi_device(smart_interface * intf,
  157:   const char * dev_name, const char * req_type)
  158: : smart_device(intf, dev_name, "scsi", req_type),
  159:   legacy_smart_device("SCSI")
  160: {
  161: }
  162: 
  163: bool legacy_scsi_device::scsi_pass_through(scsi_cmnd_io * iop)
  164: {
  165:   int status = ::do_scsi_cmnd_io(get_fd(), iop, scsi_debugmode);
  166:   if (status < 0) {
  167:       set_err(-status);
  168:       return false;
  169:   }
  170:   return true;
  171: }
  172: 
  173: 
  174: /////////////////////////////////////////////////////////////////////////////
  175: /// SCSI open with autodetection support
  176: 
  177: smart_device * legacy_scsi_device::autodetect_open()
  178: {
  179:   // Open device
  180:   if (!open())
  181:     return this;
  182: 
  183:   // No Autodetection if device type was specified by user
  184:   if (*get_req_type())
  185:     return this;
  186: 
  187:   // The code below is based on smartd.cpp:SCSIFilterKnown()
  188: 
  189:   // Get INQUIRY
  190:   unsigned char req_buff[64] = {0, };
  191:   int req_len = 36;
  192:   if (scsiStdInquiry(this, req_buff, req_len)) {
  193:     // Marvell controllers fail on a 36 bytes StdInquiry, but 64 suffices
  194:     // watch this spot ... other devices could lock up here
  195:     req_len = 64;
  196:     if (scsiStdInquiry(this, req_buff, req_len)) {
  197:       // device doesn't like INQUIRY commands
  198:       close();
  199:       set_err(EIO, "INQUIRY failed");
  200:       return this;
  201:     }
  202:   }
  203: 
  204:   int avail_len = req_buff[4] + 5;
  205:   int len = (avail_len < req_len ? avail_len : req_len);
  206:   if (len < 36)
  207:     return this;
  208: 
  209:   // Use INQUIRY to detect type
  210: 
  211:   // SAT or USB ?
  212:   {
  213:     smart_device * newdev = smi()->autodetect_sat_device(this, req_buff, len);
  214:     if (newdev)
  215:       // NOTE: 'this' is now owned by '*newdev'
  216:       return newdev;
  217:   }
  218: 
  219:   // Nothing special found
  220:   return this;
  221: }
  222: 
  223: 
  224: /////////////////////////////////////////////////////////////////////////////
  225: /// Implement platform interface with old functions.
  226: 
  227: class legacy_smart_interface
  228: : public /*implements*/ smart_interface
  229: {
  230: public:
  231:   virtual std::string get_app_examples(const char * appname);
  232: 
  233:   virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
  234:     const char * pattern = 0);
  235: 
  236: protected:
  237:   virtual ata_device * get_ata_device(const char * name, const char * type);
  238: 
  239:   virtual scsi_device * get_scsi_device(const char * name, const char * type);
  240: 
  241:   virtual smart_device * autodetect_smart_device(const char * name);
  242: };
  243: 
  244: 
  245: //////////////////////////////////////////////////////////////////////
  246: 
  247: std::string legacy_smart_interface::get_app_examples(const char * appname)
  248: {
  249:   if (!strcmp(appname, "smartctl"))
  250:     ::print_smartctl_examples(); // this prints to stdout ...
  251:   return ""; // ... so don't print again.
  252: }
  253: 
  254: ata_device * legacy_smart_interface::get_ata_device(const char * name, const char * type)
  255: {
  256:   return new legacy_ata_device(this, name, type);
  257: }
  258: 
  259: scsi_device * legacy_smart_interface::get_scsi_device(const char * name, const char * type)
  260: {
  261:   return new legacy_scsi_device(this, name, type);
  262: }
  263: 
  264: 
  265: smart_device * legacy_smart_interface::autodetect_smart_device(const char * name)
  266: {
  267:   switch (::guess_device_type(name)) {
  268:     case CONTROLLER_ATA : return new legacy_ata_device(this, name, "");
  269:     case CONTROLLER_SCSI: return new legacy_scsi_device(this, name, "");
  270:   }
  271:   // TODO: Test autodetect device here
  272:   return 0;
  273: }
  274: 
  275: 
  276: static void free_devnames(char * * devnames, int numdevs)
  277: {
  278:   static const char version[] = "$Id: dev_legacy.cpp,v 1.1.1.1 2012/02/21 16:32:16 misho Exp $";
  279:   for (int i = 0; i < numdevs; i++)
  280:     FreeNonZero(devnames[i], -1,__LINE__, version);
  281:   FreeNonZero(devnames, (sizeof (char*) * numdevs),__LINE__, version);
  282: }
  283: 
  284: bool legacy_smart_interface::scan_smart_devices(smart_device_list & devlist,
  285:   const char * type, const char * pattern /*= 0*/)
  286: {
  287:   if (pattern) {
  288:     set_err(EINVAL, "DEVICESCAN with pattern not implemented yet");
  289:     return false;
  290:   }
  291: 
  292:   // Make namelists
  293:   char * * atanames = 0; int numata = 0;
  294:   if (!type || !strcmp(type, "ata")) {
  295:     numata = ::make_device_names(&atanames, "ATA");
  296:     if (numata < 0) {
  297:       set_err(ENOMEM);
  298:       return false;
  299:     }
  300:   }
  301: 
  302:   char * * scsinames = 0; int numscsi = 0;
  303:   if (!type || !strcmp(type, "scsi")) {
  304:     numscsi = ::make_device_names(&scsinames, "SCSI");
  305:     if (numscsi < 0) {
  306:       free_devnames(atanames, numata);
  307:       set_err(ENOMEM);
  308:       return false;
  309:     }
  310:   }
  311: 
  312:   // Add to devlist
  313:   int i;
  314:   if (!type)
  315:     type="";
  316:   for (i = 0; i < numata; i++) {
  317:     ata_device * atadev = get_ata_device(atanames[i], type);
  318:     if (atadev)
  319:       devlist.push_back(atadev);
  320:   }
  321:   free_devnames(atanames, numata);
  322: 
  323:   for (i = 0; i < numscsi; i++) {
  324:     scsi_device * scsidev = get_scsi_device(scsinames[i], type);
  325:     if (scsidev)
  326:       devlist.push_back(scsidev);
  327:   }
  328:   free_devnames(scsinames, numscsi);
  329:   return true;
  330: }
  331: 
  332: } // namespace
  333: 
  334: 
  335: /////////////////////////////////////////////////////////////////////////////
  336: /// Initialize platform interface and register with smi()
  337: 
  338: void smart_interface::init()
  339: {
  340:   static os::legacy_smart_interface the_interface;
  341:   smart_interface::set(&the_interface);
  342: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>