smartmontools  SVN Rev 4631
Utility to control and monitor storage systems with "S.M.A.R.T."
dev_interface.h
Go to the documentation of this file.
1 /*
2  * dev_interface.h
3  *
4  * Home page of code is: http://www.smartmontools.org
5  *
6  * Copyright (C) 2008-16 Christian Franke
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 #ifndef DEV_INTERFACE_H
19 #define DEV_INTERFACE_H
20 
21 #define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 4283 2016-04-10 12:55:59Z chrfranke $\n"
22 
23 #include "utility.h"
24 
25 #include <stdexcept>
26 #include <string>
27 #include <vector>
28 
29 /////////////////////////////////////////////////////////////////////////////
30 // Common functionality for all device types
31 
32 // Forward declarations
33 class smart_interface;
34 class ata_device;
35 class scsi_device;
36 class nvme_device;
37 
38 /// Base class for all devices
40 {
41 // Types
42 public:
43  /// Device info strings
44  struct device_info {
46  { }
47  device_info(const char * d_name, const char * d_type, const char * r_type)
48  : dev_name(d_name), info_name(d_name),
49  dev_type(d_type), req_type(r_type)
50  { }
51 
52  std::string dev_name; ///< Device (path)name
53  std::string info_name; ///< Informal name
54  std::string dev_type; ///< Actual device type
55  std::string req_type; ///< Device type requested by user, empty if none
56  };
57 
58  /// Error (number,message) pair
59  struct error_info {
60  explicit error_info(int n = 0)
61  : no(n) { }
62  error_info(int n, const char * m)
63  : no(n), msg(m) { }
64  void clear()
65  { no = 0; msg.erase(); }
66 
67  int no; ///< Error number
68  std::string msg; ///< Error message
69  };
70 
71 // Construction
72 protected:
73  /// Constructor to init interface and device info.
74  /// Must be called in implementation classes.
75  smart_device(smart_interface * intf, const char * dev_name,
76  const char * dev_type, const char * req_type);
77 
78  /// Dummy enum for dummy constructor.
80  /// Dummy constructor for abstract classes.
81  /// Must never be called in implementation classes.
83 
84 public:
85  virtual ~smart_device() throw();
86 
87 // Attributes
88 public:
89  ///////////////////////////////////////////////
90  // Dynamic downcasts to actual device flavor
91 
92  /// Return true if ATA device
93  bool is_ata() const
94  { return !!m_ata_ptr; }
95  /// Return true if SCSI device
96  bool is_scsi() const
97  { return !!m_scsi_ptr; }
98  /// Return true if NVMe device
99  bool is_nvme() const
100  { return !!m_nvme_ptr; }
101 
102  /// Downcast to ATA device.
104  { return m_ata_ptr; }
105  /// Downcast to ATA device (const).
106  const ata_device * to_ata() const
107  { return m_ata_ptr; }
108  /// Downcast to SCSI device.
110  { return m_scsi_ptr; }
111  /// Downcast to SCSI device (const).
112  const scsi_device * to_scsi() const
113  { return m_scsi_ptr; }
114  /// Downcast to NVMe device.
116  { return m_nvme_ptr; }
117  /// Downcast to NVMe device (const).
118  const nvme_device * to_nvme() const
119  { return m_nvme_ptr; }
120 
121  ///////////////////////////////////////////////
122  // Device information
123 
124  /// Get device info struct.
125  const device_info & get_info() const
126  { return m_info; }
127 
128  /// Get device (path)name.
129  const char * get_dev_name() const
130  { return m_info.dev_name.c_str(); }
131  /// Get informal name.
132  const char * get_info_name() const
133  { return m_info.info_name.c_str(); }
134  /// Get device type.
135  const char * get_dev_type() const
136  { return m_info.dev_type.c_str(); }
137  /// Get type requested by user, empty if none.
138  const char * get_req_type() const
139  { return m_info.req_type.c_str(); }
140 
141 protected:
142  /// R/W access to device info struct.
144  { return m_info; }
145 
146 public:
147  ///////////////////////////////////////////////
148  // Last error information
149 
150  /// Get last error info struct.
151  const error_info & get_err() const
152  { return m_err; }
153  /// Get last error number.
154  int get_errno() const
155  { return m_err.no; }
156  /// Get last error message.
157  const char * get_errmsg() const
158  { return m_err.msg.c_str(); }
159 
160  /// Return true if last error indicates an unsupported system call.
161  /// Default implementation returns true on ENOSYS and ENOTSUP.
162  virtual bool is_syscall_unsup() const;
163 
164  /// Set last error number and message.
165  /// Printf()-like formatting is supported.
166  /// Returns false always to allow use as a return expression.
167  bool set_err(int no, const char * msg, ...)
169 
170  /// Set last error info struct.
171  bool set_err(const error_info & err)
172  { m_err = err; return false; }
173 
174  /// Clear last error info.
175  void clear_err()
176  { m_err.clear(); }
177 
178  /// Set last error number and default message.
179  /// Message is retrieved from interface's get_msg_for_errno(no).
180  bool set_err(int no);
181 
182  /// Get current number of allocated 'smart_device' objects.
183  static int get_num_objects()
184  { return s_num_objects; }
185 
186 // Operations
187 public:
188  ///////////////////////////////////////////////
189  // Device open/close
190  // Must be implemented in derived class
191 
192  /// Return true if device is open.
193  virtual bool is_open() const = 0;
194 
195  /// Open device, return false on error.
196  virtual bool open() = 0;
197 
198  /// Close device, return false on error.
199  virtual bool close() = 0;
200 
201  /// Open device with autodetection support.
202  /// May return another device for further access.
203  /// In this case, the original pointer is no longer valid.
204  /// Default implementation calls 'open()' and returns 'this'.
205  virtual smart_device * autodetect_open();
206 
207  ///////////////////////////////////////////////
208  // Support for checking power mode reported by operating system
209 
210  /// Early test if device is powered up or down.
211  /// Can be used without calling 'open()' first!
212  /// Return true when device is powered down, false when
213  /// powered up. If this function is not implemented or
214  /// the mode cannot be determined, return false.
215  /// Default implementation returns false.
216  virtual bool is_powered_down();
217 
218  ///////////////////////////////////////////////
219  // Support for tunnelled devices
220 
221  /// Return true if other device is owned by this device.
222  /// Default implementation returns false.
223  virtual bool owns(const smart_device * dev) const;
224 
225  /// Release ownership of other device.
226  /// Default implementation does nothing.
227  virtual void release(const smart_device * dev);
228 
229 protected:
230  /// Get interface which produced this object.
232  { return m_intf; }
233  /// Get interface which produced this object (const).
234  const smart_interface * smi() const
235  { return m_intf; }
236 
237 // Implementation
238 private:
242 
243  // Pointers for to_ata(), to_scsi(), to_nvme()
244  // set by ATA/SCSI/NVMe interface classes.
245  friend class ata_device;
247  friend class scsi_device;
249  friend class nvme_device;
251 
252  // Number of objects.
253  static int s_num_objects;
254 
255  // Prevent copy/assigment
256  smart_device(const smart_device &);
257  void operator=(const smart_device &);
258 };
259 
260 
261 /////////////////////////////////////////////////////////////////////////////
262 // ATA specific interface
263 
264 /// ATA register value and info whether it has ever been set
265 // (Automatically set by first assignment)
267 {
268 public:
270  : m_val(0x00), m_is_set(false) { }
271 
272  ata_register & operator=(unsigned char x)
273  { m_val = x; m_is_set = true; return * this; }
274 
275  unsigned char val() const
276  { return m_val; }
277  operator unsigned char() const
278  { return m_val; }
279 
280  bool is_set() const
281  { return m_is_set; }
282 
283 private:
284  unsigned char m_val; ///< Register value
285  bool m_is_set; ///< true if set
286 };
287 
288 /// ATA Input registers (for 28-bit commands)
290 {
291  // ATA-6/7 register names // ATA-3/4/5 // ATA-8
292  ata_register features; // features // features
293  ata_register sector_count; // sector count // count
294  ata_register lba_low; // sector number // ]
295  ata_register lba_mid; // cylinder low // ] lba
296  ata_register lba_high; // cylinder high // ]
297  ata_register device; // device/head // device
298  ata_register command; // command // command
299 
300  /// Return true if any register is set
301  bool is_set() const
302  { return (features.is_set() || sector_count.is_set()
303  || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
304  || device.is_set() || command.is_set()); }
305 };
306 
307 /// ATA Output registers (for 28-bit commands)
309 {
317 
318  /// Return true if any register is set
319  bool is_set() const
320  { return (error.is_set() || sector_count.is_set()
321  || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
322  || device.is_set() || status.is_set()); }
323 };
324 
325 
326 /// 16-bit alias to a 8-bit ATA register pair.
328 {
329 public:
331  : m_lo(lo), m_hi(hi) { }
332 
333  ata_reg_alias_16 & operator=(unsigned short x)
334  { m_lo = (unsigned char) x;
335  m_hi = (unsigned char)(x >> 8);
336  return * this; }
337 
338  unsigned short val() const
339  { return m_lo | (m_hi << 8); }
340  operator unsigned short() const
341  { return m_lo | (m_hi << 8); }
342 
343 private:
345 
346  // References must not be copied.
348  void operator=(const ata_reg_alias_16 &);
349 };
350 
351 
352 /// 48-bit alias to six 8-bit ATA registers (for LBA).
354 {
355 public:
357  ata_register & hl, ata_register & hm, ata_register & hh)
358  : m_ll(ll), m_lm(lm), m_lh(lh),
359  m_hl(hl), m_hm(hm), m_hh(hh)
360  { }
361 
363  {
364  m_ll = (unsigned char) x;
365  m_lm = (unsigned char)(x >> 8);
366  m_lh = (unsigned char)(x >> 16);
367  m_hl = (unsigned char)(x >> 24);
368  m_hm = (unsigned char)(x >> 32);
369  m_hh = (unsigned char)(x >> 40);
370  return * this;
371  }
372 
373  uint64_t val() const
374  {
375  return ( (unsigned)m_ll
376  | ((unsigned)m_lm << 8)
377  | ((unsigned)m_lh << 16)
378  | ((unsigned)m_hl << 24)
379  | ((uint64_t)m_hm << 32)
380  | ((uint64_t)m_hh << 40));
381  }
382 
383  operator uint64_t() const
384  { return val(); }
385 
386 private:
388  & m_hl, & m_hm, & m_hh;
389 
390  // References must not be copied.
392  void operator=(const ata_reg_alias_48 &);
393 };
394 
395 
396 /// ATA Input registers for 48-bit commands
397 // See section 4.14 of T13/1532D Volume 1 Revision 4b
398 //
399 // Uses ATA-6/7 method to specify 16-bit registers as
400 // recent (low byte) and previous (high byte) content of
401 // 8-bit registers.
402 //
403 // (ATA-8 ACS does not longer follow this scheme, it uses
404 // abstract registers with sufficient size and leaves the
405 // actual mapping to the transport layer.)
406 //
408 : public ata_in_regs // "most recently written" registers
409 {
410  ata_in_regs prev; ///< "previous content"
411 
412  // 16-bit aliases for above pair.
418 
419  // 48-bit alias to all 8-bit LBA registers.
421 
422  /// Return true if 48-bit command
423  bool is_48bit_cmd() const
424  { return prev.is_set(); }
425 
426  /// Return true if 48-bit command with any nonzero high byte
427  bool is_real_48bit_cmd() const
428  { return ( prev.features || prev.sector_count
429  || prev.lba_low || prev.lba_mid || prev.lba_high); }
430 
432 };
433 
434 
435 /// ATA Output registers for 48-bit commands
437 : public ata_out_regs // read with HOB=0
438 {
439  ata_out_regs prev; ///< read with HOB=1
440 
441  // 16-bit aliases for above pair.
446 
447  // 48-bit alias to all 8-bit LBA registers.
449 
451 };
452 
453 
454 /// Flags for each ATA output register
456 {
458 
459  /// Return true if any flag is set.
460  bool is_set() const
461  { return ( error || sector_count || lba_low
462  || lba_mid || lba_high || device || status); }
463 
464  /// Default constructor clears all flags.
466  : error(false), sector_count(false), lba_low(false), lba_mid(false),
467  lba_high(false), device(false), status(false) { }
468 };
469 
470 
471 /// ATA pass through input parameters
473 {
474  ata_in_regs_48bit in_regs; ///< Input registers
475  ata_out_regs_flags out_needed; ///< True if output register value needed
476  enum { no_data = 0, data_in, data_out } direction; ///< I/O direction
477  void * buffer; ///< Pointer to data buffer
478  unsigned size; ///< Size of buffer
479 
480  /// Prepare for 28-bit DATA IN command
481  void set_data_in(void * buf, unsigned nsectors)
482  {
483  buffer = buf;
484  in_regs.sector_count = nsectors;
485  direction = data_in;
486  size = nsectors * 512;
487  }
488 
489  /// Prepare for 28-bit DATA OUT command
490  void set_data_out(const void * buf, unsigned nsectors)
491  {
492  buffer = const_cast<void *>(buf);
493  in_regs.sector_count = nsectors;
495  size = nsectors * 512;
496  }
497 
498  /// Prepare for 48-bit DATA IN command
499  void set_data_in_48bit(void * buf, unsigned nsectors)
500  {
501  buffer = buf;
502  // Note: This also sets 'in_regs.is_48bit_cmd()'
503  in_regs.sector_count_16 = nsectors;
504  direction = data_in;
505  size = nsectors * 512;
506  }
507 
508  ata_cmd_in();
509 };
510 
511 /// ATA pass through output parameters
513 {
514  ata_out_regs_48bit out_regs; ///< Output registers
515 
516  ata_cmd_out();
517 };
518 
519 /// ATA device access
521 : virtual public /*extends*/ smart_device
522 {
523 public:
524  /// ATA pass through.
525  /// Return false on error.
526  /// Must be implemented in derived class.
527  virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0;
528 
529  /// ATA pass through without output registers.
530  /// Return false on error.
531  /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
532  bool ata_pass_through(const ata_cmd_in & in);
533 
534  /// Return true if OS caches ATA identify sector.
535  /// Default implementation returns false.
536  virtual bool ata_identify_is_cached() const;
537 
538 protected:
539  /// Flags for ata_cmd_is_supported().
540  enum {
541  supports_data_out = 0x01, // PIO DATA OUT
542  supports_smart_status = 0x02, // read output registers for SMART STATUS only
543  supports_output_regs = 0x04, // read output registers for all commands
544  supports_multi_sector = 0x08, // more than one sector (1 DRQ/sector variant)
545  supports_48bit_hi_null = 0x10, // 48-bit commands with null high bytes only
546  supports_48bit = 0x20, // all 48-bit commands
547  };
548 
549  /// Check command input parameters.
550  /// Return false if required features are not implemented.
551  /// Calls set_err(...) accordingly.
552  bool ata_cmd_is_supported(const ata_cmd_in & in, unsigned flags,
553  const char * type = 0);
554 
555  /// Check command input parameters (old version).
556  // TODO: Remove if no longer used.
557  bool ata_cmd_is_ok(const ata_cmd_in & in,
558  bool data_out_support = false,
559  bool multi_sector_support = false,
560  bool ata_48bit_support = false)
561  {
562  return ata_cmd_is_supported(in,
563  (data_out_support ? supports_data_out : 0) |
565  (multi_sector_support ? supports_multi_sector : 0) |
566  (ata_48bit_support ? supports_48bit : 0));
567  }
568 
569  /// Hide/unhide ATA interface.
570  void hide_ata(bool hide = true)
571  { m_ata_ptr = (!hide ? this : 0); }
572 
573  /// Default constructor, registers device as ATA.
576  { hide_ata(false); }
577 };
578 
579 
580 /////////////////////////////////////////////////////////////////////////////
581 // SCSI specific interface
582 
583 struct scsi_cmnd_io;
584 
585 /// SCSI device access
587 : virtual public /*extends*/ smart_device
588 {
589 public:
590  /// SCSI pass through.
591  /// Returns false on error.
592  virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
593 
594 protected:
595  /// Hide/unhide SCSI interface.
596  void hide_scsi(bool hide = true)
597  { m_scsi_ptr = (!hide ? this : 0); }
598 
599  /// Default constructor, registers device as SCSI.
602  { hide_scsi(false); }
603 };
604 
605 
606 /////////////////////////////////////////////////////////////////////////////
607 // NVMe specific interface
608 
609 /// NVMe pass through input parameters
611 {
612  unsigned char opcode; ///< Opcode (CDW0 07:00)
613  unsigned nsid; ///< Namespace ID
614  unsigned cdw10, cdw11, cdw12, cdw13, cdw14, cdw15; ///< Cmd specific
615 
616  void * buffer; ///< Pointer to data buffer
617  unsigned size; ///< Size of buffer
618 
619  enum {
620  no_data = 0x0, data_out = 0x1, data_in = 0x2, data_io = 0x3
621  };
622 
623  /// Get I/O direction from opcode
624  unsigned char direction() const
625  { return (opcode & 0x3); }
626 
627  // Prepare for DATA IN command
628  void set_data_in(unsigned char op, void * buf, unsigned sz)
629  {
630  opcode = op;
631  if (direction() != data_in)
632  throw std::logic_error("invalid opcode for DATA IN");
633  buffer = buf;
634  size = sz;
635  }
636 
638  : opcode(0), nsid(0),
639  cdw10(0), cdw11(0), cdw12(0), cdw13(0), cdw14(0), cdw15(0),
640  buffer(0), size(0)
641  { }
642 };
643 
644 /// NVMe pass through output parameters
646 {
647  unsigned result; ///< Command specific result (DW0)
648  unsigned short status; ///< Status Field (DW3 31:17)
649  bool status_valid; ///< true if status is valid
650 
652  : result(0), status(0), status_valid(false)
653  { }
654 };
655 
656 /// NVMe device access
658 : virtual public /*extends*/ smart_device
659 {
660 public:
661  /// NVMe pass through.
662  /// Return false on error.
663  virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) = 0;
664 
665  /// Get namespace id.
666  unsigned get_nsid() const
667  { return m_nsid; }
668 
669 protected:
670  /// Hide/unhide NVMe interface.
671  void hide_nvme(bool hide = true)
672  { m_nvme_ptr = (!hide ? this : 0); }
673 
674  /// Constructor requires namespace ID, registers device as NVMe.
675  explicit nvme_device(unsigned nsid)
677  m_nsid(nsid)
678  { hide_nvme(false); }
679 
680  /// Set namespace id.
681  /// Should be called in open() function if get_nsid() returns 0.
682  void set_nsid(unsigned nsid)
683  { m_nsid = nsid; }
684 
685  /// Set last error number and message if pass-through returns NVMe error status.
686  /// Returns false always to allow use as a return expression.
687  bool set_nvme_err(nvme_cmd_out & out, unsigned status, const char * msg = 0);
688 
689 private:
690  unsigned m_nsid;
691 };
692 
693 
694 /////////////////////////////////////////////////////////////////////////////
695 /// Smart pointer class for device pointers
696 
697 template <class Dev>
699 {
700 public:
701  typedef Dev device_type;
702 
703  /// Construct from optional pointer to device
704  /// and optional pointer to base device.
705  explicit any_device_auto_ptr(device_type * dev = 0,
706  smart_device * base_dev = 0)
707  : m_dev(dev), m_base_dev(base_dev) { }
708 
709  /// Destructor deletes device object.
711  { reset(); }
712 
713  /// Assign a new pointer.
714  /// Throws if a pointer is already assigned.
715  void operator=(device_type * dev)
716  {
717  if (m_dev)
718  fail();
719  m_dev = dev;
720  }
721 
722  /// Delete device object and clear the pointer.
723  void reset()
724  {
725  if (m_dev) {
726  if (m_base_dev && m_dev->owns(m_base_dev))
727  m_dev->release(m_base_dev);
728  delete m_dev;
729  m_dev = 0;
730  }
731  }
732 
733  /// Return the pointer and release ownership.
734  device_type * release()
735  {
736  device_type * dev = m_dev;
737  m_dev = 0;
738  return dev;
739  }
740 
741  /// Replace the pointer.
742  /// Used to call dev->autodetect_open().
743  void replace(device_type * dev)
744  { m_dev = dev; }
745 
746  /// Return the pointer.
747  device_type * get() const
748  { return m_dev; }
749 
750  /// Pointer dereferencing.
751  device_type & operator*() const
752  { return *m_dev; }
753 
754  /// Pointer dereferencing.
755  device_type * operator->() const
756  { return m_dev; }
757 
758  /// For (ptr != 0) check.
759  operator bool() const
760  { return !!m_dev; }
761 
762  /// For (ptr == 0) check.
763  bool operator !() const
764  { return !m_dev; }
765 
766 private:
767  device_type * m_dev;
769 
770  void fail() const
771  { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
772 
773  // Prevent copy/assignment
775  void operator=(const any_device_auto_ptr<Dev> &);
776 };
777 
782 
783 
784 /////////////////////////////////////////////////////////////////////////////
785 // smart_device_list
786 
787 /// List of devices for DEVICESCAN
789 {
790 // Construction
791 public:
793  { }
794 
796  {
797  for (unsigned i = 0; i < m_list.size(); i++)
798  delete m_list[i];
799  }
800 
801 // Attributes
802  unsigned size() const
803  { return m_list.size(); }
804 
805 // Operations
806  void clear()
807  {
808  for (unsigned i = 0; i < m_list.size(); i++)
809  delete m_list[i];
810  m_list.clear();
811  }
812 
813 
815  { m_list.push_back(dev); }
816 
818  {
819  m_list.push_back(dev.get());
820  dev.release();
821  }
822 
823  smart_device * at(unsigned i)
824  { return m_list.at(i); }
825 
826  const smart_device * at(unsigned i) const
827  { return m_list.at(i); }
828 
829  smart_device * release(unsigned i)
830  {
831  smart_device * dev = m_list.at(i);
832  m_list[i] = 0;
833  return dev;
834  }
835 
836  void append(smart_device_list & devlist)
837  {
838  for (unsigned i = 0; i < devlist.size(); i++) {
839  smart_device * dev = devlist.at(i);
840  if (!dev)
841  continue;
842  push_back(dev);
843  devlist.m_list.at(i) = 0;
844  }
845  }
846 
847 // Implementation
848 private:
849  std::vector<smart_device *> m_list;
850 
851  // Prevent copy/assigment
853  void operator=(const smart_device_list &);
854 };
855 
856 
857 /// List of types for DEVICESCAN
858 typedef std::vector<std::string> smart_devtype_list;
859 
860 
861 /////////////////////////////////////////////////////////////////////////////
862 // smart_interface
863 
864 /// The platform interface abstraction
866 {
867 public:
868  /// Initialize platform interface and register with smi().
869  /// Must be implemented by platform module and register interface with set()
870  static void init();
871 
873  { }
874 
875  virtual ~smart_interface() throw()
876  { }
877 
878  /// Return info string about build host and/or OS version.
879  /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
880  virtual std::string get_os_version_str();
881 
882  /// Return valid args for device type option/directive.
883  /// Default implementation returns "ata, scsi, sat, usb*..."
884  /// concatenated with result from get_valid_custom_dev_types_str().
885  virtual std::string get_valid_dev_types_str();
886 
887  /// Return example string for program 'appname'.
888  /// Default implementation returns empty string.
889  /// For the migration of print_smartctl_examples(),
890  /// function is allowed to print examples to stdout.
891  /// TODO: Remove this hack.
892  virtual std::string get_app_examples(const char * appname);
893 
894  /// Get microseconds since some unspecified starting point.
895  /// Used only for command duration measurements in debug outputs.
896  /// Returns -1 if unsupported.
897  /// Default implementation uses clock_gettime(), gettimeofday() or ftime().
898  virtual int64_t get_timer_usec();
899 
900  /// Disable/Enable system auto standby/sleep mode.
901  /// Return false if unsupported or if system is running
902  /// on battery.
903  /// Default implementation returns false.
904  virtual bool disable_system_auto_standby(bool disable);
905 
906 
907  ///////////////////////////////////////////////
908  // Last error information
909 
910  /// Get last error info struct.
912  { return m_err; }
913  /// Get last error number.
914  int get_errno() const
915  { return m_err.no; }
916  /// Get last error message.
917  const char * get_errmsg() const
918  { return m_err.msg.c_str(); }
919 
920  /// Set last error number and message.
921  /// Printf()-like formatting is supported.
922  /// Returns false always to allow use as a return expression.
923  bool set_err(int no, const char * msg, ...)
925 
926  /// Set last error info struct.
927  bool set_err(const smart_device::error_info & err)
928  { m_err = err; return false; }
929 
930  /// Clear last error info.
931  void clear_err()
932  { m_err.clear(); }
933 
934  /// Set last error number and default message.
935  /// Message is retrieved from get_msg_for_errno(no).
936  bool set_err(int no);
937 
938  /// Set last error number and default message to any error_info.
939  /// Used by set_err(no).
940  bool set_err_var(smart_device::error_info * err, int no);
941 
942  /// Convert error number into message, used by set_err(no).
943  /// Default implementation returns strerror(no).
944  virtual const char * get_msg_for_errno(int no);
945 
946  ///////////////////////////////////////////////////////////////////////////
947  // Device factory:
948 
949  /// Return device object for device 'name' with some 'type'.
950  /// 'type' is 0 if not specified by user.
951  /// Return 0 on error.
952  /// Default implementation selects between ata, scsi and custom device.
953  virtual smart_device * get_smart_device(const char * name, const char * type);
954 
955  /// Fill 'devlist' with devices of some 'type' with device names
956  /// specified by some optional 'pattern'.
957  /// Use platform specific default if 'type' is empty or 0.
958  /// Return false on error.
959  virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
960  const char * pattern = 0) = 0;
961 
962  /// Fill 'devlist' with devices of all 'types' with device names
963  /// specified by some optional 'pattern'.
964  /// Use platform specific default if 'types' is empty.
965  /// Return false on error.
966  /// Default implementation calls above function for all types
967  /// and concatenates the results.
968  virtual bool scan_smart_devices(smart_device_list & devlist,
969  const smart_devtype_list & types, const char * pattern = 0);
970 
971 protected:
972  /// Return standard ATA device.
973  virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
974 
975  /// Return standard SCSI device.
976  virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
977 
978  /// Return standard NVMe device.
979  /// Default implementation returns 0.
980  virtual nvme_device * get_nvme_device(const char * name, const char * type,
981  unsigned nsid);
982 
983  /// Autodetect device if no device type specified.
984  virtual smart_device * autodetect_smart_device(const char * name) = 0;
985 
986  /// Return device for platform specific 'type'.
987  /// Default implementation returns 0.
988  virtual smart_device * get_custom_smart_device(const char * name, const char * type);
989 
990  /// Return valid 'type' args accepted by above.
991  /// This is called in get_valid_dev_types_str().
992  /// Default implementation returns empty string.
993  virtual std::string get_valid_custom_dev_types_str();
994 
995  /// Return ATA->SCSI filter for a SAT or USB 'type'.
996  /// Device 'scsidev' is used for SCSI access.
997  /// Return 0 and delete 'scsidev' on error.
998  /// Override only if platform needs special handling.
999  virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
1000  //{ implemented in scsiata.cpp }
1001 
1002 public:
1003  /// Try to detect a SAT device behind a SCSI interface.
1004  /// Inquiry data can be passed if available.
1005  /// Return appropriate device if yes, otherwise 0.
1006  /// Override only if platform needs special handling.
1007  virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
1008  const unsigned char * inqdata, unsigned inqsize);
1009  //{ implemented in scsiata.cpp }
1010 
1011  /// Get type name for USB device with known VENDOR:PRODUCT ID.
1012  /// Return name if device known and supported, otherwise 0.
1013  virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
1014  int version = -1);
1015  //{ implemented in scsiata.cpp }
1016 
1017 protected:
1018  /// Set interface to use, must be called from init().
1019  static void set(smart_interface * intf)
1020  { s_instance = intf; }
1021 
1022 // Implementation
1023 private:
1025 
1026  friend smart_interface * smi(); // below
1027  static smart_interface * s_instance; ///< Pointer to the interface object.
1028 
1029  // Prevent copy/assigment
1031  void operator=(const smart_interface &);
1032 };
1033 
1034 
1035 /////////////////////////////////////////////////////////////////////////////
1036 // smi()
1037 
1038 /// Global access to the (usually singleton) smart_interface
1040  { return smart_interface::s_instance; }
1041 
1042 /////////////////////////////////////////////////////////////////////////////
1043 
1044 #endif // DEV_INTERFACE_H
ata_reg_alias_48(ata_register &ll, ata_register &lm, ata_register &lh, ata_register &hl, ata_register &hm, ata_register &hh)
virtual int64_t get_timer_usec()
Get microseconds since some unspecified starting point.
Error (number,message) pair.
Definition: dev_interface.h:59
ata_reg_alias_16 & operator=(unsigned short x)
ata_reg_alias_16 sector_count_16
virtual ata_device * autodetect_sat_device(scsi_device *scsidev, const unsigned char *inqdata, unsigned inqsize)
Try to detect a SAT device behind a SCSI interface.
Definition: scsiata.cpp:1563
int get_errno() const
Get last error number.
unsigned char direction() const
Get I/O direction from opcode.
u16 flags
Definition: megaraid.h:93
unsigned char m_val
Register value.
ATA Input registers for 48-bit commands.
ata_reg_alias_48 & operator=(uint64_t x)
ata_device * to_ata()
Downcast to ATA device.
ata_out_regs_flags out_needed
True if output register value needed.
const char * get_errmsg() const
Get last error message.
ata_reg_alias_16 sector_count_16
virtual std::string get_valid_dev_types_str()
Return valid args for device type option/directive.
std::string msg
Error message.
Definition: dev_interface.h:68
const char * get_dev_type() const
Get device type.
virtual ata_device * get_sat_device(const char *type, scsi_device *scsidev)
Return ATA->SCSI filter for a SAT or USB 'type'.
Definition: scsiata.cpp:1486
do_not_use_in_implementation_classes
Dummy enum for dummy constructor.
Definition: dev_interface.h:79
ata_in_regs prev
"previous content"
ata_register error
any_device_auto_ptr< ata_device > ata_device_auto_ptr
smart_device::error_info m_err
ata_register lba_mid
uint64_t val() const
void set_data_out(const void *buf, unsigned nsectors)
Prepare for 28-bit DATA OUT command.
int get_errno() const
Get last error number.
virtual void release(const smart_device *dev)
Release ownership of other device.
virtual bool open()=0
Open device, return false on error.
any_device_auto_ptr< nvme_device > nvme_device_auto_ptr
ata_reg_alias_48 lba_48
void clear_err()
Clear last error info.
virtual bool scsi_pass_through(scsi_cmnd_io *iop)=0
SCSI pass through.
ata_reg_alias_16 lba_high_16
smart_device * at(unsigned i)
bool set_nvme_err(nvme_cmd_out &out, unsigned status, const char *msg=0)
Set last error number and message if pass-through returns NVMe error status.
Smart pointer class for device pointers.
ata_register & m_hh
virtual bool is_powered_down()
Early test if device is powered up or down.
void hide_scsi(bool hide=true)
Hide/unhide SCSI interface.
ata_register device
smart_interface * smi()
Global access to the (usually singleton) smart_interface.
virtual const char * get_msg_for_errno(int no)
Convert error number into message, used by set_err(no).
unsigned char val() const
smart_interface * m_intf
const smart_device::error_info & get_err() const
Get last error info struct.
virtual std::string get_valid_custom_dev_types_str()
Return valid 'type' args accepted by above.
virtual bool close()=0
Close device, return false on error.
ata_register sector_count
unsigned cdw11
ata_register & m_lm
ATA Input registers (for 28-bit commands)
NVMe pass through input parameters.
friend smart_interface * smi()
Global access to the (usually singleton) smart_interface.
nvme_device(unsigned nsid)
Constructor requires namespace ID, registers device as NVMe.
device_info & set_info()
R/W access to device info struct.
#define __attribute_format_printf(x, y)
Definition: utility.h:39
16-bit alias to a 8-bit ATA register pair.
bool is_nvme() const
Return true if NVMe device.
Definition: dev_interface.h:99
ata_reg_alias_16 lba_high_16
void * buffer
Pointer to data buffer.
ata_device()
Default constructor, registers device as ATA.
NVMe pass through output parameters.
nvme_device * m_nvme_ptr
std::vector< smart_device * > m_list
void operator=(const smart_device &)
device_type * m_dev
void push_back(smart_device *dev)
bool operator!() const
For (ptr == 0) check.
ata_register lba_mid
scsi_device * to_scsi()
Downcast to SCSI device.
bool is_real_48bit_cmd() const
Return true if 48-bit command with any nonzero high byte.
device_info m_info
virtual smart_device * get_smart_device(const char *name, const char *type)
Return device object for device 'name' with some 'type'.
bool ata_cmd_is_supported(const ata_cmd_in &in, unsigned flags, const char *type=0)
Check command input parameters.
virtual ~smart_interface()
48-bit alias to six 8-bit ATA registers (for LBA).
uint32_t nsid
void operator=(const smart_interface &)
ata_in_regs_48bit in_regs
Input registers.
ata_out_regs_48bit out_regs
Output registers.
std::string dev_type
Actual device type.
Definition: dev_interface.h:54
virtual ata_device * get_ata_device(const char *name, const char *type)=0
Return standard ATA device.
unsigned result
Command specific result (DW0)
List of devices for DEVICESCAN.
void set_data_in(void *buf, unsigned nsectors)
Prepare for 28-bit DATA IN command.
device_type * release()
Return the pointer and release ownership.
const ata_device * to_ata() const
Downcast to ATA device (const).
bool set_err_var(smart_device::error_info *err, int no)
Set last error number and default message to any error_info.
static int get_num_objects()
Get current number of allocated 'smart_device' objects.
device_type * get() const
Return the pointer.
virtual bool is_open() const =0
Return true if device is open.
ata_out_regs prev
read with HOB=1
bool m_is_set
true if set
static void init()
Initialize platform interface and register with smi().
Definition: dev_legacy.cpp:341
nvme_device * to_nvme()
Downcast to NVMe device.
enum ata_cmd_in::@29 direction
I/O direction.
The platform interface abstraction.
virtual bool ata_pass_through(const ata_cmd_in &in, ata_cmd_out &out)=0
ATA pass through.
std::vector< std::string > smart_devtype_list
List of types for DEVICESCAN.
void operator=(const smart_device_list &)
device_info(const char *d_name, const char *d_type, const char *r_type)
Definition: dev_interface.h:47
void replace(device_type *dev)
Replace the pointer.
NVMe device access.
bool status_valid
true if status is valid
static void set(smart_interface *intf)
Set interface to use, must be called from init().
void * buffer
Pointer to data buffer.
error_info m_err
unsigned get_nsid() const
Get namespace id.
ata_register & m_hm
scsi_device * m_scsi_ptr
const char * get_errmsg() const
Get last error message.
long long int64_t
Definition: int64.h:51
static smart_interface * s_instance
Pointer to the interface object.
const scsi_device * to_scsi() const
Downcast to SCSI device (const).
virtual smart_device * autodetect_smart_device(const char *name)=0
Autodetect device if no device type specified.
virtual nvme_device * get_nvme_device(const char *name, const char *type, unsigned nsid)
Return standard NVMe device.
unsigned char opcode
Opcode (CDW0 07:00)
smart_device * release(unsigned i)
ATA Output registers for 48-bit commands.
const smart_device * at(unsigned i) const
ata_register & m_lo
bool is_ata() const
Return true if ATA device.
Definition: dev_interface.h:93
virtual smart_device * get_custom_smart_device(const char *name, const char *type)
Return device for platform specific 'type'.
virtual std::string get_app_examples(const char *appname)
Return example string for program 'appname'.
unsigned cdw12
ata_register status
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
bool is_set() const
Return true if any flag is set.
device_type & operator*() const
Pointer dereferencing.
unsigned size
Size of buffer.
ata_register lba_low
Device info strings.
Definition: dev_interface.h:44
unsigned cdw15
Cmd specific.
SCSI device access.
ata_reg_alias_16 lba_mid_16
unsigned nsid
Namespace ID.
ata_register features
void hide_ata(bool hide=true)
Hide/unhide ATA interface.
Flags for each ATA output register.
ata_register & operator=(unsigned char x)
unsigned size() const
ata_register & m_hl
void hide_nvme(bool hide=true)
Hide/unhide NVMe interface.
ata_register & m_lh
void set_data_in(unsigned char op, void *buf, unsigned sz)
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)
Check command input parameters (old version).
unsigned short val() const
bool is_scsi() const
Return true if SCSI device.
Definition: dev_interface.h:96
bool is_48bit_cmd() const
Return true if 48-bit command.
virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id, int version=-1)
Get type name for USB device with known VENDOR:PRODUCT ID.
Definition: scsiata.cpp:1593
virtual bool scan_smart_devices(smart_device_list &devlist, const char *type, const char *pattern=0)=0
Fill 'devlist' with devices of some 'type' with device names specified by some optional 'pattern'...
~any_device_auto_ptr()
Destructor deletes device object.
ata_reg_alias_16 lba_low_16
ata_register device
Base class for all devices.
Definition: dev_interface.h:39
ata_device * m_ata_ptr
ata_register lba_high
int no
Error number.
Definition: dev_interface.h:67
ata_reg_alias_16 lba_low_16
ATA device access.
ata_register sector_count
device_type * operator->() const
Pointer dereferencing.
virtual bool disable_system_auto_standby(bool disable)
Disable/Enable system auto standby/sleep mode.
virtual bool nvme_pass_through(const nvme_cmd_in &in, nvme_cmd_out &out)=0
NVMe pass through.
unsigned long long uint64_t
Definition: int64.h:54
std::string dev_name
Device (path)name.
Definition: dev_interface.h:52
smart_device * m_base_dev
ata_register & m_hi
error_info(int n, const char *m)
Definition: dev_interface.h:62
bool is_set() const
Return true if any register is set.
unsigned size
Size of buffer.
void set_data_in_48bit(void *buf, unsigned nsectors)
Prepare for 48-bit DATA IN command.
virtual scsi_device * get_scsi_device(const char *name, const char *type)=0
Return standard SCSI device.
unsigned cdw13
ata_register command
const device_info & get_info() const
Get device info struct.
scsi_device()
Default constructor, registers device as SCSI.
void fail() const
any_device_auto_ptr< smart_device > smart_device_auto_ptr
any_device_auto_ptr< scsi_device > scsi_device_auto_ptr
virtual smart_device * autodetect_open()
Open device with autodetection support.
any_device_auto_ptr(device_type *dev=0, smart_device *base_dev=0)
Construct from optional pointer to device and optional pointer to base device.
void reset()
Delete device object and clear the pointer.
ATA pass through input parameters.
unsigned cdw10
const char va_list ap char buf[512+EBUFLEN]
Definition: smartd.cpp:1240
ata_register & m_ll
ata_reg_alias_16 lba_mid_16
const smart_interface * smi() const
Get interface which produced this object (const).
std::string req_type
Device type requested by user, empty if none.
Definition: dev_interface.h:55
virtual ~smart_device()
ata_register lba_low
void set_nsid(unsigned nsid)
Set namespace id.
void append(smart_device_list &devlist)
void push_back(smart_device_auto_ptr &dev)
ata_register lba_high
ata_reg_alias_16(ata_register &lo, ata_register &hi)
smart_interface * smi()
Get interface which produced this object.
const error_info & get_err() const
Get last error info struct.
ata_out_regs_flags()
Default constructor clears all flags.
void clear_err()
Clear last error info.
const char * get_dev_name() const
Get device (path)name.
unsigned short status
Status Field (DW3 31:17)
std::string info_name
Informal name.
Definition: dev_interface.h:53
bool is_set() const
void operator=(device_type *dev)
Assign a new pointer.
bool set_err(int no, const char *msg,...) __attribute_format_printf(3
Set last error number and message.
ATA Output registers (for 28-bit commands)
const char * get_req_type() const
Get type requested by user, empty if none.
unsigned m_nsid
virtual bool ata_identify_is_cached() const
Return true if OS caches ATA identify sector.
ata_reg_alias_16 features_16
virtual bool is_syscall_unsup() const
Return true if last error indicates an unsupported system call.
ATA pass through output parameters.
smart_device(smart_interface *intf, const char *dev_name, const char *dev_type, const char *req_type)
Constructor to init interface and device info.
virtual bool owns(const smart_device *dev) const
Return true if other device is owned by this device.
static int s_num_objects
ATA register value and info whether it has ever been set.
bool is_set() const
Return true if any register is set.
virtual std::string get_os_version_str()
Return info string about build host and/or OS version.
unsigned cdw14
const char * get_info_name() const
Get informal name.
const nvme_device * to_nvme() const
Downcast to NVMe device (const).
ata_reg_alias_48 lba_48