4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2008-9 Christian Franke <smartmontools-support@lists.sourceforge.net>
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)
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/>.
18 #ifndef DEV_INTERFACE_H
19 #define DEV_INTERFACE_H
21 #define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 2973 2009-10-26 22:38:19Z chrfranke $\n"
28 #if !defined(__GNUC__) && !defined(__attribute__)
29 #define __attribute__(x) /**/
32 #ifdef _MSC_VER // Disable MSVC warning
33 #pragma warning(disable:4250) // 'class1' : inherits 'class2::member' via dominance
36 /////////////////////////////////////////////////////////////////////////////
37 // Common functionality for all device types
39 // Forward declarations
40 class smart_interface
;
44 /// Base class for all devices
49 /// Device info strings
53 device_info(const char * d_name
, const char * d_type
, const char * r_type
)
54 : dev_name(d_name
), info_name(d_name
),
55 dev_type(d_type
), req_type(r_type
)
58 std::string dev_name
; ///< Device (path)name
59 std::string info_name
; ///< Informal name
60 std::string dev_type
; ///< Actual device type
61 std::string req_type
; ///< Device type requested by user, empty if none
64 /// Error (number,message) pair
66 explicit error_info(int n
= 0)
68 error_info(int n
, const char * m
)
71 { no
= 0; msg
.erase(); }
73 int no
; ///< Error number
74 std::string msg
; ///< Error message
79 /// Constructor to init interface and device info.
80 /// Must be called in implementation classes.
81 smart_device(smart_interface
* intf
, const char * dev_name
,
82 const char * dev_type
, const char * req_type
);
84 /// Dummy enum for dummy constructor.
85 enum do_not_use_in_implementation_classes
{ never_called
};
86 /// Dummy constructor for abstract classes.
87 /// Must never be called in implementation classes.
88 smart_device(do_not_use_in_implementation_classes
);
91 virtual ~smart_device() throw();
95 ///////////////////////////////////////////////
96 // Dynamic downcasts to actual device flavor
98 /// Return true if ATA device
100 { return !!m_ata_ptr
; }
101 /// Return true if SCSI device
103 { return !!m_scsi_ptr
; }
105 /// Downcast to ATA device.
106 ata_device
* to_ata()
107 { return m_ata_ptr
; }
108 /// Downcast to ATA device (const).
109 const ata_device
* to_ata() const
110 { return m_ata_ptr
; }
111 /// Downcast to SCSI device.
112 scsi_device
* to_scsi()
113 { return m_scsi_ptr
; }
114 /// Downcast to ATA device (const).
115 const scsi_device
* to_scsi() const
116 { return m_scsi_ptr
; }
118 ///////////////////////////////////////////////
119 // Device information
121 /// Get device info struct.
122 const device_info
& get_info() const
125 /// Get device (path)name.
126 const char * get_dev_name() const
127 { return m_info
.dev_name
.c_str(); }
128 /// Get informal name.
129 const char * get_info_name() const
130 { return m_info
.info_name
.c_str(); }
132 const char * get_dev_type() const
133 { return m_info
.dev_type
.c_str(); }
134 /// Get type requested by user, empty if none.
135 const char * get_req_type() const
136 { return m_info
.req_type
.c_str(); }
139 /// R/W access to device info struct.
140 device_info
& set_info()
144 ///////////////////////////////////////////////
145 // Last error information
147 /// Get last error info struct.
148 const error_info
& get_err() const
150 /// Get last error number.
151 int get_errno() const
153 /// Get last error message.
154 const char * get_errmsg() const
155 { return m_err
.msg
.c_str(); }
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
, ...)
161 __attribute__ ((format (printf
, 3, 4)));
163 /// Set last error info struct.
164 bool set_err(const error_info
& err
)
165 { m_err
= err
; return false; }
167 /// Clear last error info.
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
);
177 ///////////////////////////////////////////////
179 // Must be implemented in derived class
181 /// Return true if device is open.
182 virtual bool is_open() const = 0;
184 /// Open device, return false on error.
185 virtual bool open() = 0;
187 /// Close device, return false on error.
188 virtual bool close() = 0;
190 /// Open device with autodetection support.
191 /// May return another device for further access.
192 /// In this case, the original pointer is no longer valid.
193 /// Default Implementation calls 'open()' and returns 'this'.
194 virtual smart_device
* autodetect_open();
196 ///////////////////////////////////////////////
197 // Support for tunnelled devices
199 /// Return true if other device is owned by this device.
200 /// Default implementation returns false.
201 virtual bool owns(const smart_device
* dev
) const;
203 /// Release ownership of other device.
204 /// Default implementation does nothing.
205 virtual void release(const smart_device
* dev
);
208 /// Set dynamic downcast for ATA
209 void this_is_ata(ata_device
* ata
);
212 /// Set dynamic downcast for SCSI
213 void this_is_scsi(scsi_device
* scsi
);
216 /// Get interface which produced this object.
217 smart_interface
* smi()
219 /// Get interface which produced this object (const).
220 const smart_interface
* smi() const
225 smart_interface
* m_intf
;
227 ata_device
* m_ata_ptr
;
228 scsi_device
* m_scsi_ptr
;
231 // Prevent copy/assigment
232 smart_device(const smart_device
&);
233 void operator=(const smart_device
&);
237 /////////////////////////////////////////////////////////////////////////////
238 // ATA specific interface
240 /// ATA register value and info whether is has been ever set
241 // (Automatically set by first assignment)
246 : m_val(0x00), m_is_set(false) { }
248 ata_register
& operator=(unsigned char val
)
249 { m_val
= val
; m_is_set
= true; return * this; }
251 unsigned char val() const
253 operator unsigned char() const
260 unsigned char m_val
; ///< Register value
261 bool m_is_set
; ///< true if set
264 /// ATA Input registers (for 28-bit commands)
267 // ATA-6/7 register names // ATA-3/4/5 // ATA-8
268 ata_register features
; // features // features
269 ata_register sector_count
; // sector count // count
270 ata_register lba_low
; // sector number // ]
271 ata_register lba_mid
; // cylinder low // ] lba
272 ata_register lba_high
; // cylinder high // ]
273 ata_register device
; // device/head // device
274 ata_register command
; // command // command
276 /// Return true if any register is set
278 { return (features
.is_set() || sector_count
.is_set()
279 || lba_low
.is_set() || lba_mid
.is_set() || lba_high
.is_set()
280 || device
.is_set() || command
.is_set()); }
283 /// ATA Output registers (for 28-bit commands)
287 ata_register sector_count
;
288 ata_register lba_low
;
289 ata_register lba_mid
;
290 ata_register lba_high
;
294 /// Return true if any register is set
296 { return (error
.is_set() || sector_count
.is_set()
297 || lba_low
.is_set() || lba_mid
.is_set() || lba_high
.is_set()
298 || device
.is_set() || status
.is_set()); }
302 /// 16-bit alias to a 8-bit ATA register pair.
303 class ata_reg_alias_16
306 ata_reg_alias_16(ata_register
& lo
, ata_register
& hi
)
307 : m_lo(lo
), m_hi(hi
) { }
309 ata_reg_alias_16
& operator=(unsigned short val
)
310 { m_lo
= (unsigned char) val
;
311 m_hi
= (unsigned char)(val
>> 8);
314 unsigned short val() const
315 { return m_lo
| (m_hi
<< 8); }
316 operator unsigned short() const
317 { return m_lo
| (m_hi
<< 8); }
320 ata_register
& m_lo
, & m_hi
;
322 // References must not be copied.
323 ata_reg_alias_16(const ata_reg_alias_16
&);
324 void operator=(const ata_reg_alias_16
&);
328 /// ATA Input registers for 48-bit commands
329 // See section 4.14 of T13/1532D Volume 1 Revision 4b
331 // Uses ATA-6/7 method to specify 16-bit registers as
332 // recent (low byte) and previous (high byte) content of
335 // (ATA-8 ACS does not longer follow this scheme, it uses
336 // abstract registers with sufficient size and leaves the
337 // actual mapping to the transport layer.)
339 struct ata_in_regs_48bit
340 : public ata_in_regs
// "most recently written" registers
342 ata_in_regs prev
; ///< "previous content"
344 // 16-bit aliases for above pair.
345 ata_reg_alias_16 features_16
;
346 ata_reg_alias_16 sector_count_16
;
347 ata_reg_alias_16 lba_low_16
;
348 ata_reg_alias_16 lba_mid_16
;
349 ata_reg_alias_16 lba_high_16
;
351 /// Return true if 48-bit command
352 bool is_48bit_cmd() const
353 { return prev
.is_set(); }
355 /// Return true if 48-bit command with any nonzero high byte
356 bool is_real_48bit_cmd() const
357 { return ( prev
.features
|| prev
.sector_count
358 || prev
.lba_low
|| prev
.lba_mid
|| prev
.lba_high
); }
364 /// ATA Output registers for 48-bit commands
365 struct ata_out_regs_48bit
366 : public ata_out_regs
// read with HOB=0
368 ata_out_regs prev
; ///< read with HOB=1
370 // 16-bit aliases for above pair.
371 ata_reg_alias_16 sector_count_16
;
372 ata_reg_alias_16 lba_low_16
;
373 ata_reg_alias_16 lba_mid_16
;
374 ata_reg_alias_16 lba_high_16
;
376 ata_out_regs_48bit();
380 /// Flags for each ATA output register
381 struct ata_out_regs_flags
383 bool error
, sector_count
, lba_low
, lba_mid
, lba_high
, device
, status
;
385 /// Return true if any flag is set.
387 { return ( error
|| sector_count
|| lba_low
388 || lba_mid
|| lba_high
|| device
|| status
); }
390 /// Default constructor clears all flags.
392 : error(false), sector_count(false), lba_low(false), lba_mid(false),
393 lba_high(false), device(false), status(false) { }
397 /// ATA pass through input parameters
400 ata_in_regs_48bit in_regs
; ///< Input registers
401 ata_out_regs_flags out_needed
; ///< True if output register value needed
402 enum { no_data
= 0, data_in
, data_out
} direction
; ///< I/O direction
403 void * buffer
; ///< Pointer to data buffer
404 unsigned size
; ///< Size of buffer
406 /// Prepare for 28-bit DATA IN command
407 void set_data_in(void * buf
, unsigned nsectors
)
410 in_regs
.sector_count
= nsectors
;
412 size
= nsectors
* 512;
415 /// Prepare for 28-bit DATA OUT command
416 void set_data_out(const void * buf
, unsigned nsectors
)
418 buffer
= const_cast<void *>(buf
);
419 in_regs
.sector_count
= nsectors
;
420 direction
= data_out
;
421 size
= nsectors
* 512;
424 /// Prepare for 48-bit DATA IN command
425 void set_data_in_48bit(void * buf
, unsigned nsectors
)
428 // Note: This also sets 'in_regs.is_48bit_cmd()'
429 in_regs
.sector_count_16
= nsectors
;
431 size
= nsectors
* 512;
437 /// ATA pass through output parameters
440 ata_out_regs_48bit out_regs
; ///< Output registers
445 /// ATA device access
447 : virtual public /*extends*/ smart_device
450 /// ATA pass through.
451 /// Return false on error.
452 /// Must be implemented in derived class.
453 virtual bool ata_pass_through(const ata_cmd_in
& in
, ata_cmd_out
& out
) = 0;
455 /// ATA pass through without output registers.
456 /// Return false on error.
457 /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
458 bool ata_pass_through(const ata_cmd_in
& in
);
460 /// Return true if OS caches ATA identify sector.
461 /// Default implementation returns false.
462 virtual bool ata_identify_is_cached() const;
465 /// Check command input parameters.
466 /// Calls set_err(...) accordingly.
467 bool ata_cmd_is_ok(const ata_cmd_in
& in
,
468 bool data_out_support
= false,
469 bool multi_sector_support
= false,
470 bool ata_48bit_support
= false);
472 /// Default constructor, registers device as ATA.
474 : smart_device(never_called
)
475 { this_is_ata(this); }
479 /////////////////////////////////////////////////////////////////////////////
480 // SCSI specific interface
484 /// SCSI device access
486 : virtual public /*extends*/ smart_device
489 /// SCSI pass through.
490 /// Returns false on error.
491 virtual bool scsi_pass_through(scsi_cmnd_io
* iop
) = 0;
494 /// Default constructor, registers device as SCSI.
496 : smart_device(never_called
)
497 { this_is_scsi(this); }
501 /////////////////////////////////////////////////////////////////////////////
503 // Set dynamic downcasts
504 // Note that due to virtual inheritance,
505 // (ata == this) does not imply ((void*)ata == (void*)this))
507 inline void smart_device::this_is_ata(ata_device
* ata
)
509 m_ata_ptr
= (ata
== this ? ata
: 0);
512 inline void smart_device::this_is_scsi(scsi_device
* scsi
)
514 m_scsi_ptr
= (scsi
== this ? scsi
: 0);
518 /////////////////////////////////////////////////////////////////////////////
519 /// Smart pointer class for device pointers
522 class any_device_auto_ptr
525 typedef Dev device_type
;
527 /// Construct from optional pointer to device
528 /// and optional pointer to base device.
529 explicit any_device_auto_ptr(device_type
* dev
= 0,
530 smart_device
* base_dev
= 0)
531 : m_dev(dev
), m_base_dev(base_dev
) { }
533 /// Destructor deletes device object.
534 ~any_device_auto_ptr() throw()
537 /// Assign a new pointer.
538 /// Throws if a pointer is already assigned.
539 void operator=(device_type
* dev
)
546 /// Delete device object and clear the pointer.
550 if (m_base_dev
&& m_dev
->owns(m_base_dev
))
551 m_dev
->release(m_base_dev
);
557 /// Return the pointer and release ownership.
558 device_type
* release()
560 device_type
* dev
= m_dev
;
565 /// Replace the pointer.
566 /// Used to call dev->autodetect_open().
567 void replace(device_type
* dev
)
570 /// Return the pointer.
571 device_type
* get() const
574 /// Pointer dereferencing.
575 device_type
& operator*() const
578 /// Pointer dereferencing.
579 device_type
* operator->() const
582 /// For (ptr != 0) check.
583 operator bool() const
586 /// For (ptr == 0) check.
587 bool operator !() const
592 smart_device
* m_base_dev
;
595 { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
597 // Prevent copy/assignment
598 any_device_auto_ptr(const any_device_auto_ptr
<Dev
> &);
599 void operator=(const any_device_auto_ptr
<Dev
> &);
602 typedef any_device_auto_ptr
<smart_device
> smart_device_auto_ptr
;
603 typedef any_device_auto_ptr
<ata_device
> ata_device_auto_ptr
;
604 typedef any_device_auto_ptr
<scsi_device
> scsi_device_auto_ptr
;
607 /////////////////////////////////////////////////////////////////////////////
610 /// List of devices for DEVICESCAN
611 class smart_device_list
618 ~smart_device_list() throw()
620 for (unsigned i
= 0; i
< m_list
.size(); i
++)
625 unsigned size() const
626 { return m_list
.size(); }
631 for (unsigned i
= 0; i
< m_list
.size(); i
++)
637 void push_back(smart_device
* dev
)
638 { m_list
.push_back(dev
); }
640 void push_back(smart_device_auto_ptr
& dev
)
642 m_list
.push_back(dev
.get());
646 smart_device
* at(unsigned i
)
647 { return m_list
.at(i
); }
649 const smart_device
* at(unsigned i
) const
650 { return m_list
.at(i
); }
652 smart_device
* release(unsigned i
)
654 smart_device
* dev
= m_list
.at(i
);
661 std::vector
<smart_device
*> m_list
;
663 // Prevent copy/assigment
664 smart_device_list(const smart_device_list
&);
665 void operator=(const smart_device_list
&);
669 /////////////////////////////////////////////////////////////////////////////
672 /// The platform interface abstraction
673 class smart_interface
676 /// Initialize platform interface and register with smi().
677 /// Must be implemented by platform module and register interface with set()
683 virtual ~smart_interface() throw()
686 /// Return info string about build host and/or OS version.
687 /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
688 virtual std::string
get_os_version_str();
690 /// Return valid args for device type option/directive.
691 /// Default implementation returns "ata, scsi, sat, usb*..."
692 /// concatenated with result from get_valid_custom_dev_types_str().
693 virtual std::string
get_valid_dev_types_str();
695 /// Return example string for program 'appname'.
696 /// Default implementation returns empty string.
697 /// For the migration of print_smartctl_examples(),
698 /// function is allowed to print examples to stdout.
699 /// TODO: Remove this hack.
700 virtual std::string
get_app_examples(const char * appname
);
702 ///////////////////////////////////////////////
703 // Last error information
705 /// Get last error info struct.
706 const smart_device::error_info
& get_err() const
708 /// Get last error number.
709 int get_errno() const
711 /// Get last error message.
712 const char * get_errmsg() const
713 { return m_err
.msg
.c_str(); }
715 /// Set last error number and message.
716 /// Printf()-like formatting is supported.
717 void set_err(int no
, const char * msg
, ...)
718 __attribute__ ((format (printf
, 3, 4)));
720 /// Set last error info struct.
721 void set_err(const smart_device::error_info
& err
)
724 /// Clear last error info.
728 /// Set last error number and default message.
729 /// Message is retrieved from get_msg_for_errno(no).
730 void set_err(int no
);
732 /// Set last error number and default message to any error_info.
733 /// Used by set_err(no).
734 void set_err_var(smart_device::error_info
* err
, int no
);
736 /// Convert error number into message, used by set_err(no).
737 /// Default implementation returns strerror(no).
738 virtual const char * get_msg_for_errno(int no
);
740 ///////////////////////////////////////////////////////////////////////////
743 /// Return device object for device 'name' with some 'type'.
744 /// 'type' is 0 if not specified by user.
745 /// Return 0 on error.
746 /// Default implementation selects between ata, scsi and custom device.
747 virtual smart_device
* get_smart_device(const char * name
, const char * type
);
749 /// Fill 'devlist' with devices of some 'type' with devices names.
750 /// specified by some optional 'pattern'.
751 /// Return false on error.
752 virtual bool scan_smart_devices(smart_device_list
& devlist
, const char * type
,
753 const char * pattern
= 0) = 0;
756 /// Return standard ATA device.
757 virtual ata_device
* get_ata_device(const char * name
, const char * type
) = 0;
759 /// Return standard SCSI device.
760 virtual scsi_device
* get_scsi_device(const char * name
, const char * type
) = 0;
762 /// Autodetect device if no device type specified.
763 virtual smart_device
* autodetect_smart_device(const char * name
) = 0;
765 /// Return device for platform specific 'type'.
766 /// Default implementation returns 0.
767 virtual smart_device
* get_custom_smart_device(const char * name
, const char * type
);
769 /// Return valid 'type' args accepted by above.
770 /// This is called in get_valid_dev_types_str().
771 /// Default implementation returns empty string.
772 virtual std::string
get_valid_custom_dev_types_str();
774 /// Return ATA->SCSI filter for SAT or USB.
775 /// Override only if platform needs special handling.
776 virtual ata_device
* get_sat_device(const char * type
, scsi_device
* scsidev
);
777 //{ implemented in scsiata.cpp }
780 /// Try to detect a SAT device behind a SCSI interface.
781 /// Inquiry data can be passed if available.
782 /// Return appropriate device if yes, otherwise 0.
783 /// Override only if platform needs special handling.
784 virtual ata_device
* autodetect_sat_device(scsi_device
* scsidev
,
785 const unsigned char * inqdata
, unsigned inqsize
);
786 //{ implemented in scsiata.cpp }
788 /// Get type name for USB device with known VENDOR:PRODUCT ID.
789 /// Return name if device known and supported, otherwise 0.
790 virtual const char * get_usb_dev_type_by_id(int vendor_id
, int product_id
,
792 //{ implemented in scsiata.cpp }
795 /// Set interface to use, must be called from init().
796 static void set(smart_interface
* intf
)
797 { s_instance
= intf
; }
801 smart_device::error_info m_err
;
803 friend smart_interface
* smi(); // below
804 static smart_interface
* s_instance
; ///< Pointer to the interface object.
806 // Prevent copy/assigment
807 smart_interface(const smart_interface
&);
808 void operator=(const smart_interface
&);
812 /////////////////////////////////////////////////////////////////////////////
815 /// Global access to the (usually singleton) smart_interface
816 inline smart_interface
* smi()
817 { return smart_interface::s_instance
; }
819 /////////////////////////////////////////////////////////////////////////////
821 #endif // DEV_INTERFACE_H