Annotation of embedaddon/smartmontools/dev_legacy.cpp, revision 1.1
1.1 ! misho 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 3263 2011-02-20 18:32:56Z chrfranke $"
! 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 3263 2011-02-20 18:32:56Z chrfranke $";
! 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>