smartmontools  SVN Rev 4735
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 4718 2018-03-07 16:47:28Z dpgilbert $\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  /// Always try READ CAPACITY(10) (rcap10) first but once we know
595  /// rcap16 is needed, use it instead.
597  { rcap16_first = true; }
598 
599  bool use_rcap16() const
600  { return rcap16_first; }
601 
602 protected:
603  /// Hide/unhide SCSI interface.
604  void hide_scsi(bool hide = true)
605  { m_scsi_ptr = (!hide ? this : 0); }
606 
607  /// Default constructor, registers device as SCSI.
610  rcap16_first(false)
611  { hide_scsi(false); }
612 
613 private:
615 };
616 
617 
618 /////////////////////////////////////////////////////////////////////////////
619 // NVMe specific interface
620 
621 /// NVMe pass through input parameters
623 {
624  unsigned char opcode; ///< Opcode (CDW0 07:00)
625  unsigned nsid; ///< Namespace ID
626  unsigned cdw10, cdw11, cdw12, cdw13, cdw14, cdw15; ///< Cmd specific
627 
628  void * buffer; ///< Pointer to data buffer
629  unsigned size; ///< Size of buffer
630 
631  enum {
632  no_data = 0x0, data_out = 0x1, data_in = 0x2, data_io = 0x3
633  };
634 
635  /// Get I/O direction from opcode
636  unsigned char direction() const
637  { return (opcode & 0x3); }
638 
639  // Prepare for DATA IN command
640  void set_data_in(unsigned char op, void * buf, unsigned sz)
641  {
642  opcode = op;
643  if (direction() != data_in)
644  throw std::logic_error("invalid opcode for DATA IN");
645  buffer = buf;
646  size = sz;
647  }
648 
650  : opcode(0), nsid(0),
651  cdw10(0), cdw11(0), cdw12(0), cdw13(0), cdw14(0), cdw15(0),
652  buffer(0), size(0)
653  { }
654 };
655 
656 /// NVMe pass through output parameters
658 {
659  unsigned result; ///< Command specific result (DW0)
660  unsigned short status; ///< Status Field (DW3 31:17)
661  bool status_valid; ///< true if status is valid
662 
664  : result(0), status(0), status_valid(false)
665  { }
666 };
667 
668 /// NVMe device access
670 : virtual public /*extends*/ smart_device
671 {
672 public:
673  /// NVMe pass through.
674  /// Return false on error.
675  virtual bool nvme_pass_through(const nvme_cmd_in & in, nvme_cmd_out & out) = 0;
676 
677  /// Get namespace id.
678  unsigned get_nsid() const
679  { return m_nsid; }
680 
681 protected:
682  /// Hide/unhide NVMe interface.
683  void hide_nvme(bool hide = true)
684  { m_nvme_ptr = (!hide ? this : 0); }
685 
686  /// Constructor requires namespace ID, registers device as NVMe.
687  explicit nvme_device(unsigned nsid)
689  m_nsid(nsid)
690  { hide_nvme(false); }
691 
692  /// Set namespace id.
693  /// Should be called in open() function if get_nsid() returns 0.
694  void set_nsid(unsigned nsid)
695  { m_nsid = nsid; }
696 
697  /// Set last error number and message if pass-through returns NVMe error status.
698  /// Returns false always to allow use as a return expression.
699  bool set_nvme_err(nvme_cmd_out & out, unsigned status, const char * msg = 0);
700 
701 private:
702  unsigned m_nsid;
703 };
704 
705 
706 /////////////////////////////////////////////////////////////////////////////
707 /// Smart pointer class for device pointers
708 
709 template <class Dev>
711 {
712 public:
713  typedef Dev device_type;
714 
715  /// Construct from optional pointer to device
716  /// and optional pointer to base device.
717  explicit any_device_auto_ptr(device_type * dev = 0,
718  smart_device * base_dev = 0)
719  : m_dev(dev), m_base_dev(base_dev) { }
720 
721  /// Destructor deletes device object.
723  { reset(); }
724 
725  /// Assign a new pointer.
726  /// Throws if a pointer is already assigned.
727  void operator=(device_type * dev)
728  {
729  if (m_dev)
730  fail();
731  m_dev = dev;
732  }
733 
734  /// Delete device object and clear the pointer.
735  void reset()
736  {
737  if (m_dev) {
738  if (m_base_dev && m_dev->owns(m_base_dev))
739  m_dev->release(m_base_dev);
740  delete m_dev;
741  m_dev = 0;
742  }
743  }
744 
745  /// Return the pointer and release ownership.
746  device_type * release()
747  {
748  device_type * dev = m_dev;
749  m_dev = 0;
750  return dev;
751  }
752 
753  /// Replace the pointer.
754  /// Used to call dev->autodetect_open().
755  void replace(device_type * dev)
756  { m_dev = dev; }
757 
758  /// Return the pointer.
759  device_type * get() const
760  { return m_dev; }
761 
762  /// Pointer dereferencing.
763  device_type & operator*() const
764  { return *m_dev; }
765 
766  /// Pointer dereferencing.
767  device_type * operator->() const
768  { return m_dev; }
769 
770  /// For (ptr != 0) check.
771  operator bool() const
772  { return !!m_dev; }
773 
774  /// For (ptr == 0) check.
775  bool operator !() const
776  { return !m_dev; }
777 
778 private:
779  device_type * m_dev;
781 
782  void fail() const
783  { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
784 
785  // Prevent copy/assignment
787  void operator=(const any_device_auto_ptr<Dev> &);
788 };
789 
794 
795 
796 /////////////////////////////////////////////////////////////////////////////
797 // smart_device_list
798 
799 /// List of devices for DEVICESCAN
801 {
802 // Construction
803 public:
805  { }
806 
808  {
809  for (unsigned i = 0; i < m_list.size(); i++)
810  delete m_list[i];
811  }
812 
813 // Attributes
814  unsigned size() const
815  { return m_list.size(); }
816 
817 // Operations
818  void clear()
819  {
820  for (unsigned i = 0; i < m_list.size(); i++)
821  delete m_list[i];
822  m_list.clear();
823  }
824 
825 
827  { m_list.push_back(dev); }
828 
830  {
831  m_list.push_back(dev.get());
832  dev.release();
833  }
834 
835  smart_device * at(unsigned i)
836  { return m_list.at(i); }
837 
838  const smart_device * at(unsigned i) const
839  { return m_list.at(i); }
840 
841  smart_device * release(unsigned i)
842  {
843  smart_device * dev = m_list.at(i);
844  m_list[i] = 0;
845  return dev;
846  }
847 
848  void append(smart_device_list & devlist)
849  {
850  for (unsigned i = 0; i < devlist.size(); i++) {
851  smart_device * dev = devlist.at(i);
852  if (!dev)
853  continue;
854  push_back(dev);
855  devlist.m_list.at(i) = 0;
856  }
857  }
858 
859 // Implementation
860 private:
861  std::vector<smart_device *> m_list;
862 
863  // Prevent copy/assigment
865  void operator=(const smart_device_list &);
866 };
867 
868 
869 /// List of types for DEVICESCAN
870 typedef std::vector<std::string> smart_devtype_list;
871 
872 
873 /////////////////////////////////////////////////////////////////////////////
874 // smart_interface
875 
876 /// The platform interface abstraction
878 {
879 public:
880  /// Initialize platform interface and register with smi().
881  /// Must be implemented by platform module and register interface with set()
882  static void init();
883 
885  { }
886 
887  virtual ~smart_interface() throw()
888  { }
889 
890  /// Return info string about build host and/or OS version.
891  /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
892  virtual std::string get_os_version_str();
893 
894  /// Return valid args for device type option/directive.
895  /// Default implementation returns "ata, scsi, sat, usb*..."
896  /// concatenated with result from get_valid_custom_dev_types_str().
897  virtual std::string get_valid_dev_types_str();
898 
899  /// Return example string for program 'appname'.
900  /// Default implementation returns empty string.
901  /// For the migration of print_smartctl_examples(),
902  /// function is allowed to print examples to stdout.
903  /// TODO: Remove this hack.
904  virtual std::string get_app_examples(const char * appname);
905 
906  /// Get microseconds since some unspecified starting point.
907  /// Used only for command duration measurements in debug outputs.
908  /// Returns -1 if unsupported.
909  /// Default implementation uses clock_gettime(), gettimeofday() or ftime().
910  virtual int64_t get_timer_usec();
911 
912  /// Disable/Enable system auto standby/sleep mode.
913  /// Return false if unsupported or if system is running
914  /// on battery.
915  /// Default implementation returns false.
916  virtual bool disable_system_auto_standby(bool disable);
917 
918 
919  ///////////////////////////////////////////////
920  // Last error information
921 
922  /// Get last error info struct.
924  { return m_err; }
925  /// Get last error number.
926  int get_errno() const
927  { return m_err.no; }
928  /// Get last error message.
929  const char * get_errmsg() const
930  { return m_err.msg.c_str(); }
931 
932  /// Set last error number and message.
933  /// Printf()-like formatting is supported.
934  /// Returns false always to allow use as a return expression.
935  bool set_err(int no, const char * msg, ...)
937 
938  /// Set last error info struct.
939  bool set_err(const smart_device::error_info & err)
940  { m_err = err; return false; }
941 
942  /// Clear last error info.
943  void clear_err()
944  { m_err.clear(); }
945 
946  /// Set last error number and default message.
947  /// Message is retrieved from get_msg_for_errno(no).
948  bool set_err(int no);
949 
950  /// Set last error number and default message to any error_info.
951  /// Used by set_err(no).
952  bool set_err_var(smart_device::error_info * err, int no);
953 
954  /// Convert error number into message, used by set_err(no).
955  /// Default implementation returns strerror(no).
956  virtual const char * get_msg_for_errno(int no);
957 
958  ///////////////////////////////////////////////////////////////////////////
959  // Device factory:
960 
961  /// Return device object for device 'name' with some 'type'.
962  /// 'type' is 0 if not specified by user.
963  /// Return 0 on error.
964  /// Default implementation selects between ata, scsi and custom device.
965  virtual smart_device * get_smart_device(const char * name, const char * type);
966 
967  /// Fill 'devlist' with devices of some 'type' with device names
968  /// specified by some optional 'pattern'.
969  /// Use platform specific default if 'type' is empty or 0.
970  /// Return false on error.
971  virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
972  const char * pattern = 0) = 0;
973 
974  /// Fill 'devlist' with devices of all 'types' with device names
975  /// specified by some optional 'pattern'.
976  /// Use platform specific default if 'types' is empty.
977  /// Return false on error.
978  /// Default implementation calls above function for all types
979  /// and concatenates the results.
980  virtual bool scan_smart_devices(smart_device_list & devlist,
981  const smart_devtype_list & types, const char * pattern = 0);
982 
983 protected:
984  /// Return standard ATA device.
985  virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
986 
987  /// Return standard SCSI device.
988  virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
989 
990  /// Return standard NVMe device.
991  /// Default implementation returns 0.
992  virtual nvme_device * get_nvme_device(const char * name, const char * type,
993  unsigned nsid);
994 
995  /// Autodetect device if no device type specified.
996  virtual smart_device * autodetect_smart_device(const char * name) = 0;
997 
998  /// Return device for platform specific 'type'.
999  /// Default implementation returns 0.
1000  virtual smart_device * get_custom_smart_device(const char * name, const char * type);
1001 
1002  /// Return valid 'type' args accepted by above.
1003  /// This is called in get_valid_dev_types_str().
1004  /// Default implementation returns empty string.
1005  virtual std::string get_valid_custom_dev_types_str();
1006 
1007  /// Return ATA->SCSI filter for a SAT or USB 'type'.
1008  /// Device 'scsidev' is used for SCSI access.
1009  /// Return 0 and delete 'scsidev' on error.
1010  /// Override only if platform needs special handling.
1011  virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
1012  //{ implemented in scsiata.cpp }
1013 
1014 public:
1015  /// Try to detect a SAT device behind a SCSI interface.
1016  /// Inquiry data can be passed if available.
1017  /// Return appropriate device if yes, otherwise 0.
1018  /// Override only if platform needs special handling.
1019  virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
1020  const unsigned char * inqdata, unsigned inqsize);
1021  //{ implemented in scsiata.cpp }
1022 
1023  /// Get type name for USB device with known VENDOR:PRODUCT ID.
1024  /// Return name if device known and supported, otherwise 0.
1025  virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
1026  int version = -1);
1027  //{ implemented in scsiata.cpp }
1028 
1029 protected:
1030  /// Set interface to use, must be called from init().
1031  static void set(smart_interface * intf)
1032  { s_instance = intf; }
1033 
1034 // Implementation
1035 private:
1037 
1038  friend smart_interface * smi(); // below
1039  static smart_interface * s_instance; ///< Pointer to the interface object.
1040 
1041  // Prevent copy/assigment
1043  void operator=(const smart_interface &);
1044 };
1045 
1046 
1047 /////////////////////////////////////////////////////////////////////////////
1048 // smi()
1049 
1050 /// Global access to the (usually singleton) smart_interface
1052  { return smart_interface::s_instance; }
1053 
1054 /////////////////////////////////////////////////////////////////////////////
1055 
1056 #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:1558
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:1481
do_not_use_in_implementation_classes
Dummy enum for dummy constructor.
Definition: dev_interface.h:79
void set_rcap16_first()
Always try READ CAPACITY(10) (rcap10) first but once we know rcap16 is needed, use it instead...
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.
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:1590
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.
bool use_rcap16() const
virtual bool nvme_pass_through(const nvme_cmd_in &in, nvme_cmd_out &out)=0
NVMe pass through.
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