]> git.proxmox.com Git - mirror_smartmontools-debian.git/blob - dev_interface.h
7550c3aa3476ae6e42f2bcbc93a7d92f7db4ab4a
[mirror_smartmontools-debian.git] / dev_interface.h
1 /*
2 * dev_interface.h
3 *
4 * Home page of code is: http://smartmontools.sourceforge.net
5 *
6 * Copyright (C) 2008-9 Christian Franke <smartmontools-support@lists.sourceforge.net>
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,v 1.9 2009/03/12 20:31:12 chrfranke Exp $\n"
22
23 #include <stdarg.h>
24 #include <string>
25 #include <vector>
26
27 #if !defined(__GNUC__) && !defined(__attribute__)
28 #define __attribute__(x) /**/
29 #endif
30
31 #ifdef _MSC_VER // Disable MSVC warning
32 #pragma warning(disable:4250) // 'class1' : inherits 'class2::member' via dominance
33 #endif
34
35 /////////////////////////////////////////////////////////////////////////////
36 // Common functionality for all device types
37
38 // Forward declarations
39 class smart_interface;
40 class ata_device;
41 class scsi_device;
42
43 /// Base class for all devices
44 class smart_device
45 {
46 // Types
47 public:
48 /// Device info strings
49 struct device_info {
50 device_info()
51 { }
52 device_info(const char * d_name, const char * d_type, const char * r_type)
53 : dev_name(d_name), info_name(d_name),
54 dev_type(d_type), req_type(r_type)
55 { }
56
57 std::string dev_name; ///< Device (path)name
58 std::string info_name; ///< Informal name
59 std::string dev_type; ///< Actual device type
60 std::string req_type; ///< Device type requested by user, empty if none
61 };
62
63 /// Error (number,message) pair
64 struct error_info {
65 explicit error_info(int n = 0)
66 : no(n) { }
67 error_info(int n, const char * m)
68 : no(n), msg(m) { }
69 void clear()
70 { no = 0; msg.erase(); }
71
72 int no; ///< Error number
73 std::string msg; ///< Error message
74 };
75
76 // Construction
77 protected:
78 /// Constructor to init interface and device info.
79 /// Must be called in implementation classes.
80 smart_device(smart_interface * intf, const char * dev_name,
81 const char * dev_type, const char * req_type);
82
83 /// Dummy enum for dummy constructor.
84 enum do_not_use_in_implementation_classes { never_called };
85 /// Dummy constructor for abstract classes.
86 /// Must never be called in implementation classes.
87 smart_device(do_not_use_in_implementation_classes);
88
89 public:
90 virtual ~smart_device() throw();
91
92 // Attributes
93 public:
94 ///////////////////////////////////////////////
95 // Dynamic downcasts to actual device flavor
96
97 /// Return true if ATA device
98 bool is_ata() const
99 { return !!m_ata_ptr; }
100 /// Return true if SCSI device
101 bool is_scsi() const
102 { return !!m_scsi_ptr; }
103
104 /// Downcast to ATA device.
105 ata_device * to_ata()
106 { return m_ata_ptr; }
107 /// Downcast to ATA device (const).
108 const ata_device * to_ata() const
109 { return m_ata_ptr; }
110 /// Downcast to SCSI device.
111 scsi_device * to_scsi()
112 { return m_scsi_ptr; }
113 /// Downcast to ATA device (const).
114 const scsi_device * to_scsi() const
115 { return m_scsi_ptr; }
116
117 ///////////////////////////////////////////////
118 // Device information
119
120 /// Get device info struct.
121 const device_info & get_info() const
122 { return m_info; }
123
124 /// Get device (path)name.
125 const char * get_dev_name() const
126 { return m_info.dev_name.c_str(); }
127 /// Get informal name.
128 const char * get_info_name() const
129 { return m_info.info_name.c_str(); }
130 /// Get device type.
131 const char * get_dev_type() const
132 { return m_info.dev_type.c_str(); }
133 /// Get type requested by user, empty if none.
134 const char * get_req_type() const
135 { return m_info.req_type.c_str(); }
136
137 protected:
138 /// R/W access to device info struct.
139 device_info & set_info()
140 { return m_info; }
141
142 public:
143 ///////////////////////////////////////////////
144 // Last error information
145
146 /// Get last error info struct.
147 const error_info & get_err() const
148 { return m_err; }
149 /// Get last error number.
150 int get_errno() const
151 { return m_err.no; }
152 /// Get last error message.
153 const char * get_errmsg() const
154 { return m_err.msg.c_str(); }
155
156 /// Set last error number and message.
157 /// Printf()-like formatting is supported.
158 /// Returns false always to allow use as a return expression.
159 bool set_err(int no, const char * msg, ...)
160 __attribute__ ((format (printf, 3, 4)));
161
162 /// Set last error info struct.
163 bool set_err(const error_info & err)
164 { m_err = err; return false; }
165
166 /// Clear last error info.
167 void clear_err()
168 { m_err.clear(); }
169
170 /// Set last error number and default message.
171 /// Message is retrieved from interface's get_msg_for_errno(no).
172 bool set_err(int no);
173
174 // Operations
175 public:
176 ///////////////////////////////////////////////
177 // Device open/close
178 // Must be implemented in derived class
179
180 /// Return true if device is open.
181 virtual bool is_open() const = 0;
182
183 /// Open device, return false on error.
184 virtual bool open() = 0;
185
186 /// Close device, return false on error.
187 virtual bool close() = 0;
188
189 /// Open device with autodetection support.
190 /// May return another device for further access.
191 /// In this case, the original pointer is no longer valid.
192 /// Default Implementation calls 'open()' and returns 'this'.
193 virtual smart_device * autodetect_open();
194
195 ///////////////////////////////////////////////
196 // Support for tunnelled devices
197
198 /// Return true if other device is owned by this device.
199 /// Default implementation returns false.
200 virtual bool owns(const smart_device * dev) const;
201
202 /// Release ownership of other device.
203 /// Default implementation does nothing.
204 virtual void release(const smart_device * dev);
205
206 protected:
207 /// Set dynamic downcast for ATA
208 void this_is_ata(ata_device * ata);
209 // {see below;}
210
211 /// Set dynamic downcast for SCSI
212 void this_is_scsi(scsi_device * scsi);
213 // {see below;}
214
215 /// Get interface which produced this object.
216 smart_interface * smi()
217 { return m_intf; }
218 /// Get interface which produced this object (const).
219 const smart_interface * smi() const
220 { return m_intf; }
221
222 // Implementation
223 private:
224 smart_interface * m_intf;
225 device_info m_info;
226 ata_device * m_ata_ptr;
227 scsi_device * m_scsi_ptr;
228 error_info m_err;
229
230 // Prevent copy/assigment
231 smart_device(const smart_device &);
232 void operator=(const smart_device &);
233 };
234
235
236 /////////////////////////////////////////////////////////////////////////////
237 // ATA specific interface
238
239 /// ATA register value and info whether is has been ever set
240 // (Automatically set by first assignment)
241 class ata_register
242 {
243 public:
244 ata_register()
245 : m_val(0x00), m_is_set(false) { }
246
247 ata_register & operator=(unsigned char val)
248 { m_val = val; m_is_set = true; return * this; }
249
250 unsigned char val() const
251 { return m_val; }
252 operator unsigned char() const
253 { return m_val; }
254
255 bool is_set() const
256 { return m_is_set; }
257
258 private:
259 unsigned char m_val; ///< Register value
260 bool m_is_set; ///< true if set
261 };
262
263 /// ATA Input registers (for 28-bit commands)
264 struct ata_in_regs
265 {
266 // ATA-6/7 register names // ATA-3/4/5 // ATA-8
267 ata_register features; // features // features
268 ata_register sector_count; // sector count // count
269 ata_register lba_low; // sector number // ]
270 ata_register lba_mid; // cylinder low // ] lba
271 ata_register lba_high; // cylinder high // ]
272 ata_register device; // device/head // device
273 ata_register command; // command // command
274
275 /// Return true if any register is set
276 bool is_set() const
277 { return (features.is_set() || sector_count.is_set()
278 || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
279 || device.is_set() || command.is_set()); }
280 };
281
282 /// ATA Output registers (for 28-bit commands)
283 struct ata_out_regs
284 {
285 ata_register error;
286 ata_register sector_count;
287 ata_register lba_low;
288 ata_register lba_mid;
289 ata_register lba_high;
290 ata_register device;
291 ata_register status;
292
293 /// Return true if any register is set
294 bool is_set() const
295 { return (error.is_set() || sector_count.is_set()
296 || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
297 || device.is_set() || status.is_set()); }
298 };
299
300
301 /// 16-bit alias to a 8-bit ATA register pair.
302 class ata_reg_alias_16
303 {
304 public:
305 ata_reg_alias_16(ata_register & lo, ata_register & hi)
306 : m_lo(lo), m_hi(hi) { }
307
308 ata_reg_alias_16 & operator=(unsigned short val)
309 { m_lo = (unsigned char) val;
310 m_hi = (unsigned char)(val >> 8);
311 return * this; }
312
313 unsigned short val() const
314 { return m_lo | (m_hi << 8); }
315 operator unsigned short() const
316 { return m_lo | (m_hi << 8); }
317
318 private:
319 ata_register & m_lo, & m_hi;
320
321 // References must not be copied.
322 ata_reg_alias_16(const ata_reg_alias_16 &);
323 void operator=(const ata_reg_alias_16 &);
324 };
325
326
327 /// ATA Input registers for 48-bit commands
328 // See section 4.14 of T13/1532D Volume 1 Revision 4b
329 //
330 // Uses ATA-6/7 method to specify 16-bit registers as
331 // recent (low byte) and previous (high byte) content of
332 // 8-bit registers.
333 //
334 // (ATA-8 ACS does not longer follow this scheme, it uses
335 // abstract registers with sufficient size and leaves the
336 // actual mapping to the transport layer.)
337 //
338 struct ata_in_regs_48bit
339 : public ata_in_regs // "most recently written" registers
340 {
341 ata_in_regs prev; ///< "previous content"
342
343 // 16-bit aliases for above pair.
344 ata_reg_alias_16 features_16;
345 ata_reg_alias_16 sector_count_16;
346 ata_reg_alias_16 lba_low_16;
347 ata_reg_alias_16 lba_mid_16;
348 ata_reg_alias_16 lba_high_16;
349
350 /// Return true if 48-bit command
351 bool is_48bit_cmd() const
352 { return prev.is_set(); }
353
354 /// Return true if 48-bit command with any nonzero high byte
355 bool is_real_48bit_cmd() const
356 { return ( prev.features || prev.sector_count
357 || prev.lba_low || prev.lba_mid || prev.lba_high); }
358
359 ata_in_regs_48bit();
360 };
361
362
363 /// ATA Output registers for 48-bit commands
364 struct ata_out_regs_48bit
365 : public ata_out_regs // read with HOB=0
366 {
367 ata_out_regs prev; ///< read with HOB=1
368
369 // 16-bit aliases for above pair.
370 ata_reg_alias_16 sector_count_16;
371 ata_reg_alias_16 lba_low_16;
372 ata_reg_alias_16 lba_mid_16;
373 ata_reg_alias_16 lba_high_16;
374
375 ata_out_regs_48bit();
376 };
377
378
379 /// Flags for each ATA output register
380 struct ata_out_regs_flags
381 {
382 bool error, sector_count, lba_low, lba_mid, lba_high, device, status;
383
384 /// Return true if any flag is set.
385 bool is_set() const
386 { return ( error || sector_count || lba_low
387 || lba_mid || lba_high || device || status); }
388
389 /// Default constructor clears all flags.
390 ata_out_regs_flags()
391 : error(false), sector_count(false), lba_low(false), lba_mid(false),
392 lba_high(false), device(false), status(false) { }
393 };
394
395
396 /// ATA pass through input parameters
397 struct ata_cmd_in
398 {
399 ata_in_regs_48bit in_regs; ///< Input registers
400 ata_out_regs_flags out_needed; ///< True if output register value needed
401 enum { no_data = 0, data_in, data_out } direction; ///< I/O direction
402 void * buffer; ///< Pointer to data buffer
403 unsigned size; ///< Size of buffer
404
405 /// Prepare for 28-bit DATA IN command
406 void set_data_in(void * buf, unsigned nsectors)
407 {
408 buffer = buf;
409 in_regs.sector_count = nsectors;
410 direction = data_in;
411 size = nsectors * 512;
412 }
413
414 /// Prepare for 28-bit DATA OUT command
415 void set_data_out(const void * buf, unsigned nsectors)
416 {
417 buffer = const_cast<void *>(buf);
418 in_regs.sector_count = nsectors;
419 direction = data_out;
420 size = nsectors * 512;
421 }
422
423 /// Prepare for 48-bit DATA IN command
424 void set_data_in_48bit(void * buf, unsigned nsectors)
425 {
426 buffer = buf;
427 // Note: This also sets 'in_regs.is_48bit_cmd()'
428 in_regs.sector_count_16 = nsectors;
429 direction = data_in;
430 size = nsectors * 512;
431 }
432
433 ata_cmd_in();
434 };
435
436 /// ATA pass through output parameters
437 struct ata_cmd_out
438 {
439 ata_out_regs_48bit out_regs; ///< Output registers
440
441 ata_cmd_out();
442 };
443
444 /// ATA device access
445 class ata_device
446 : virtual public /*extends*/ smart_device
447 {
448 public:
449 /// ATA pass through.
450 /// Return false on error.
451 /// Must be implemented in derived class.
452 virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0;
453
454 /// ATA pass through without output registers.
455 /// Return false on error.
456 /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
457 bool ata_pass_through(const ata_cmd_in & in);
458
459 /// Return true if OS caches ATA identify sector.
460 /// Default implementation returns false.
461 virtual bool ata_identify_is_cached() const;
462
463 protected:
464 /// Check command input parameters.
465 /// Calls set_err(...) accordingly.
466 bool ata_cmd_is_ok(const ata_cmd_in & in,
467 bool data_out_support = false,
468 bool multi_sector_support = false,
469 bool ata_48bit_support = false);
470
471 /// Default constructor, registers device as ATA.
472 ata_device()
473 : smart_device(never_called)
474 { this_is_ata(this); }
475 };
476
477
478 /////////////////////////////////////////////////////////////////////////////
479 // SCSI specific interface
480
481 struct scsi_cmnd_io;
482
483 /// SCSI device access
484 class scsi_device
485 : virtual public /*extends*/ smart_device
486 {
487 public:
488 /// SCSI pass through.
489 /// Returns false on error.
490 virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
491
492 protected:
493 /// Default constructor, registers device as SCSI.
494 scsi_device()
495 : smart_device(never_called)
496 { this_is_scsi(this); }
497 };
498
499
500 /////////////////////////////////////////////////////////////////////////////
501
502 // Set dynamic downcasts
503 // Note that due to virtual inheritance,
504 // (ata == this) does not imply ((void*)ata == (void*)this))
505
506 inline void smart_device::this_is_ata(ata_device * ata)
507 {
508 m_ata_ptr = (ata == this ? ata : 0);
509 }
510
511 inline void smart_device::this_is_scsi(scsi_device * scsi)
512 {
513 m_scsi_ptr = (scsi == this ? scsi : 0);
514 }
515
516
517 /////////////////////////////////////////////////////////////////////////////
518 // smart_device_list
519
520 /// List of devices for DEVICESCAN
521 class smart_device_list
522 {
523 // Construction
524 public:
525 smart_device_list()
526 { }
527
528 ~smart_device_list() throw()
529 {
530 for (unsigned i = 0; i < m_list.size(); i++)
531 delete m_list[i];
532 }
533
534 // Attributes
535 unsigned size() const
536 { return m_list.size(); }
537
538 // Operations
539 void clear()
540 {
541 for (unsigned i = 0; i < m_list.size(); i++)
542 delete m_list[i];
543 m_list.clear();
544 }
545
546
547 void add(smart_device * dev)
548 { m_list.push_back(dev); }
549
550 void push_back(smart_device * dev)
551 { m_list.push_back(dev); }
552
553 smart_device * at(unsigned i)
554 { return m_list.at(i); }
555
556 const smart_device * at(unsigned i) const
557 { return m_list.at(i); }
558
559 smart_device * release(unsigned i)
560 {
561 smart_device * dev = m_list.at(i);
562 m_list[i] = 0;
563 return dev;
564 }
565
566 // Implementation
567 private:
568 std::vector<smart_device *> m_list;
569
570 // Prevent copy/assigment
571 smart_device_list(const smart_device_list &);
572 void operator=(const smart_device_list &);
573 };
574
575
576 /////////////////////////////////////////////////////////////////////////////
577 // smart_interface
578
579 /// The platform interface abstraction
580 class smart_interface
581 {
582 public:
583 /// Initialize platform interface and register with smi().
584 /// Must be implemented by platform module and register interface with set()
585 static void init();
586
587 smart_interface()
588 { }
589
590 virtual ~smart_interface() throw()
591 { }
592
593 /// Return build host and OS version as static string
594 virtual const char * get_os_version_str();
595
596 /// Return valid args for device type option/directive.
597 /// Default implementation returns "ata, scsi" concatenated
598 /// with result from get_valid_custom_dev_types_str() below.
599 virtual const char * get_valid_dev_types_str();
600
601 /// Return example string for program 'appname'.
602 /// Default implementation returns 0.
603 /// For the migration of print_smartctl_examples(),
604 /// function is allowed to print examples to stdout.
605 /// TODO: Remove this hack.
606 virtual const char * get_app_examples(const char * appname);
607
608 ///////////////////////////////////////////////
609 // Last error information
610
611 /// Get last error info struct.
612 const smart_device::error_info & get_err() const
613 { return m_err; }
614 /// Get last error number.
615 int get_errno() const
616 { return m_err.no; }
617 /// Get last error message.
618 const char * get_errmsg() const
619 { return m_err.msg.c_str(); }
620
621 /// Set last error number and message.
622 /// Printf()-like formatting is supported.
623 void set_err(int no, const char * msg, ...)
624 __attribute__ ((format (printf, 3, 4)));
625
626 /// Set last error info struct.
627 void set_err(const smart_device::error_info & err)
628 { m_err = err; }
629
630 /// Clear last error info.
631 void clear_err()
632 { m_err.clear(); }
633
634 /// Set last error number and default message.
635 /// Message is retrieved from get_msg_for_errno(no).
636 void set_err(int no);
637
638 /// Set last error number and default message to any error_info.
639 /// Used by set_err(no).
640 void set_err_var(smart_device::error_info * err, int no);
641
642 /// Convert error number into message, used by set_err(no).
643 /// Default implementation returns strerror(no).
644 virtual const char * get_msg_for_errno(int no);
645
646 ///////////////////////////////////////////////////////////////////////////
647 // Device factory:
648
649 /// Return device object for device 'name' with some 'type'.
650 /// 'type' is 0 if not specified by user.
651 /// Return 0 on error.
652 /// Default implementation selects between ata, scsi and custom device.
653 virtual smart_device * get_smart_device(const char * name, const char * type);
654
655 /// Fill 'devlist' with devices of some 'type' with devices names.
656 /// specified by some optional 'pattern'.
657 /// Return false on error.
658 virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
659 const char * pattern = 0) = 0;
660
661 protected:
662 /// Return standard ATA device.
663 virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
664
665 /// Return standard SCSI device.
666 virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
667
668 /// Autodetect device if no device type specified.
669 virtual smart_device * autodetect_smart_device(const char * name) = 0;
670
671 /// Return device for platform specific 'type'.
672 /// Default implementation returns 0.
673 virtual smart_device * get_custom_smart_device(const char * name, const char * type);
674
675 /// Return valid 'type' args accepted by above.
676 /// This is called in get_valid_dev_types_str().
677 /// Default implementation returns 0.
678 virtual const char * get_valid_custom_dev_types_str();
679
680 /// Return ATA->SCSI filter for SAT or USB.
681 /// Override only if platform needs special handling.
682 virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
683 //{ implemented in scsiata.cpp }
684
685 public:
686 /// Try to detect a SAT device behind a SCSI interface.
687 /// Inquiry data can be passed if available.
688 /// Return appropriate device if yes, otherwise 0.
689 /// Override only if platform needs special handling.
690 virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
691 const unsigned char * inqdata, unsigned inqsize);
692 //{ implemented in scsiata.cpp }
693
694 /// Get type name for USB device with known VENDOR:PRODUCT ID.
695 /// Return name if device known and supported, otherwise 0.
696 virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
697 int version = -1);
698 //{ implemented in scsiata.cpp }
699
700 protected:
701 /// Set interface to use, must be called from init().
702 static void set(smart_interface * intf)
703 { s_instance = intf; }
704
705 // Implementation
706 private:
707 smart_device::error_info m_err;
708
709 friend smart_interface * smi(); // below
710 static smart_interface * s_instance; ///< Pointer to the interface object.
711
712 // Prevent copy/assigment
713 smart_interface(const smart_interface &);
714 void operator=(const smart_interface &);
715 };
716
717
718 /////////////////////////////////////////////////////////////////////////////
719 // smi()
720
721 /// Global access to the (usually singleton) smart_interface
722 inline smart_interface * smi()
723 { return smart_interface::s_instance; }
724
725 /////////////////////////////////////////////////////////////////////////////
726
727 #endif // DEV_INTERFACE_H