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