Annotation of embedaddon/smartmontools/dev_interface.h, revision 1.1.1.3
1.1 misho 1: /*
2: * dev_interface.h
3: *
4: * Home page of code is: http://smartmontools.sourceforge.net
5: *
1.1.1.2 misho 6: * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
1.1 misho 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:
1.1.1.3 ! misho 21: #define DEV_INTERFACE_H_CVSID "$Id: dev_interface.h 3663 2012-10-24 20:35:55Z chrfranke $\n"
1.1.1.2 misho 22:
23: #include "utility.h"
1.1 misho 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:
37: /// Base class for all devices
38: class smart_device
39: {
40: // Types
41: public:
42: /// Device info strings
43: struct device_info {
44: device_info()
45: { }
46: device_info(const char * d_name, const char * d_type, const char * r_type)
47: : dev_name(d_name), info_name(d_name),
48: dev_type(d_type), req_type(r_type)
49: { }
50:
51: std::string dev_name; ///< Device (path)name
52: std::string info_name; ///< Informal name
53: std::string dev_type; ///< Actual device type
54: std::string req_type; ///< Device type requested by user, empty if none
55: };
56:
57: /// Error (number,message) pair
58: struct error_info {
59: explicit error_info(int n = 0)
60: : no(n) { }
61: error_info(int n, const char * m)
62: : no(n), msg(m) { }
63: void clear()
64: { no = 0; msg.erase(); }
65:
66: int no; ///< Error number
67: std::string msg; ///< Error message
68: };
69:
70: // Construction
71: protected:
72: /// Constructor to init interface and device info.
73: /// Must be called in implementation classes.
74: smart_device(smart_interface * intf, const char * dev_name,
75: const char * dev_type, const char * req_type);
76:
77: /// Dummy enum for dummy constructor.
78: enum do_not_use_in_implementation_classes { never_called };
79: /// Dummy constructor for abstract classes.
80: /// Must never be called in implementation classes.
81: smart_device(do_not_use_in_implementation_classes);
82:
83: public:
84: virtual ~smart_device() throw();
85:
86: // Attributes
87: public:
88: ///////////////////////////////////////////////
89: // Dynamic downcasts to actual device flavor
90:
91: /// Return true if ATA device
92: bool is_ata() const
93: { return !!m_ata_ptr; }
94: /// Return true if SCSI device
95: bool is_scsi() const
96: { return !!m_scsi_ptr; }
97:
98: /// Downcast to ATA device.
99: ata_device * to_ata()
100: { return m_ata_ptr; }
101: /// Downcast to ATA device (const).
102: const ata_device * to_ata() const
103: { return m_ata_ptr; }
104: /// Downcast to SCSI device.
105: scsi_device * to_scsi()
106: { return m_scsi_ptr; }
107: /// Downcast to SCSI device (const).
108: const scsi_device * to_scsi() const
109: { return m_scsi_ptr; }
110:
111: ///////////////////////////////////////////////
112: // Device information
113:
114: /// Get device info struct.
115: const device_info & get_info() const
116: { return m_info; }
117:
118: /// Get device (path)name.
119: const char * get_dev_name() const
120: { return m_info.dev_name.c_str(); }
121: /// Get informal name.
122: const char * get_info_name() const
123: { return m_info.info_name.c_str(); }
124: /// Get device type.
125: const char * get_dev_type() const
126: { return m_info.dev_type.c_str(); }
127: /// Get type requested by user, empty if none.
128: const char * get_req_type() const
129: { return m_info.req_type.c_str(); }
130:
131: protected:
132: /// R/W access to device info struct.
133: device_info & set_info()
134: { return m_info; }
135:
136: public:
137: ///////////////////////////////////////////////
138: // Last error information
139:
140: /// Get last error info struct.
141: const error_info & get_err() const
142: { return m_err; }
143: /// Get last error number.
144: int get_errno() const
145: { return m_err.no; }
146: /// Get last error message.
147: const char * get_errmsg() const
148: { return m_err.msg.c_str(); }
149:
1.1.1.2 misho 150: /// Return true if last error indicates an unsupported system call.
151: /// Default implementation returns true on ENOSYS and ENOTSUP.
152: virtual bool is_syscall_unsup() const;
153:
1.1 misho 154: /// Set last error number and message.
155: /// Printf()-like formatting is supported.
156: /// Returns false always to allow use as a return expression.
157: bool set_err(int no, const char * msg, ...)
1.1.1.2 misho 158: __attribute_format_printf(3, 4);
1.1 misho 159:
160: /// Set last error info struct.
161: bool set_err(const error_info & err)
162: { m_err = err; return false; }
163:
164: /// Clear last error info.
165: void clear_err()
166: { m_err.clear(); }
167:
168: /// Set last error number and default message.
169: /// Message is retrieved from interface's get_msg_for_errno(no).
170: bool set_err(int no);
171:
172: // Operations
173: public:
174: ///////////////////////////////////////////////
175: // Device open/close
176: // Must be implemented in derived class
177:
178: /// Return true if device is open.
179: virtual bool is_open() const = 0;
180:
181: /// Open device, return false on error.
182: virtual bool open() = 0;
183:
184: /// Close device, return false on error.
185: virtual bool close() = 0;
186:
187: /// Open device with autodetection support.
188: /// May return another device for further access.
189: /// In this case, the original pointer is no longer valid.
1.1.1.2 misho 190: /// Default implementation calls 'open()' and returns 'this'.
1.1 misho 191: virtual smart_device * autodetect_open();
192:
193: ///////////////////////////////////////////////
194: // Support for tunnelled devices
195:
196: /// Return true if other device is owned by this device.
197: /// Default implementation returns false.
198: virtual bool owns(const smart_device * dev) const;
199:
200: /// Release ownership of other device.
201: /// Default implementation does nothing.
202: virtual void release(const smart_device * dev);
203:
204: protected:
205: /// Get interface which produced this object.
206: smart_interface * smi()
207: { return m_intf; }
208: /// Get interface which produced this object (const).
209: const smart_interface * smi() const
210: { return m_intf; }
211:
212: // Implementation
213: private:
214: smart_interface * m_intf;
215: device_info m_info;
1.1.1.2 misho 216: error_info m_err;
217:
218: // Pointers for to_ata(), to_scsi(),
219: // set by ATA/SCSI interface classes.
220: friend class ata_device;
1.1 misho 221: ata_device * m_ata_ptr;
1.1.1.2 misho 222: friend class scsi_device;
1.1 misho 223: scsi_device * m_scsi_ptr;
224:
225: // Prevent copy/assigment
226: smart_device(const smart_device &);
227: void operator=(const smart_device &);
228: };
229:
230:
231: /////////////////////////////////////////////////////////////////////////////
232: // ATA specific interface
233:
234: /// ATA register value and info whether it has ever been set
235: // (Automatically set by first assignment)
236: class ata_register
237: {
238: public:
239: ata_register()
240: : m_val(0x00), m_is_set(false) { }
241:
242: ata_register & operator=(unsigned char x)
243: { m_val = x; m_is_set = true; return * this; }
244:
245: unsigned char val() const
246: { return m_val; }
247: operator unsigned char() const
248: { return m_val; }
249:
250: bool is_set() const
251: { return m_is_set; }
252:
253: private:
254: unsigned char m_val; ///< Register value
255: bool m_is_set; ///< true if set
256: };
257:
258: /// ATA Input registers (for 28-bit commands)
259: struct ata_in_regs
260: {
261: // ATA-6/7 register names // ATA-3/4/5 // ATA-8
262: ata_register features; // features // features
263: ata_register sector_count; // sector count // count
264: ata_register lba_low; // sector number // ]
265: ata_register lba_mid; // cylinder low // ] lba
266: ata_register lba_high; // cylinder high // ]
267: ata_register device; // device/head // device
268: ata_register command; // command // command
269:
270: /// Return true if any register is set
271: bool is_set() const
272: { return (features.is_set() || sector_count.is_set()
273: || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
274: || device.is_set() || command.is_set()); }
275: };
276:
277: /// ATA Output registers (for 28-bit commands)
278: struct ata_out_regs
279: {
280: ata_register error;
281: ata_register sector_count;
282: ata_register lba_low;
283: ata_register lba_mid;
284: ata_register lba_high;
285: ata_register device;
286: ata_register status;
287:
288: /// Return true if any register is set
289: bool is_set() const
290: { return (error.is_set() || sector_count.is_set()
291: || lba_low.is_set() || lba_mid.is_set() || lba_high.is_set()
292: || device.is_set() || status.is_set()); }
293: };
294:
295:
296: /// 16-bit alias to a 8-bit ATA register pair.
297: class ata_reg_alias_16
298: {
299: public:
300: ata_reg_alias_16(ata_register & lo, ata_register & hi)
301: : m_lo(lo), m_hi(hi) { }
302:
303: ata_reg_alias_16 & operator=(unsigned short x)
304: { m_lo = (unsigned char) x;
305: m_hi = (unsigned char)(x >> 8);
306: return * this; }
307:
308: unsigned short val() const
309: { return m_lo | (m_hi << 8); }
310: operator unsigned short() const
311: { return m_lo | (m_hi << 8); }
312:
313: private:
314: ata_register & m_lo, & m_hi;
315:
316: // References must not be copied.
317: ata_reg_alias_16(const ata_reg_alias_16 &);
318: void operator=(const ata_reg_alias_16 &);
319: };
320:
321:
322: /// 48-bit alias to six 8-bit ATA registers (for LBA).
323: class ata_reg_alias_48
324: {
325: public:
326: ata_reg_alias_48(ata_register & ll, ata_register & lm, ata_register & lh,
327: ata_register & hl, ata_register & hm, ata_register & hh)
328: : m_ll(ll), m_lm(lm), m_lh(lh),
329: m_hl(hl), m_hm(hm), m_hh(hh)
330: { }
331:
332: ata_reg_alias_48 & operator=(uint64_t x)
333: {
334: m_ll = (unsigned char) x;
335: m_lm = (unsigned char)(x >> 8);
336: m_lh = (unsigned char)(x >> 16);
337: m_hl = (unsigned char)(x >> 24);
338: m_hm = (unsigned char)(x >> 32);
339: m_hh = (unsigned char)(x >> 40);
340: return * this;
341: }
342:
343: uint64_t val() const
344: {
345: return ( (unsigned)m_ll
346: | ((unsigned)m_lm << 8)
347: | ((unsigned)m_lh << 16)
348: | ((unsigned)m_hl << 24)
349: | ((uint64_t)m_hm << 32)
350: | ((uint64_t)m_hh << 40));
351: }
352:
353: operator uint64_t() const
354: { return val(); }
355:
356: private:
357: ata_register & m_ll, & m_lm, & m_lh,
358: & m_hl, & m_hm, & m_hh;
359:
360: // References must not be copied.
361: ata_reg_alias_48(const ata_reg_alias_48 &);
362: void operator=(const ata_reg_alias_48 &);
363: };
364:
365:
366: /// ATA Input registers for 48-bit commands
367: // See section 4.14 of T13/1532D Volume 1 Revision 4b
368: //
369: // Uses ATA-6/7 method to specify 16-bit registers as
370: // recent (low byte) and previous (high byte) content of
371: // 8-bit registers.
372: //
373: // (ATA-8 ACS does not longer follow this scheme, it uses
374: // abstract registers with sufficient size and leaves the
375: // actual mapping to the transport layer.)
376: //
377: struct ata_in_regs_48bit
378: : public ata_in_regs // "most recently written" registers
379: {
380: ata_in_regs prev; ///< "previous content"
381:
382: // 16-bit aliases for above pair.
383: ata_reg_alias_16 features_16;
384: ata_reg_alias_16 sector_count_16;
385: ata_reg_alias_16 lba_low_16;
386: ata_reg_alias_16 lba_mid_16;
387: ata_reg_alias_16 lba_high_16;
388:
389: // 48-bit alias to all 8-bit LBA registers.
390: ata_reg_alias_48 lba_48;
391:
392: /// Return true if 48-bit command
393: bool is_48bit_cmd() const
394: { return prev.is_set(); }
395:
396: /// Return true if 48-bit command with any nonzero high byte
397: bool is_real_48bit_cmd() const
398: { return ( prev.features || prev.sector_count
399: || prev.lba_low || prev.lba_mid || prev.lba_high); }
400:
401: ata_in_regs_48bit();
402: };
403:
404:
405: /// ATA Output registers for 48-bit commands
406: struct ata_out_regs_48bit
407: : public ata_out_regs // read with HOB=0
408: {
409: ata_out_regs prev; ///< read with HOB=1
410:
411: // 16-bit aliases for above pair.
412: ata_reg_alias_16 sector_count_16;
413: ata_reg_alias_16 lba_low_16;
414: ata_reg_alias_16 lba_mid_16;
415: ata_reg_alias_16 lba_high_16;
416:
417: // 48-bit alias to all 8-bit LBA registers.
418: ata_reg_alias_48 lba_48;
419:
420: ata_out_regs_48bit();
421: };
422:
423:
424: /// Flags for each ATA output register
425: struct ata_out_regs_flags
426: {
427: bool error, sector_count, lba_low, lba_mid, lba_high, device, status;
428:
429: /// Return true if any flag is set.
430: bool is_set() const
431: { return ( error || sector_count || lba_low
432: || lba_mid || lba_high || device || status); }
433:
434: /// Default constructor clears all flags.
435: ata_out_regs_flags()
436: : error(false), sector_count(false), lba_low(false), lba_mid(false),
437: lba_high(false), device(false), status(false) { }
438: };
439:
440:
441: /// ATA pass through input parameters
442: struct ata_cmd_in
443: {
444: ata_in_regs_48bit in_regs; ///< Input registers
445: ata_out_regs_flags out_needed; ///< True if output register value needed
446: enum { no_data = 0, data_in, data_out } direction; ///< I/O direction
447: void * buffer; ///< Pointer to data buffer
448: unsigned size; ///< Size of buffer
449:
450: /// Prepare for 28-bit DATA IN command
451: void set_data_in(void * buf, unsigned nsectors)
452: {
453: buffer = buf;
454: in_regs.sector_count = nsectors;
455: direction = data_in;
456: size = nsectors * 512;
457: }
458:
459: /// Prepare for 28-bit DATA OUT command
460: void set_data_out(const void * buf, unsigned nsectors)
461: {
462: buffer = const_cast<void *>(buf);
463: in_regs.sector_count = nsectors;
464: direction = data_out;
465: size = nsectors * 512;
466: }
467:
468: /// Prepare for 48-bit DATA IN command
469: void set_data_in_48bit(void * buf, unsigned nsectors)
470: {
471: buffer = buf;
472: // Note: This also sets 'in_regs.is_48bit_cmd()'
473: in_regs.sector_count_16 = nsectors;
474: direction = data_in;
475: size = nsectors * 512;
476: }
477:
478: ata_cmd_in();
479: };
480:
481: /// ATA pass through output parameters
482: struct ata_cmd_out
483: {
484: ata_out_regs_48bit out_regs; ///< Output registers
485:
486: ata_cmd_out();
487: };
488:
489: /// ATA device access
490: class ata_device
491: : virtual public /*extends*/ smart_device
492: {
493: public:
494: /// ATA pass through.
495: /// Return false on error.
496: /// Must be implemented in derived class.
497: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0;
498:
499: /// ATA pass through without output registers.
500: /// Return false on error.
501: /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
502: bool ata_pass_through(const ata_cmd_in & in);
503:
504: /// Return true if OS caches ATA identify sector.
505: /// Default implementation returns false.
506: virtual bool ata_identify_is_cached() const;
507:
508: protected:
1.1.1.3 ! misho 509: /// Flags for ata_cmd_is_supported().
! 510: enum {
! 511: supports_data_out = 0x01, // PIO DATA OUT
! 512: supports_smart_status = 0x02, // read output registers for SMART STATUS only
! 513: supports_output_regs = 0x04, // read output registers for all commands
! 514: supports_multi_sector = 0x08, // more than one sector (1 DRQ/sector variant)
! 515: supports_48bit_hi_null = 0x10, // 48-bit commands with null high bytes only
! 516: supports_48bit = 0x20, // all 48-bit commands
! 517: };
! 518:
1.1 misho 519: /// Check command input parameters.
1.1.1.3 ! misho 520: /// Return false if required features are not implemented.
1.1 misho 521: /// Calls set_err(...) accordingly.
1.1.1.3 ! misho 522: bool ata_cmd_is_supported(const ata_cmd_in & in, unsigned flags,
! 523: const char * type = 0);
! 524:
! 525: /// Check command input parameters (old version).
! 526: // TODO: Remove if no longer used.
1.1 misho 527: bool ata_cmd_is_ok(const ata_cmd_in & in,
528: bool data_out_support = false,
529: bool multi_sector_support = false,
1.1.1.3 ! misho 530: bool ata_48bit_support = false)
! 531: {
! 532: return ata_cmd_is_supported(in,
! 533: (data_out_support ? supports_data_out : 0) |
! 534: supports_output_regs |
! 535: (multi_sector_support ? supports_multi_sector : 0) |
! 536: (ata_48bit_support ? supports_48bit : 0));
! 537: }
1.1 misho 538:
1.1.1.2 misho 539: /// Hide/unhide ATA interface.
540: void hide_ata(bool hide = true)
541: { m_ata_ptr = (!hide ? this : 0); }
542:
1.1 misho 543: /// Default constructor, registers device as ATA.
544: ata_device()
545: : smart_device(never_called)
1.1.1.2 misho 546: { hide_ata(false); }
1.1 misho 547: };
548:
549:
550: /////////////////////////////////////////////////////////////////////////////
551: // SCSI specific interface
552:
553: struct scsi_cmnd_io;
554:
555: /// SCSI device access
556: class scsi_device
557: : virtual public /*extends*/ smart_device
558: {
559: public:
560: /// SCSI pass through.
561: /// Returns false on error.
562: virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
563:
564: protected:
1.1.1.2 misho 565: /// Hide/unhide SCSI interface.
566: void hide_scsi(bool hide = true)
567: { m_scsi_ptr = (!hide ? this : 0); }
568:
1.1 misho 569: /// Default constructor, registers device as SCSI.
570: scsi_device()
571: : smart_device(never_called)
1.1.1.2 misho 572: { hide_scsi(false); }
1.1 misho 573: };
574:
575:
576: /////////////////////////////////////////////////////////////////////////////
577: /// Smart pointer class for device pointers
578:
579: template <class Dev>
580: class any_device_auto_ptr
581: {
582: public:
583: typedef Dev device_type;
584:
585: /// Construct from optional pointer to device
586: /// and optional pointer to base device.
587: explicit any_device_auto_ptr(device_type * dev = 0,
588: smart_device * base_dev = 0)
589: : m_dev(dev), m_base_dev(base_dev) { }
590:
591: /// Destructor deletes device object.
592: ~any_device_auto_ptr() throw()
593: { reset(); }
594:
595: /// Assign a new pointer.
596: /// Throws if a pointer is already assigned.
597: void operator=(device_type * dev)
598: {
599: if (m_dev)
600: fail();
601: m_dev = dev;
602: }
603:
604: /// Delete device object and clear the pointer.
605: void reset()
606: {
607: if (m_dev) {
608: if (m_base_dev && m_dev->owns(m_base_dev))
609: m_dev->release(m_base_dev);
610: delete m_dev;
611: m_dev = 0;
612: }
613: }
614:
615: /// Return the pointer and release ownership.
616: device_type * release()
617: {
618: device_type * dev = m_dev;
619: m_dev = 0;
620: return dev;
621: }
622:
623: /// Replace the pointer.
624: /// Used to call dev->autodetect_open().
625: void replace(device_type * dev)
626: { m_dev = dev; }
627:
628: /// Return the pointer.
629: device_type * get() const
630: { return m_dev; }
631:
632: /// Pointer dereferencing.
633: device_type & operator*() const
634: { return *m_dev; }
635:
636: /// Pointer dereferencing.
637: device_type * operator->() const
638: { return m_dev; }
639:
640: /// For (ptr != 0) check.
641: operator bool() const
642: { return !!m_dev; }
643:
644: /// For (ptr == 0) check.
645: bool operator !() const
646: { return !m_dev; }
647:
648: private:
649: device_type * m_dev;
650: smart_device * m_base_dev;
651:
652: void fail() const
653: { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
654:
655: // Prevent copy/assignment
656: any_device_auto_ptr(const any_device_auto_ptr<Dev> &);
657: void operator=(const any_device_auto_ptr<Dev> &);
658: };
659:
660: typedef any_device_auto_ptr<smart_device> smart_device_auto_ptr;
661: typedef any_device_auto_ptr<ata_device> ata_device_auto_ptr;
662: typedef any_device_auto_ptr<scsi_device> scsi_device_auto_ptr;
663:
664:
665: /////////////////////////////////////////////////////////////////////////////
666: // smart_device_list
667:
668: /// List of devices for DEVICESCAN
669: class smart_device_list
670: {
671: // Construction
672: public:
673: smart_device_list()
674: { }
675:
676: ~smart_device_list() throw()
677: {
678: for (unsigned i = 0; i < m_list.size(); i++)
679: delete m_list[i];
680: }
681:
682: // Attributes
683: unsigned size() const
684: { return m_list.size(); }
685:
686: // Operations
687: void clear()
688: {
689: for (unsigned i = 0; i < m_list.size(); i++)
690: delete m_list[i];
691: m_list.clear();
692: }
693:
694:
695: void push_back(smart_device * dev)
696: { m_list.push_back(dev); }
697:
698: void push_back(smart_device_auto_ptr & dev)
699: {
700: m_list.push_back(dev.get());
701: dev.release();
702: }
703:
704: smart_device * at(unsigned i)
705: { return m_list.at(i); }
706:
707: const smart_device * at(unsigned i) const
708: { return m_list.at(i); }
709:
710: smart_device * release(unsigned i)
711: {
712: smart_device * dev = m_list.at(i);
713: m_list[i] = 0;
714: return dev;
715: }
716:
717: // Implementation
718: private:
719: std::vector<smart_device *> m_list;
720:
721: // Prevent copy/assigment
722: smart_device_list(const smart_device_list &);
723: void operator=(const smart_device_list &);
724: };
725:
726:
727: /////////////////////////////////////////////////////////////////////////////
728: // smart_interface
729:
730: /// The platform interface abstraction
731: class smart_interface
732: {
733: public:
734: /// Initialize platform interface and register with smi().
735: /// Must be implemented by platform module and register interface with set()
736: static void init();
737:
738: smart_interface()
739: { }
740:
741: virtual ~smart_interface() throw()
742: { }
743:
744: /// Return info string about build host and/or OS version.
745: /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
746: virtual std::string get_os_version_str();
747:
748: /// Return valid args for device type option/directive.
749: /// Default implementation returns "ata, scsi, sat, usb*..."
750: /// concatenated with result from get_valid_custom_dev_types_str().
751: virtual std::string get_valid_dev_types_str();
752:
753: /// Return example string for program 'appname'.
754: /// Default implementation returns empty string.
755: /// For the migration of print_smartctl_examples(),
756: /// function is allowed to print examples to stdout.
757: /// TODO: Remove this hack.
758: virtual std::string get_app_examples(const char * appname);
759:
1.1.1.2 misho 760: /// Get microseconds since some unspecified starting point.
761: /// Used only for command duration measurements in debug outputs.
762: /// Returns -1 if unsupported.
763: /// Default implementation uses clock_gettime(), gettimeofday() or ftime().
764: virtual int64_t get_timer_usec();
765:
766: /// Disable/Enable system auto standby/sleep mode.
767: /// Return false if unsupported or if system is running
768: /// on battery.
769: /// Default implementation returns false.
770: virtual bool disable_system_auto_standby(bool disable);
771:
772:
1.1 misho 773: ///////////////////////////////////////////////
774: // Last error information
775:
776: /// Get last error info struct.
777: const smart_device::error_info & get_err() const
778: { return m_err; }
779: /// Get last error number.
780: int get_errno() const
781: { return m_err.no; }
782: /// Get last error message.
783: const char * get_errmsg() const
784: { return m_err.msg.c_str(); }
785:
786: /// Set last error number and message.
787: /// Printf()-like formatting is supported.
1.1.1.2 misho 788: /// Returns false always to allow use as a return expression.
789: bool set_err(int no, const char * msg, ...)
790: __attribute_format_printf(3, 4);
1.1 misho 791:
792: /// Set last error info struct.
1.1.1.2 misho 793: bool set_err(const smart_device::error_info & err)
794: { m_err = err; return false; }
1.1 misho 795:
796: /// Clear last error info.
797: void clear_err()
798: { m_err.clear(); }
799:
800: /// Set last error number and default message.
801: /// Message is retrieved from get_msg_for_errno(no).
1.1.1.2 misho 802: bool set_err(int no);
1.1 misho 803:
804: /// Set last error number and default message to any error_info.
805: /// Used by set_err(no).
1.1.1.2 misho 806: bool set_err_var(smart_device::error_info * err, int no);
1.1 misho 807:
808: /// Convert error number into message, used by set_err(no).
809: /// Default implementation returns strerror(no).
810: virtual const char * get_msg_for_errno(int no);
811:
812: ///////////////////////////////////////////////////////////////////////////
813: // Device factory:
814:
815: /// Return device object for device 'name' with some 'type'.
816: /// 'type' is 0 if not specified by user.
817: /// Return 0 on error.
818: /// Default implementation selects between ata, scsi and custom device.
819: virtual smart_device * get_smart_device(const char * name, const char * type);
820:
821: /// Fill 'devlist' with devices of some 'type' with device names
822: /// specified by some optional 'pattern'.
823: /// Return false on error.
824: virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
825: const char * pattern = 0) = 0;
826:
827: protected:
828: /// Return standard ATA device.
829: virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
830:
831: /// Return standard SCSI device.
832: virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
833:
834: /// Autodetect device if no device type specified.
835: virtual smart_device * autodetect_smart_device(const char * name) = 0;
836:
837: /// Return device for platform specific 'type'.
838: /// Default implementation returns 0.
839: virtual smart_device * get_custom_smart_device(const char * name, const char * type);
840:
841: /// Return valid 'type' args accepted by above.
842: /// This is called in get_valid_dev_types_str().
843: /// Default implementation returns empty string.
844: virtual std::string get_valid_custom_dev_types_str();
845:
846: /// Return ATA->SCSI filter for SAT or USB.
847: /// Override only if platform needs special handling.
848: virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
849: //{ implemented in scsiata.cpp }
850:
851: public:
852: /// Try to detect a SAT device behind a SCSI interface.
853: /// Inquiry data can be passed if available.
854: /// Return appropriate device if yes, otherwise 0.
855: /// Override only if platform needs special handling.
856: virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
857: const unsigned char * inqdata, unsigned inqsize);
858: //{ implemented in scsiata.cpp }
859:
860: /// Get type name for USB device with known VENDOR:PRODUCT ID.
861: /// Return name if device known and supported, otherwise 0.
862: virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
863: int version = -1);
864: //{ implemented in scsiata.cpp }
865:
866: protected:
867: /// Set interface to use, must be called from init().
868: static void set(smart_interface * intf)
869: { s_instance = intf; }
870:
871: // Implementation
872: private:
873: smart_device::error_info m_err;
874:
875: friend smart_interface * smi(); // below
876: static smart_interface * s_instance; ///< Pointer to the interface object.
877:
878: // Prevent copy/assigment
879: smart_interface(const smart_interface &);
880: void operator=(const smart_interface &);
881: };
882:
883:
884: /////////////////////////////////////////////////////////////////////////////
885: // smi()
886:
887: /// Global access to the (usually singleton) smart_interface
888: inline smart_interface * smi()
889: { return smart_interface::s_instance; }
890:
891: /////////////////////////////////////////////////////////////////////////////
892:
893: #endif // DEV_INTERFACE_H
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>