smartmontools  SVN Rev 4315
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:1564
int get_errno() const
Get last error number.
unsigned char direction() const
Get I/O direction from opcode.
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:1487
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
u16 flags
Definition: megaraid.h:93
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).
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.
enum ata_cmd_in::@27 direction
I/O direction.
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.
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:1594
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
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