Annotation of embedaddon/smartmontools/dev_interface.h, revision 1.1.1.1
1.1 misho 1: /*
2: * dev_interface.h
3: *
4: * Home page of code is: http://smartmontools.sourceforge.net
5: *
6: * Copyright (C) 2008-11 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 3256 2011-02-08 22:13:41Z chrfranke $\n"
22:
23: #include <stdexcept>
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 SCSI 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 it has ever been 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 x)
248: { m_val = x; 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 x)
309: { m_lo = (unsigned char) x;
310: m_hi = (unsigned char)(x >> 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: /// 48-bit alias to six 8-bit ATA registers (for LBA).
328: class ata_reg_alias_48
329: {
330: public:
331: ata_reg_alias_48(ata_register & ll, ata_register & lm, ata_register & lh,
332: ata_register & hl, ata_register & hm, ata_register & hh)
333: : m_ll(ll), m_lm(lm), m_lh(lh),
334: m_hl(hl), m_hm(hm), m_hh(hh)
335: { }
336:
337: ata_reg_alias_48 & operator=(uint64_t x)
338: {
339: m_ll = (unsigned char) x;
340: m_lm = (unsigned char)(x >> 8);
341: m_lh = (unsigned char)(x >> 16);
342: m_hl = (unsigned char)(x >> 24);
343: m_hm = (unsigned char)(x >> 32);
344: m_hh = (unsigned char)(x >> 40);
345: return * this;
346: }
347:
348: uint64_t val() const
349: {
350: return ( (unsigned)m_ll
351: | ((unsigned)m_lm << 8)
352: | ((unsigned)m_lh << 16)
353: | ((unsigned)m_hl << 24)
354: | ((uint64_t)m_hm << 32)
355: | ((uint64_t)m_hh << 40));
356: }
357:
358: operator uint64_t() const
359: { return val(); }
360:
361: private:
362: ata_register & m_ll, & m_lm, & m_lh,
363: & m_hl, & m_hm, & m_hh;
364:
365: // References must not be copied.
366: ata_reg_alias_48(const ata_reg_alias_48 &);
367: void operator=(const ata_reg_alias_48 &);
368: };
369:
370:
371: /// ATA Input registers for 48-bit commands
372: // See section 4.14 of T13/1532D Volume 1 Revision 4b
373: //
374: // Uses ATA-6/7 method to specify 16-bit registers as
375: // recent (low byte) and previous (high byte) content of
376: // 8-bit registers.
377: //
378: // (ATA-8 ACS does not longer follow this scheme, it uses
379: // abstract registers with sufficient size and leaves the
380: // actual mapping to the transport layer.)
381: //
382: struct ata_in_regs_48bit
383: : public ata_in_regs // "most recently written" registers
384: {
385: ata_in_regs prev; ///< "previous content"
386:
387: // 16-bit aliases for above pair.
388: ata_reg_alias_16 features_16;
389: ata_reg_alias_16 sector_count_16;
390: ata_reg_alias_16 lba_low_16;
391: ata_reg_alias_16 lba_mid_16;
392: ata_reg_alias_16 lba_high_16;
393:
394: // 48-bit alias to all 8-bit LBA registers.
395: ata_reg_alias_48 lba_48;
396:
397: /// Return true if 48-bit command
398: bool is_48bit_cmd() const
399: { return prev.is_set(); }
400:
401: /// Return true if 48-bit command with any nonzero high byte
402: bool is_real_48bit_cmd() const
403: { return ( prev.features || prev.sector_count
404: || prev.lba_low || prev.lba_mid || prev.lba_high); }
405:
406: ata_in_regs_48bit();
407: };
408:
409:
410: /// ATA Output registers for 48-bit commands
411: struct ata_out_regs_48bit
412: : public ata_out_regs // read with HOB=0
413: {
414: ata_out_regs prev; ///< read with HOB=1
415:
416: // 16-bit aliases for above pair.
417: ata_reg_alias_16 sector_count_16;
418: ata_reg_alias_16 lba_low_16;
419: ata_reg_alias_16 lba_mid_16;
420: ata_reg_alias_16 lba_high_16;
421:
422: // 48-bit alias to all 8-bit LBA registers.
423: ata_reg_alias_48 lba_48;
424:
425: ata_out_regs_48bit();
426: };
427:
428:
429: /// Flags for each ATA output register
430: struct ata_out_regs_flags
431: {
432: bool error, sector_count, lba_low, lba_mid, lba_high, device, status;
433:
434: /// Return true if any flag is set.
435: bool is_set() const
436: { return ( error || sector_count || lba_low
437: || lba_mid || lba_high || device || status); }
438:
439: /// Default constructor clears all flags.
440: ata_out_regs_flags()
441: : error(false), sector_count(false), lba_low(false), lba_mid(false),
442: lba_high(false), device(false), status(false) { }
443: };
444:
445:
446: /// ATA pass through input parameters
447: struct ata_cmd_in
448: {
449: ata_in_regs_48bit in_regs; ///< Input registers
450: ata_out_regs_flags out_needed; ///< True if output register value needed
451: enum { no_data = 0, data_in, data_out } direction; ///< I/O direction
452: void * buffer; ///< Pointer to data buffer
453: unsigned size; ///< Size of buffer
454:
455: /// Prepare for 28-bit DATA IN command
456: void set_data_in(void * buf, unsigned nsectors)
457: {
458: buffer = buf;
459: in_regs.sector_count = nsectors;
460: direction = data_in;
461: size = nsectors * 512;
462: }
463:
464: /// Prepare for 28-bit DATA OUT command
465: void set_data_out(const void * buf, unsigned nsectors)
466: {
467: buffer = const_cast<void *>(buf);
468: in_regs.sector_count = nsectors;
469: direction = data_out;
470: size = nsectors * 512;
471: }
472:
473: /// Prepare for 48-bit DATA IN command
474: void set_data_in_48bit(void * buf, unsigned nsectors)
475: {
476: buffer = buf;
477: // Note: This also sets 'in_regs.is_48bit_cmd()'
478: in_regs.sector_count_16 = nsectors;
479: direction = data_in;
480: size = nsectors * 512;
481: }
482:
483: ata_cmd_in();
484: };
485:
486: /// ATA pass through output parameters
487: struct ata_cmd_out
488: {
489: ata_out_regs_48bit out_regs; ///< Output registers
490:
491: ata_cmd_out();
492: };
493:
494: /// ATA device access
495: class ata_device
496: : virtual public /*extends*/ smart_device
497: {
498: public:
499: /// ATA pass through.
500: /// Return false on error.
501: /// Must be implemented in derived class.
502: virtual bool ata_pass_through(const ata_cmd_in & in, ata_cmd_out & out) = 0;
503:
504: /// ATA pass through without output registers.
505: /// Return false on error.
506: /// Calls ata_pass_through(in, dummy), cannot be reimplemented.
507: bool ata_pass_through(const ata_cmd_in & in);
508:
509: /// Return true if OS caches ATA identify sector.
510: /// Default implementation returns false.
511: virtual bool ata_identify_is_cached() const;
512:
513: protected:
514: /// Check command input parameters.
515: /// Calls set_err(...) accordingly.
516: bool ata_cmd_is_ok(const ata_cmd_in & in,
517: bool data_out_support = false,
518: bool multi_sector_support = false,
519: bool ata_48bit_support = false);
520:
521: /// Default constructor, registers device as ATA.
522: ata_device()
523: : smart_device(never_called)
524: { this_is_ata(this); }
525: };
526:
527:
528: /////////////////////////////////////////////////////////////////////////////
529: // SCSI specific interface
530:
531: struct scsi_cmnd_io;
532:
533: /// SCSI device access
534: class scsi_device
535: : virtual public /*extends*/ smart_device
536: {
537: public:
538: /// SCSI pass through.
539: /// Returns false on error.
540: virtual bool scsi_pass_through(scsi_cmnd_io * iop) = 0;
541:
542: protected:
543: /// Default constructor, registers device as SCSI.
544: scsi_device()
545: : smart_device(never_called)
546: { this_is_scsi(this); }
547: };
548:
549:
550: /////////////////////////////////////////////////////////////////////////////
551:
552: // Set dynamic downcasts
553: // Note that due to virtual inheritance,
554: // (ata == this) does not imply ((void*)ata == (void*)this))
555:
556: inline void smart_device::this_is_ata(ata_device * ata)
557: {
558: m_ata_ptr = (ata == this ? ata : 0);
559: }
560:
561: inline void smart_device::this_is_scsi(scsi_device * scsi)
562: {
563: m_scsi_ptr = (scsi == this ? scsi : 0);
564: }
565:
566:
567: /////////////////////////////////////////////////////////////////////////////
568: /// Smart pointer class for device pointers
569:
570: template <class Dev>
571: class any_device_auto_ptr
572: {
573: public:
574: typedef Dev device_type;
575:
576: /// Construct from optional pointer to device
577: /// and optional pointer to base device.
578: explicit any_device_auto_ptr(device_type * dev = 0,
579: smart_device * base_dev = 0)
580: : m_dev(dev), m_base_dev(base_dev) { }
581:
582: /// Destructor deletes device object.
583: ~any_device_auto_ptr() throw()
584: { reset(); }
585:
586: /// Assign a new pointer.
587: /// Throws if a pointer is already assigned.
588: void operator=(device_type * dev)
589: {
590: if (m_dev)
591: fail();
592: m_dev = dev;
593: }
594:
595: /// Delete device object and clear the pointer.
596: void reset()
597: {
598: if (m_dev) {
599: if (m_base_dev && m_dev->owns(m_base_dev))
600: m_dev->release(m_base_dev);
601: delete m_dev;
602: m_dev = 0;
603: }
604: }
605:
606: /// Return the pointer and release ownership.
607: device_type * release()
608: {
609: device_type * dev = m_dev;
610: m_dev = 0;
611: return dev;
612: }
613:
614: /// Replace the pointer.
615: /// Used to call dev->autodetect_open().
616: void replace(device_type * dev)
617: { m_dev = dev; }
618:
619: /// Return the pointer.
620: device_type * get() const
621: { return m_dev; }
622:
623: /// Pointer dereferencing.
624: device_type & operator*() const
625: { return *m_dev; }
626:
627: /// Pointer dereferencing.
628: device_type * operator->() const
629: { return m_dev; }
630:
631: /// For (ptr != 0) check.
632: operator bool() const
633: { return !!m_dev; }
634:
635: /// For (ptr == 0) check.
636: bool operator !() const
637: { return !m_dev; }
638:
639: private:
640: device_type * m_dev;
641: smart_device * m_base_dev;
642:
643: void fail() const
644: { throw std::logic_error("any_device_auto_ptr: wrong usage"); }
645:
646: // Prevent copy/assignment
647: any_device_auto_ptr(const any_device_auto_ptr<Dev> &);
648: void operator=(const any_device_auto_ptr<Dev> &);
649: };
650:
651: typedef any_device_auto_ptr<smart_device> smart_device_auto_ptr;
652: typedef any_device_auto_ptr<ata_device> ata_device_auto_ptr;
653: typedef any_device_auto_ptr<scsi_device> scsi_device_auto_ptr;
654:
655:
656: /////////////////////////////////////////////////////////////////////////////
657: // smart_device_list
658:
659: /// List of devices for DEVICESCAN
660: class smart_device_list
661: {
662: // Construction
663: public:
664: smart_device_list()
665: { }
666:
667: ~smart_device_list() throw()
668: {
669: for (unsigned i = 0; i < m_list.size(); i++)
670: delete m_list[i];
671: }
672:
673: // Attributes
674: unsigned size() const
675: { return m_list.size(); }
676:
677: // Operations
678: void clear()
679: {
680: for (unsigned i = 0; i < m_list.size(); i++)
681: delete m_list[i];
682: m_list.clear();
683: }
684:
685:
686: void push_back(smart_device * dev)
687: { m_list.push_back(dev); }
688:
689: void push_back(smart_device_auto_ptr & dev)
690: {
691: m_list.push_back(dev.get());
692: dev.release();
693: }
694:
695: smart_device * at(unsigned i)
696: { return m_list.at(i); }
697:
698: const smart_device * at(unsigned i) const
699: { return m_list.at(i); }
700:
701: smart_device * release(unsigned i)
702: {
703: smart_device * dev = m_list.at(i);
704: m_list[i] = 0;
705: return dev;
706: }
707:
708: // Implementation
709: private:
710: std::vector<smart_device *> m_list;
711:
712: // Prevent copy/assigment
713: smart_device_list(const smart_device_list &);
714: void operator=(const smart_device_list &);
715: };
716:
717:
718: /////////////////////////////////////////////////////////////////////////////
719: // smart_interface
720:
721: /// The platform interface abstraction
722: class smart_interface
723: {
724: public:
725: /// Initialize platform interface and register with smi().
726: /// Must be implemented by platform module and register interface with set()
727: static void init();
728:
729: smart_interface()
730: { }
731:
732: virtual ~smart_interface() throw()
733: { }
734:
735: /// Return info string about build host and/or OS version.
736: /// Default implementation returns SMARTMONTOOLS_BUILD_HOST.
737: virtual std::string get_os_version_str();
738:
739: /// Return valid args for device type option/directive.
740: /// Default implementation returns "ata, scsi, sat, usb*..."
741: /// concatenated with result from get_valid_custom_dev_types_str().
742: virtual std::string get_valid_dev_types_str();
743:
744: /// Return example string for program 'appname'.
745: /// Default implementation returns empty string.
746: /// For the migration of print_smartctl_examples(),
747: /// function is allowed to print examples to stdout.
748: /// TODO: Remove this hack.
749: virtual std::string get_app_examples(const char * appname);
750:
751: ///////////////////////////////////////////////
752: // Last error information
753:
754: /// Get last error info struct.
755: const smart_device::error_info & get_err() const
756: { return m_err; }
757: /// Get last error number.
758: int get_errno() const
759: { return m_err.no; }
760: /// Get last error message.
761: const char * get_errmsg() const
762: { return m_err.msg.c_str(); }
763:
764: /// Set last error number and message.
765: /// Printf()-like formatting is supported.
766: void set_err(int no, const char * msg, ...)
767: __attribute__ ((format (printf, 3, 4)));
768:
769: /// Set last error info struct.
770: void set_err(const smart_device::error_info & err)
771: { m_err = err; }
772:
773: /// Clear last error info.
774: void clear_err()
775: { m_err.clear(); }
776:
777: /// Set last error number and default message.
778: /// Message is retrieved from get_msg_for_errno(no).
779: void set_err(int no);
780:
781: /// Set last error number and default message to any error_info.
782: /// Used by set_err(no).
783: void set_err_var(smart_device::error_info * err, int no);
784:
785: /// Convert error number into message, used by set_err(no).
786: /// Default implementation returns strerror(no).
787: virtual const char * get_msg_for_errno(int no);
788:
789: ///////////////////////////////////////////////////////////////////////////
790: // Device factory:
791:
792: /// Return device object for device 'name' with some 'type'.
793: /// 'type' is 0 if not specified by user.
794: /// Return 0 on error.
795: /// Default implementation selects between ata, scsi and custom device.
796: virtual smart_device * get_smart_device(const char * name, const char * type);
797:
798: /// Fill 'devlist' with devices of some 'type' with device names
799: /// specified by some optional 'pattern'.
800: /// Return false on error.
801: virtual bool scan_smart_devices(smart_device_list & devlist, const char * type,
802: const char * pattern = 0) = 0;
803:
804: protected:
805: /// Return standard ATA device.
806: virtual ata_device * get_ata_device(const char * name, const char * type) = 0;
807:
808: /// Return standard SCSI device.
809: virtual scsi_device * get_scsi_device(const char * name, const char * type) = 0;
810:
811: /// Autodetect device if no device type specified.
812: virtual smart_device * autodetect_smart_device(const char * name) = 0;
813:
814: /// Return device for platform specific 'type'.
815: /// Default implementation returns 0.
816: virtual smart_device * get_custom_smart_device(const char * name, const char * type);
817:
818: /// Return valid 'type' args accepted by above.
819: /// This is called in get_valid_dev_types_str().
820: /// Default implementation returns empty string.
821: virtual std::string get_valid_custom_dev_types_str();
822:
823: /// Return ATA->SCSI filter for SAT or USB.
824: /// Override only if platform needs special handling.
825: virtual ata_device * get_sat_device(const char * type, scsi_device * scsidev);
826: //{ implemented in scsiata.cpp }
827:
828: public:
829: /// Try to detect a SAT device behind a SCSI interface.
830: /// Inquiry data can be passed if available.
831: /// Return appropriate device if yes, otherwise 0.
832: /// Override only if platform needs special handling.
833: virtual ata_device * autodetect_sat_device(scsi_device * scsidev,
834: const unsigned char * inqdata, unsigned inqsize);
835: //{ implemented in scsiata.cpp }
836:
837: /// Get type name for USB device with known VENDOR:PRODUCT ID.
838: /// Return name if device known and supported, otherwise 0.
839: virtual const char * get_usb_dev_type_by_id(int vendor_id, int product_id,
840: int version = -1);
841: //{ implemented in scsiata.cpp }
842:
843: protected:
844: /// Set interface to use, must be called from init().
845: static void set(smart_interface * intf)
846: { s_instance = intf; }
847:
848: // Implementation
849: private:
850: smart_device::error_info m_err;
851:
852: friend smart_interface * smi(); // below
853: static smart_interface * s_instance; ///< Pointer to the interface object.
854:
855: // Prevent copy/assigment
856: smart_interface(const smart_interface &);
857: void operator=(const smart_interface &);
858: };
859:
860:
861: /////////////////////////////////////////////////////////////////////////////
862: // smi()
863:
864: /// Global access to the (usually singleton) smart_interface
865: inline smart_interface * smi()
866: { return smart_interface::s_instance; }
867:
868: /////////////////////////////////////////////////////////////////////////////
869:
870: #endif // DEV_INTERFACE_H
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>