diff --git a/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp b/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp
index 97d71f8e4ce0116494b54d349b7bf430e96fd129..a5b63f94a01a4536d502fec0466dad919c336201 100644
--- a/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp
+++ b/tapeserver/castor/tape/tapeserver/SCSI/Constants.hpp
@@ -238,9 +238,18 @@ namespace SCSI {
   class logSensePages {
   public:
     enum {
+      writeErrors                = 0x02,
+      readErrors                 = 0x03,
+      nonMediumErrors            = 0x06,
       sequentialAccessDevicePage = 0x0C,
+      volumeStatistics           = 0x17, // IBM specific page
       tapeAlert                  = 0x2e,
       dataCompression32h         = 0x32, // for LTO, SDLT. We have Data Compression 1Bh for LTO5,6 and DataComppression 0Fh in SSC-3 
+      driveWriteErrors           = 0x32, // IBM specific page
+      driveReadForwardErrors     = 0x34, // IBM specific page
+      driveReadBackwardErrors    = 0x36, // IBM specific page
+      performanceCharacteristics = 0x37, // IBM specific page
+      vendorUniqueDriveStatistics= 0x3d, // Oracle T1000D/E specific page
       blockBytesTransferred      = 0x38  // parameters in this page are reset when a cartridge is loaded
     };
   };
@@ -272,7 +281,109 @@ namespace SCSI {
       unitSerialNumber = 0x80 
     };
   };
-  
+ 
+  class writeErrorsDevicePage {
+  public:
+    enum {
+      totalCorrectedErrors        = 0x0003,
+      totalProcessed              = 0x0005,
+      totalUncorrectedErrors      = 0x0006
+    };
+  };
+
+  class readErrorsDevicePage {
+  public:
+    enum {
+      totalCorrectedErrors        = 0x0003,
+      totalProcessed              = 0x0005,
+      totalUncorrectedErrors      = 0x0006
+    };
+  };
+
+  class nonMediumErrorsDevicePage {
+  public:
+    enum {
+      totalCount                  = 0x0000
+    };
+  };
+
+  class volumeStatisticsPage { // IBM 3592 specific
+  public:
+    enum {
+      validityFlag                            = 0x0000,
+      volumeMounts                            = 0x0001,
+      volumeRecoveredWriteDataErrors          = 0x0003,
+      volumeUnrecoveredWriteDataErrors        = 0x0004,
+      volumeRecoveredReadErrors               = 0x0008,
+      volumeUnrecoveredReadErrors             = 0x0009,
+      volumeManufacturingDate                 = 0x0046,
+      BOTPasses                               = 0x0101,
+      MOTPasses                               = 0x0102
+    };
+  };
+
+  class performanceCharacteristicsQualitySummaryPage { // IBM 3592 specific
+  public:
+    enum {
+      driveEfficiency             = 0x0000,
+      mediaEfficiency             = 0x0001,
+      primaryInterfaceEfficiency0 = 0x0011,
+      primaryInterfaceEfficiency1 = 0x0012,
+      libraryInterfaceEfficiency  = 0x001a
+    };
+  };
+
+  class performanceCharacteristicsHostCommandsPage { // IBM 3592 specific
+  public:
+    enum {
+      readPerformanceEfficiency   = 0x03d0,
+      writePerformanceEfficiency  = 0x04d0
+    };
+  };
+
+  class driveWriteErrorsPage { // IBM 3592 specific
+  public:
+    enum {
+      servoTransients             = 0x0001,
+      dataTransients              = 0x0002,
+      servoTemps                  = 0x0006,
+      dataTemps                   = 0x0007,
+      totalRetries                = 0x0008
+    };
+  };
+
+  class driveReadErrorsPage { // IBM 3592 specific (both FW and BW)
+  public:
+    enum {
+      servoTransients             = 0x0001,
+      dataTransients              = 0x0002,
+      servoTemps                  = 0x0006,
+      dataTemps                   = 0x0007,
+      totalRetries                = 0x0015
+    };
+  };
+
+  class vendorUniqueDriveStatistics { // Oracle T10K specific
+  public:
+    enum {
+      // Drive stats
+      readRecoveryRetries         = 0x0104,
+      readTransientConditions     = 0x0105,
+      writeTransientConditions    = 0x0106,
+      servoTepomporaries          = 0x0107,
+      servoTransientConditions    = 0x0108,
+      writeRecoveryRetries        = 0x0112,
+      temporaryDriveErrors        = 0x0203,
+      permanentDriveErrors        = 0x0204,
+
+      // Quality stats
+      tapeEfficiency              = 0x0400,
+      readQualityIndex            = 0x0401,
+      readBackCheckQualityIndex   = 0x0402,
+      writeEfficiency             = 0x0407
+    };
+  };
+
   /**
    * Sun StorageTekTM T10000 Tape Drive Fibre Channel Interface Reference Manual
    */
diff --git a/tapeserver/castor/tape/tapeserver/SCSI/DeviceTest.cpp b/tapeserver/castor/tape/tapeserver/SCSI/DeviceTest.cpp
index 0d89e4d91bb915d1b9c4b4f040bdbc62971022e8..25b5ed38cdbf574368ffdf49b36db14b02c3b8a9 100644
--- a/tapeserver/castor/tape/tapeserver/SCSI/DeviceTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/SCSI/DeviceTest.cpp
@@ -51,57 +51,97 @@ TEST(castor_tape_SCSI_DeviceList, ScansCorrectly) {
   sysWrapper.delegateToFake();
   /* Populate the test harness */
   sysWrapper.fake.setupSLC5();
+  // TODO: Test against SLC6 setup
 
   /* We expect the following calls: */
   EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
   EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(19);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(38);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(19);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(38);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
+
 
   /* Everything should have been found correctly */
 
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
 
-  ASSERT_EQ(3U, dl.size());
+  ASSERT_EQ(6U, dl.size());
   ASSERT_EQ(castor::tape::SCSI::Types::mediumChanger, dl[0].type);
   ASSERT_EQ(castor::tape::SCSI::Types::tape,          dl[1].type);
   ASSERT_EQ(castor::tape::SCSI::Types::tape,          dl[2].type);
+  ASSERT_EQ(castor::tape::SCSI::Types::mediumChanger, dl[3].type);
+  ASSERT_EQ(castor::tape::SCSI::Types::tape,          dl[4].type);
+  ASSERT_EQ(castor::tape::SCSI::Types::tape,          dl[5].type);
+
   ASSERT_EQ( "/dev/sg2", dl[0].sg_dev);
   ASSERT_EQ( "/dev/sg0", dl[1].sg_dev);
   ASSERT_EQ( "/dev/sg1", dl[2].sg_dev);
+  ASSERT_EQ( "/dev/sg5", dl[3].sg_dev);
+  ASSERT_EQ( "/dev/sg3", dl[4].sg_dev);
+  ASSERT_EQ( "/dev/sg4", dl[5].sg_dev);
+
   ASSERT_EQ(         "", dl[0].st_dev);
   ASSERT_EQ( "/dev/st0", dl[1].st_dev);
   ASSERT_EQ( "/dev/st1", dl[2].st_dev);
+  ASSERT_EQ(         "", dl[3].st_dev);
+  ASSERT_EQ( "/dev/st2", dl[4].st_dev);
+  ASSERT_EQ( "/dev/st3", dl[5].st_dev);
+
   ASSERT_EQ(         "", dl[0].nst_dev);
   ASSERT_EQ("/dev/nst0", dl[1].nst_dev);
   ASSERT_EQ("/dev/nst1", dl[2].nst_dev);
+  ASSERT_EQ(         "", dl[3].nst_dev);
+  ASSERT_EQ("/dev/nst2", dl[4].nst_dev);
+  ASSERT_EQ("/dev/nst3", dl[5].nst_dev);
+
   ASSERT_EQ("/sys/devices/pseudo_0/adapter0/host3/target3:0:0/3:0:0:0", dl[0].sysfs_entry);
   ASSERT_EQ("/sys/devices/pseudo_0/adapter0/host3/target3:0:1/3:0:1:0", dl[1].sysfs_entry);
   ASSERT_EQ("/sys/devices/pseudo_0/adapter0/host3/target3:0:2/3:0:2:0", dl[2].sysfs_entry);
+  ASSERT_EQ("/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0", dl[3].sysfs_entry);
+  ASSERT_EQ("/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0", dl[4].sysfs_entry);
+  ASSERT_EQ("/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0", dl[5].sysfs_entry);
+
   ASSERT_EQ( 21U, dl[0].sg.major);
   ASSERT_EQ(  2U, dl[0].sg.minor);
   ASSERT_EQ( 21U, dl[1].sg.major);
   ASSERT_EQ(  0U, dl[1].sg.minor);
   ASSERT_EQ( 21U, dl[2].sg.major);
   ASSERT_EQ(  1U, dl[2].sg.minor);
+  ASSERT_EQ( 21U, dl[3].sg.major);
+  ASSERT_EQ(  5U, dl[3].sg.minor);
+  ASSERT_EQ( 21U, dl[4].sg.major);
+  ASSERT_EQ(  3U, dl[4].sg.minor);
+  ASSERT_EQ( 21U, dl[5].sg.major);
+  ASSERT_EQ(  4U, dl[5].sg.minor);
   ASSERT_EQ(  0U, dl[0].st.major);
   ASSERT_EQ(  0U, dl[0].st.minor);
   ASSERT_EQ(  9U, dl[1].st.major);
   ASSERT_EQ(  0U, dl[1].st.minor);
   ASSERT_EQ(  9U, dl[2].st.major);
   ASSERT_EQ(  1U, dl[2].st.minor);
+  ASSERT_EQ(  0U, dl[3].st.major);
+  ASSERT_EQ(  0U, dl[3].st.minor);
+  ASSERT_EQ(  9U, dl[4].st.major);
+  ASSERT_EQ(  2U, dl[4].st.minor);
+  ASSERT_EQ(  9U, dl[5].st.major);
+  ASSERT_EQ(  3U, dl[5].st.minor);
   ASSERT_EQ(  0U, dl[0].nst.major);
   ASSERT_EQ(  0U, dl[0].nst.minor);
   ASSERT_EQ(  9U, dl[1].nst.major);
   ASSERT_EQ(128U, dl[1].nst.minor);
   ASSERT_EQ(  9U, dl[2].nst.major);
   ASSERT_EQ(129U, dl[2].nst.minor);
+  ASSERT_EQ(  0U, dl[3].nst.major);
+  ASSERT_EQ(  0U, dl[3].nst.minor);
+  ASSERT_EQ(  9U, dl[4].nst.major);
+  ASSERT_EQ(130U, dl[4].nst.minor);
+  ASSERT_EQ(  9U, dl[5].nst.major);
+  ASSERT_EQ(131U, dl[5].nst.minor);
   ASSERT_EQ("STK", dl[0].vendor);
   ASSERT_EQ("STK", dl[1].vendor);
   ASSERT_EQ("STK", dl[2].vendor);
@@ -111,6 +151,15 @@ TEST(castor_tape_SCSI_DeviceList, ScansCorrectly) {
   ASSERT_EQ("0104", dl[0].productRevisionLevel);
   ASSERT_EQ("0104", dl[1].productRevisionLevel);
   ASSERT_EQ("0104", dl[2].productRevisionLevel);
+  ASSERT_EQ("IBM", dl[3].vendor);
+  ASSERT_EQ("IBM", dl[4].vendor);
+  ASSERT_EQ("IBM", dl[5].vendor);
+  ASSERT_EQ("03584L22", dl[3].product);
+  ASSERT_EQ("03592E08", dl[4].product);
+  ASSERT_EQ("03592E08", dl[5].product);
+  ASSERT_EQ("F030", dl[3].productRevisionLevel);
+  ASSERT_EQ("460E", dl[4].productRevisionLevel);
+  ASSERT_EQ("460E", dl[5].productRevisionLevel);
 }
 
 TEST(castor_tape_SCSI_DeviceList, FindBySymlink) {
diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
index be04595b6764c8bb7bdd1614b19d91d459bfc274..b1e2a124e81a87f21b9bfca3e1838545f410c815 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
@@ -453,6 +453,18 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayRecall) {
     ASSERT_EQ(0, statRc);
     ASSERT_EQ(1000, statBuf.st_size); //same size of data
   }
+
+  // 10) Check logs
+  std::string logToCheck = logger.getLog();
+  logToCheck += "";
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" "
+                                               "mountTotalCorrectedReadErrors=\"5\" mountTotalReadBytesProcessed=\"4096\" "
+                                               "mountTotalUncorrectedReadErrors=\"1\" mountTotalNonMediumErrorCounts=\"2\""));
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                               "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                               "mountReadTransients=\"10\" "
+                                               "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                               "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) {
@@ -621,6 +633,18 @@ TEST_P(DataTransferSessionTest, DataTransferSessionWrongRecall) {
   // 10) Check the remote files exist and have the correct size
   std::string temp = logger.getLog();
   ASSERT_NE(std::string::npos, logger.getLog().find("trying to position beyond the end of data"));
+
+  // 11) Check logs for drive statistics
+  std::string logToCheck = logger.getLog();
+  logToCheck += "";
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" "
+                                               "mountTotalCorrectedReadErrors=\"5\" mountTotalReadBytesProcessed=\"4096\" "
+                                               "mountTotalUncorrectedReadErrors=\"1\" mountTotalNonMediumErrorCounts=\"2\""));
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                               "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                               "mountReadTransients=\"10\" "
+                                               "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                               "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 TEST_P(DataTransferSessionTest, DataTransferSessionNoSuchDrive) {
@@ -894,6 +918,18 @@ TEST_P(DataTransferSessionTest, DataTransferSessionFailtoMount) {
   ASSERT_NO_THROW(sess.execute());
   std::string temp = logger.getLog();
   ASSERT_NE(std::string::npos, logger.getLog().find("Failed to mount the tape"));
+
+  // 10) Check logs for drive statistics
+  std::string logToCheck = logger.getLog();
+  logToCheck += "";
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" "
+                                               "mountTotalCorrectedReadErrors=\"5\" mountTotalReadBytesProcessed=\"4096\" "
+                                               "mountTotalUncorrectedReadErrors=\"1\" mountTotalNonMediumErrorCounts=\"2\""));
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                               "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                               "mountReadTransients=\"10\" "
+                                               "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                               "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 TEST_P(DataTransferSessionTest, DataTransferSessionEmptyOnVolReq) {
@@ -1058,6 +1094,17 @@ TEST_P(DataTransferSessionTest, DataTransferSessionGooddayMigration) {
     ASSERT_EQ(sf->adler32(), afs.checksumValue);
     ASSERT_EQ(1000, afs.fileSize);
   }
+
+  // Check logs for drive statistics
+  ASSERT_NE(std::string::npos, temp.find("firmwareVersion=\"123A\" "
+                                         "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" " 
+                                         "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\""));
+
+  ASSERT_NE(std::string::npos, temp.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                         "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                         "mountReadTransients=\"10\" "
+                                         "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                         "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 //
@@ -1172,6 +1219,18 @@ TEST_P(DataTransferSessionTest, DataTransferSessionMissingFilesMigration) {
   ASSERT_EQ(s_vid, sess.getVid());
   // We should no have logged a single successful file read.
   ASSERT_EQ(std::string::npos, logger.getLog().find("MSG=\"File successfully read from disk\""));
+  // Check logs for drive statistics
+  std::string logToCheck = logger.getLog();
+  logToCheck += "";
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" "
+                                               "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" " 
+                                               "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\""));
+
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                               "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                               "mountReadTransients=\"10\" "
+                                               "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                               "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 //
@@ -1303,6 +1362,18 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) {
     ASSERT_EQ(s_vid, tapes.front().vid);
     ASSERT_EQ(true, tapes.front().full);
   }
+  // Check logs for drive statistics
+  std::string logToCheck = logger.getLog();
+  logToCheck += "";
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" "
+                                               "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" " 
+                                               "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\""));
+
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                               "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                               "mountReadTransients=\"10\" "
+                                               "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                               "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) {
@@ -1430,6 +1501,17 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) {
     ASSERT_EQ(s_vid, tapes.front().vid);
     ASSERT_EQ(true, tapes.front().full);
   }
+  // Check logs for drive statistics
+  std::string logToCheck = logger.getLog();
+  logToCheck += "";
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" "
+                                               "mountTotalCorrectedWriteErrors=\"5\" mountTotalUncorrectedWriteErrors=\"1\" "
+                                               "mountTotalWriteBytesProcessed=\"4096\" mountTotalNonMediumErrorCounts=\"2\""));
+  ASSERT_NE(std::string::npos, logToCheck.find("firmwareVersion=\"123A\" lifetimeMediumEfficiencyPrct=\"100\" "
+                                               "mountReadEfficiencyPrct=\"100\" mountWriteEfficiencyPrct=\"100\" "
+                                               "mountReadTransients=\"10\" "
+                                               "mountServoTemps=\"10\" mountServoTransients=\"5\" mountTemps=\"100\" "
+                                               "mountTotalReadRetries=\"25\" mountTotalWriteRetries=\"25\" mountWriteTransients=\"10\""));
 }
 
 #undef TEST_MOCK_DB
diff --git a/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp
index 7626de821b67016efe867e4de59452371eee75bc..0291381fe9cd647ac5735b04442fb29e5f1da986 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/RecallTaskInjectorTest.cpp
@@ -128,6 +128,8 @@ namespace unitTests
     }
 
     virtual void countTapeLogError(const std::string & error) {};
+    protected:
+      virtual void logSCSIMetrics() {};
   };
   
   class TestingDatabaseRetrieveMount: public cta::SchedulerDatabase::RetrieveMount {
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp
index abe1924951cb2860818cb0c8e5bd737248f01426..5f0f0c065743419374f29499703de75160cf5c3f 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp
@@ -57,6 +57,10 @@ castor::tape::tapeserver::daemon::TapeReadSingleThread::TapeCleaning::~TapeClean
   m_this.m_stats.waitReportingTime += m_timer.secs(cta::utils::Timer::resetCounter);
   // Log (safely, exception-wise) the tape alerts (if any) at the end of the session
   try { m_this.logTapeAlerts(); } catch (...) {}
+  // Log safely SCSI Metrits
+  try { m_this.logSCSIMetrics(); } catch (...) {}
+
+  // Log safely errors at the end of the session
   // This out-of-try-catch variables allows us to record the stage of the 
   // process we're in, and to count the error if it occurs.
   // We will not record errors for an empty string. This will allow us to
@@ -279,6 +283,7 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() {
         }
       }
     }
+
     // The session completed successfully, and the cleaner (unmount) executed
     // at the end of the previous block. Log the results.
     cta::log::ScopedParamContainer params(m_logContext);
@@ -345,3 +350,59 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::logWithStat(
                   /1000/1000/m_stats.totalTime:0.0);
     m_logContext.log(level,msg);  
 }
+
+//------------------------------------------------------------------------------
+//logSCSIMetrics
+//------------------------------------------------------------------------------
+void castor::tape::tapeserver::daemon::TapeReadSingleThread::logSCSIMetrics() {
+  try {
+    // mount general statistics
+    cta::log::ScopedParamContainer scopedContainer(m_logContext);
+    appendDriveAndTapeInfoToScopedParams(scopedContainer);
+    // get mount general stats
+    std::map<std::string, uint32_t> scsi_read_metrics_hash = m_drive.getTapeReadErrors();
+    appendMetricsToScopedParams(scopedContainer, scsi_read_metrics_hash);
+    std::map<std::string, uint32_t> scsi_nonmedium_metrics_hash = m_drive.getTapeNonMediumErrors();
+    appendMetricsToScopedParams(scopedContainer, scsi_nonmedium_metrics_hash);
+    logSCSIStats("Logging mount general statistics",
+      scsi_read_metrics_hash.size() + scsi_nonmedium_metrics_hash.size());
+  }
+  catch (const cta::exception::Exception &ex) {
+    cta::log::ScopedParamContainer scoped(m_logContext);
+    scoped.add("exception_message", ex.getMessageValue());
+    m_logContext.log(cta::log::ERR, "Exception in logging mount general statistics");
+  }
+
+  // drive statistic
+  try {
+    cta::log::ScopedParamContainer scopedContainer(m_logContext);
+    appendDriveAndTapeInfoToScopedParams(scopedContainer);
+    // get drive stats
+    std::map<std::string,float> scsi_quality_metrics_hash = m_drive.getQualityStats();
+    appendMetricsToScopedParams(scopedContainer, scsi_quality_metrics_hash);
+    std::map<std::string,uint32_t> scsi_drive_metrics_hash = m_drive.getDriveStats();
+    appendMetricsToScopedParams(scopedContainer, scsi_drive_metrics_hash);
+    logSCSIStats("Logging drive statistics",
+      scsi_quality_metrics_hash.size()+scsi_drive_metrics_hash.size());
+  }
+  catch (const cta::exception::Exception &ex) {
+    cta::log::ScopedParamContainer scoped(m_logContext);
+    scoped.add("exception_message", ex.getMessageValue());
+    m_logContext.log(cta::log::ERR, "Exception in logging drive statistics");
+  }
+
+  // volume statistics
+  try {
+    cta::log::ScopedParamContainer scopedContainer(m_logContext);
+    appendDriveAndTapeInfoToScopedParams(scopedContainer);
+    std::map<std::string,uint32_t> scsi_metrics_hash = m_drive.getVolumeStats();
+    appendMetricsToScopedParams(scopedContainer, scsi_metrics_hash);
+    logSCSIStats("Logging volume statistics", scsi_metrics_hash.size());
+  }
+  catch (const cta::exception::Exception &ex) {
+    cta::log::ScopedParamContainer scoped(m_logContext);
+    scoped.add("exception_message", ex.getMessageValue());
+    m_logContext.log(cta::log::ERR, "Exception in logging volume statistics");
+  }
+}
+
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp
index f1a64c25fa531c0b9382c0847a5d995b11b8bf51..cd94fdb07ac9041afdd52e930e0637ea5ef28e8b 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.hpp
@@ -150,6 +150,11 @@ private:
     m_watchdog.addToErrorCount(error);
   }
 
+protected:
+  /**
+   * Logs SCSI metrics for read session.
+   */
+  virtual void logSCSIMetrics();
 }; // class TapeReadSingleThread
 
 } // namespace daemon
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp
index ec1bcee2c691600eb5c58a5f2f55ca7ff42abac7..5173291a50abe92bd788375fdf5a6ffab0c3757e 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeSingleThreadInterface.hpp
@@ -203,7 +203,43 @@ protected:
     }
     return true;
   }
-  
+
+  /**
+   * Log SCSI metrics for session.
+   */
+  virtual void logSCSIMetrics() = 0;
+
+  /**
+   * Function iterating through the map of available SCSI metrics and logging them.
+   */
+  void logSCSIStats(const std::string & logTitle, size_t metricsHashLength) {
+    if(metricsHashLength == 0) { // skip logging entirely if hash is empty.
+      m_logContext.log(cta::log::INFO, "SCSI Statistics could not be acquired from drive");
+      return;
+    }
+    m_logContext.log(cta::log::INFO, logTitle);
+  }
+
+  /**
+   * Function appending Tape VID, drive manufacturer and model and firmware version to the Scoped Container passed.
+   */
+  void appendDriveAndTapeInfoToScopedParams(cta::log::ScopedParamContainer &scopedContainer) {
+    drive::deviceInfo di = m_drive.getDeviceInfo();
+    scopedContainer.add("driveManufacturer", di.vendor);
+    scopedContainer.add("driveType", di.product);
+    scopedContainer.add("firmwareVersion", m_drive.getDriveFirmwareVersion());
+  }
+
+  /**
+   * Function appending SCSI Metrics to the Scoped Container passed.
+   */
+  template<class N>
+  static void appendMetricsToScopedParams( cta::log::ScopedParamContainer &scopedContainer, const std::map<std::string,N> & metricsHash) {
+     for(auto it = metricsHash.cbegin(); it != metricsHash.end(); it++) {
+      scopedContainer.add(it->first, it->second);
+     }
+   }
+
   /**
    * Helper virtual function allowing the access to the m_watchdog member
    * in the inherited classes (TapeReadSingleThread and TapeWriteSingleThread)
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp
index 331ec0f7dd9777a370b0830d0f960488218a6b00..94f3e00cf2011599c878ce3b6b826edae12e0077 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp
@@ -266,6 +266,7 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() {
         }
       } //end of while(1))
     }
+
     // The session completed successfully, and the cleaner (unmount) executed
     // at the end of the previous block. Log the results.
     cta::log::ScopedParamContainer params(m_logContext);
@@ -372,3 +373,59 @@ int level,const std::string& msg, cta::log::ScopedParamContainer& params){
                 /1000/1000/m_stats.totalTime:0.0);
   m_logContext.log(level, msg);
 }
+
+//------------------------------------------------------------------------------
+//logSCSIMetrics
+//------------------------------------------------------------------------------
+void castor::tape::tapeserver::daemon::TapeWriteSingleThread::logSCSIMetrics() {
+  try {
+    // mount general statistics
+    cta::log::ScopedParamContainer scopedContainer(m_logContext);
+    appendDriveAndTapeInfoToScopedParams(scopedContainer);
+    // get mount general stats
+    std::map<std::string, uint32_t> scsi_write_metrics_hash = m_drive.getTapeWriteErrors();
+    appendMetricsToScopedParams(scopedContainer, scsi_write_metrics_hash);
+    std::map<std::string, uint32_t> scsi_nonmedium_metrics_hash = m_drive.getTapeNonMediumErrors();
+    appendMetricsToScopedParams(scopedContainer, scsi_nonmedium_metrics_hash);
+    logSCSIStats("Logging mount general statistics",
+      scsi_write_metrics_hash.size() + scsi_nonmedium_metrics_hash.size());
+  }
+  catch (const cta::exception::Exception &ex) {
+    cta::log::ScopedParamContainer scoped(m_logContext);
+    scoped.add("exception_message", ex.getMessageValue());
+    m_logContext.log(cta::log::ERR, "Exception in logging mount general statistics");
+  }
+
+  // drive statistics
+  try {
+    cta::log::ScopedParamContainer scopedContainer(m_logContext);
+    appendDriveAndTapeInfoToScopedParams(scopedContainer);
+    // get drive stats
+    std::map<std::string,float> scsi_quality_metrics_hash = m_drive.getQualityStats();
+    appendMetricsToScopedParams(scopedContainer, scsi_quality_metrics_hash);
+    std::map<std::string,uint32_t> scsi_drive_metrics_hash = m_drive.getDriveStats();
+    appendMetricsToScopedParams(scopedContainer, scsi_drive_metrics_hash);
+    logSCSIStats("Logging drive statistics",
+      scsi_quality_metrics_hash.size()+scsi_drive_metrics_hash.size());
+  }
+  catch (const cta::exception::Exception &ex) {
+    cta::log::ScopedParamContainer scoped(m_logContext);
+    scoped.add("exception_message", ex.getMessageValue());
+    m_logContext.log(cta::log::ERR, "Exception in logging drive statistics");
+  }
+
+  // volume statistics
+  try {
+    cta::log::ScopedParamContainer scopedContainer(m_logContext);
+    appendDriveAndTapeInfoToScopedParams(scopedContainer);
+    std::map<std::string,uint32_t> scsi_metrics_hash = m_drive.getVolumeStats();
+    appendMetricsToScopedParams(scopedContainer, scsi_metrics_hash);
+    logSCSIStats("Logging volume statistics", scsi_metrics_hash.size());
+  }
+  catch (const cta::exception::Exception &ex) {
+    cta::log::ScopedParamContainer scoped(m_logContext);
+    scoped.add("exception_message", ex.getMessageValue());
+    m_logContext.log(cta::log::ERR, "Exception in logging volume statistics");
+  }
+}
+
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp
index b44e5907ffbf5b88c17a2f5e8ec828773c6a0285..3b7132be6033499a031489fed14c36aa91be8c68 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.hpp
@@ -111,12 +111,16 @@ private:
       // prevent counting where error happened upstream.
       // Log (safely, exception-wise) the tape alerts (if any) at the end of the session
       try { m_this.logTapeAlerts(); } catch (...) {}
+      // Log (safely, exception-wise) the tape SCSI metrics at the end of the session
+      try { m_this.logSCSIMetrics(); } catch(...) {}
+
       std::string currentErrorToCount = "Error_tapeUnload";
       try{
         // Do the final cleanup
         // First check that a tape is actually present in the drive. We can get here
         // after failing to mount (library error) in which case there is nothing to
         // do (and trying to unmount will only lead to a failure.)
+
         const uint32_t waitMediaInDriveTimeout = 60;
         try {
           m_this.m_drive.waitUntilReady(waitMediaInDriveTimeout);
@@ -263,6 +267,11 @@ protected:
   virtual void countTapeLogError(const std::string & error) { 
     m_watchdog.addToErrorCount(error);
   }
+
+  /**
+   * Logs SCSI metrics for write session.
+   */
+  virtual void logSCSIMetrics();
   
 private:
   /**
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
index 2268b51e6352abb1e69a1d9d3e3bab4514059269..130d143fca7f51654f3975c36886f3f0d784d149 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
@@ -1135,6 +1135,902 @@ drive::compressionStats drive::DriveIBM3592::getCompression()  {
   return driveCompressionStats;
 }
 
+//------------------------------------------------------------------------------
+// pre-emptive evaluation statistics (SCSI Statistics)
+//------------------------------------------------------------------------------
+std::map<std::string,uint32_t> drive::DriveGeneric::getTapeWriteErrors() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,uint32_t> drive::DriveGeneric::getTapeReadErrors() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,float> drive::DriveGeneric::getQualityStats() {
+  // No available data
+  return std::map<std::string,float>();
+}
+
+std::map<std::string,uint32_t> drive::DriveGeneric::getDriveStats() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,uint32_t> drive::DriveGeneric::getVolumeStats() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,uint32_t> drive::DriveIBM3592::getTapeWriteErrors() {
+  // SCSI counters get reset after read in DriveIBM3592.
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveWriteErrorStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::writeErrors;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveIBM3592::getTapeWriteErrors");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getTapeWriteErrors");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+  while (logParameter < endPage) { /* values in KiBs and we use shift <<10 to get bytes */
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::writeErrorsDevicePage::totalCorrectedErrors:
+        driveWriteErrorStats["mountTotalCorrectedWriteErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::writeErrorsDevicePage::totalProcessed:
+        driveWriteErrorStats["mountTotalWriteBytesProcessed"] = logPageParam.getU64Value() << 10;
+        break;
+      case SCSI::writeErrorsDevicePage::totalUncorrectedErrors:
+        driveWriteErrorStats["mountTotalUncorrectedWriteErrors"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return driveWriteErrorStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveT10000::getTapeWriteErrors() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveWriteErrorStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::writeErrors;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveT10000::getTapeWriteErrors");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveT10000::getTapeWriteErrors");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+  while (logParameter < endPage) {
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::writeErrorsDevicePage::totalCorrectedErrors:
+        driveWriteErrorStats["mountTotalCorrectedWriteErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::writeErrorsDevicePage::totalProcessed:
+        driveWriteErrorStats["mountTotalWriteBytesProcessed"] = logPageParam.getU64Value(); // already in bytes
+        break;
+      case SCSI::writeErrorsDevicePage::totalUncorrectedErrors:
+        driveWriteErrorStats["mountTotalUncorrectedWriteErrors"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return driveWriteErrorStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveIBM3592::getTapeReadErrors() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveReadErrorStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::readErrors;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveIBM3592::getTapeReadErrors");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getTapeReadErrors");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+  while (logParameter < endPage) { /* values in KiBs and we use shift <<10 to get bytes */
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::readErrorsDevicePage::totalCorrectedErrors:
+        driveReadErrorStats["mountTotalCorrectedReadErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::readErrorsDevicePage::totalProcessed:
+        driveReadErrorStats["mountTotalReadBytesProcessed"] = logPageParam.getU64Value() << 10;
+        break;
+      case SCSI::readErrorsDevicePage::totalUncorrectedErrors:
+        driveReadErrorStats["mountTotalUncorrectedReadErrors"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return driveReadErrorStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveT10000::getTapeReadErrors() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveReadErrorStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::readErrors;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveT10000::getTapeReadErrors");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveT10000::getTapeReadErrors");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+  while (logParameter < endPage) { /* values in KiBs and we use shift <<10 to get bytes */
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::readErrorsDevicePage::totalCorrectedErrors:
+        driveReadErrorStats["mountTotalCorrectedReadErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::readErrorsDevicePage::totalProcessed:
+        driveReadErrorStats["mountTotalReadBytesProcessed"] = logPageParam.getU64Value(); // already in bytes
+        break;
+      case SCSI::readErrorsDevicePage::totalUncorrectedErrors:
+        driveReadErrorStats["mountTotalUncorrectedReadErrors"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return driveReadErrorStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveGeneric::getTapeNonMediumErrors() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveNonMediumErrorsStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::nonMediumErrors;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveGeneric::getTapeNonMediumErrors");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveGeneric::getTapeNonMediumErrors");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+  while (logParameter < endPage) { 
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::nonMediumErrorsDevicePage::totalCount:
+        driveNonMediumErrorsStats["mountTotalNonMediumErrorCounts"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return driveNonMediumErrorsStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveIBM3592::getVolumeStats() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> volumeStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::volumeStatistics;
+  cdb.subPageCode = 0x00; // 0x01 // for IBM latest revision drives
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveIBM3592::getVolumeStats");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getVolumeStats");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+  while (logParameter < endPage) {
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::volumeStatisticsPage::validityFlag:
+        volumeStats["validity"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::volumeMounts:
+        volumeStats["lifetimeVolumeMounts"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::volumeRecoveredWriteDataErrors:
+        volumeStats["lifetimeVolumeRecoveredWriteErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::volumeUnrecoveredWriteDataErrors:
+        volumeStats["lifetimeVolumeUnrecoveredWriteErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::volumeRecoveredReadErrors:
+        volumeStats["lifetimeVolumeRecoveredReadErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::volumeUnrecoveredReadErrors:
+        volumeStats["lifetimeVolumeUnrecoveredReadErrors"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::volumeManufacturingDate:
+        char volumeManufacturingDate[9];
+        for (int i = 0; i < 8; ++i) {
+          volumeManufacturingDate[i] = logPageParam.parameterValue[i];
+        }
+        volumeManufacturingDate[8] = '\0';
+        volumeStats["volumeManufacturingDate"] = std::atoi(volumeManufacturingDate);
+        break;
+      case SCSI::volumeStatisticsPage::BOTPasses:
+        volumeStats["lifetimeBOTPasses"] = logPageParam.getU64Value();
+        break;
+      case SCSI::volumeStatisticsPage::MOTPasses:
+        volumeStats["lifetimeMOTPasses"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return volumeStats;
+}
+
+std::map<std::string,float> drive::DriveIBM3592::getQualityStats() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,float> qualityStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  // Obtain data from QualitySummarySubpage
+  {
+    // Lifetime values
+    {
+      memset(dataBuff, 0, sizeof(dataBuff));
+
+      cdb.pageCode = SCSI::logSensePages::performanceCharacteristics;
+      cdb.subPageCode = 0x80;
+      cdb.PC = 0x01; // Current Cumulative Values
+      SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+      sgh.setCDB(&cdb);
+      sgh.setDataBuffer(&dataBuff);
+      sgh.setSenseBuffer(&senseBuff);
+      sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+      /* Manage both system error and SCSI errors. */
+      cta::exception::Errnum::throwOnMinusOne(
+        m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+        "Failed SG_IO ioctl in DriveIBM3592::getQualityStats_qualitySummaryBlock");
+      SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getQualityStats");
+
+      SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+        *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+      unsigned char *endPage = dataBuff +
+        SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+      unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+      while (logParameter < endPage) { 
+        SCSI::Structures::logSenseParameter_t &logPageParam =
+          *(SCSI::Structures::logSenseParameter_t *) logParameter;
+        const int val = logPageParam.getU64Value();
+        if (val != 0)
+          switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+            case SCSI::performanceCharacteristicsQualitySummaryPage::driveEfficiency:
+              qualityStats["lifetimeDriveEfficiencyPrct"] = 100-(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::mediaEfficiency:
+              qualityStats["lifetimeMediumEfficiencyPrct"] = 100-(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::primaryInterfaceEfficiency0:
+              qualityStats["lifetimeInterfaceEfficiency0Prct"] = 100-(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::primaryInterfaceEfficiency1:
+              qualityStats["lifetimeInterfaceEfficiency1Prct"] = 100-(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::libraryInterfaceEfficiency:
+              qualityStats["lifetimeLibraryEfficiencyPrct"] = 100-(val-1)*100/254.0;
+              break;
+          }
+        logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+      }
+    }
+
+    // Mount values
+    {
+      memset(dataBuff, 0, sizeof(dataBuff));
+
+      cdb.pageCode = SCSI::logSensePages::performanceCharacteristics;
+      cdb.subPageCode = 0x40;
+      cdb.PC = 0x01; // Current Cumulative Values
+      SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+      sgh.setCDB(&cdb);
+      sgh.setDataBuffer(&dataBuff);
+      sgh.setSenseBuffer(&senseBuff);
+      sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+      /* Manage both system error and SCSI errors. */
+      cta::exception::Errnum::throwOnMinusOne(
+        m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+        "Failed SG_IO ioctl in DriveIBM3592::getQualityStats_qualitySummaryBlock");
+      SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getQualityStats");
+
+      SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+        *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+      unsigned char *endPage = dataBuff +
+        SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+      unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+      while (logParameter < endPage) {
+        SCSI::Structures::logSenseParameter_t &logPageParam =
+          *(SCSI::Structures::logSenseParameter_t *) logParameter;
+        const int val = logPageParam.getU64Value();
+        if (val != 0)
+          switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+            case SCSI::performanceCharacteristicsQualitySummaryPage::driveEfficiency:
+              qualityStats["mountDriveEfficiencyPrct"] = 100-(float)(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::mediaEfficiency:
+              qualityStats["mountMediumEfficiencyPrct"] = 100-(float)(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::primaryInterfaceEfficiency0:
+              qualityStats["mountInterfaceEfficiency0Prct"] = 100-(float)(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::primaryInterfaceEfficiency1:
+              qualityStats["mountInterfaceEfficiency1Prct"] = 100-(float)(val-1)*100/254.0;
+              break;
+            case SCSI::performanceCharacteristicsQualitySummaryPage::libraryInterfaceEfficiency:
+              qualityStats["mountLibraryEfficiencyPrct"] = 100-(float)(val-1)*100/254.0;
+              break;
+          }
+        logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+      }
+    }
+  }
+
+  // Obtain data from HostCommandsSubpage
+  {
+    // lifetime values
+    {
+      memset(dataBuff, 0, sizeof(dataBuff));
+
+      cdb.pageCode = SCSI::logSensePages::performanceCharacteristics;
+      cdb.subPageCode = 0x91;
+      cdb.PC = 0x01; // Current Cumulative Values
+      SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+      sgh.setCDB(&cdb);
+      sgh.setDataBuffer(&dataBuff);
+      sgh.setSenseBuffer(&senseBuff);
+      sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+      /* Manage both system error and SCSI errors. */
+      cta::exception::Errnum::throwOnMinusOne(
+        m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+        "Failed SG_IO ioctl in DriveIBM3592::getQualityStats_hostCommandsBlock");
+      SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getQualityStats");
+
+      SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+        *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+      unsigned char *endPage = dataBuff +
+        SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+      unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+      while (logParameter < endPage) { 
+        SCSI::Structures::logSenseParameter_t &logPageParam =
+          *(SCSI::Structures::logSenseParameter_t *) logParameter;
+        switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+          case SCSI::performanceCharacteristicsHostCommandsPage::readPerformanceEfficiency:
+            qualityStats["lifetimeReadEfficiencyPrct"] = (float)logPageParam.getU64Value()/65536;
+            break;
+          case SCSI::performanceCharacteristicsHostCommandsPage::writePerformanceEfficiency:
+            qualityStats["lifetimeWriteEfficiencyPrct"] = (float)logPageParam.getU64Value()/65536;
+            break;
+        }
+        logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+      }
+    }
+
+    // mount values
+    {
+      memset(dataBuff, 0, sizeof(dataBuff));
+
+      cdb.pageCode = SCSI::logSensePages::performanceCharacteristics;
+      cdb.subPageCode = 0x51;
+      cdb.PC = 0x01; // Current Cumulative Values
+      SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+      sgh.setCDB(&cdb);
+      sgh.setDataBuffer(&dataBuff);
+      sgh.setSenseBuffer(&senseBuff);
+      sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+      /* Manage both system error and SCSI errors. */
+      cta::exception::Errnum::throwOnMinusOne(
+        m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+        "Failed SG_IO ioctl in DriveIBM3592::getQualityStats_hostCommandsBlock");
+      SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getQualityStats");
+
+      SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+        *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+      unsigned char *endPage = dataBuff +
+        SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+      unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+      while (logParameter < endPage) {
+        SCSI::Structures::logSenseParameter_t &logPageParam =
+          *(SCSI::Structures::logSenseParameter_t *) logParameter;
+        switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+          case SCSI::performanceCharacteristicsHostCommandsPage::readPerformanceEfficiency:
+            qualityStats["mountReadEfficiencyPrct"] = (float)logPageParam.getU64Value()/65536;
+            break;
+          case SCSI::performanceCharacteristicsHostCommandsPage::writePerformanceEfficiency:
+            qualityStats["mountWriteEfficiencyPrct"] = (float)logPageParam.getU64Value()/65536;
+            break;
+        }
+        logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+      }
+    }
+  }
+  return qualityStats;
+}
+
+std::map<std::string,float> drive::DriveT10000::getQualityStats() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,float> qualityStats;
+  unsigned char dataBuff[4096]; //big enough to fit all the results
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::vendorUniqueDriveStatistics;
+  cdb.subPageCode = 0x00;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveT10000::getQualityStats");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveT10000::getQualityStats");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+  while (logParameter < endPage) { 
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::vendorUniqueDriveStatistics::readQualityIndex:
+        qualityStats["mountReadEfficiencyPrct"] = logPageParam.getU64Value()/160.0;
+        break;
+      case SCSI::vendorUniqueDriveStatistics::writeEfficiency:
+        qualityStats["mountWriteEfficiencyPrct"] = logPageParam.getU64Value()/10.0;
+        break;
+      case SCSI::vendorUniqueDriveStatistics::tapeEfficiency:
+        qualityStats["lifetimeMediumEfficiencyPrct"] = logPageParam.getU64Value()/10.0;
+        break;
+      case SCSI::vendorUniqueDriveStatistics::readBackCheckQualityIndex:
+        qualityStats["mountReadBackCheckQualityIndexPrct"] = logPageParam.getU64Value()/160.0;
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return qualityStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveIBM3592::getDriveStats() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveStats;
+  unsigned char dataBuff[1024]; //big enough to fit all the results
+
+  // write errors (0x34)
+  {
+    memset(dataBuff, 0, sizeof(dataBuff));
+
+    cdb.pageCode = SCSI::logSensePages::driveWriteErrors;
+    cdb.PC = 0x01; // Current Cumulative Values
+    SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+    sgh.setCDB(&cdb);
+    sgh.setDataBuffer(&dataBuff);
+    sgh.setSenseBuffer(&senseBuff);
+    sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+    /* Manage both system error and SCSI errors. */
+    cta::exception::Errnum::throwOnMinusOne(
+      m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+      "Failed SG_IO ioctl in DriveIBM3592::getDriveStats_writeErrors");
+    SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getDriveStats");
+
+    SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+      *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+    unsigned char *endPage = dataBuff +
+      SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+    unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+    while (logParameter < endPage) {
+      SCSI::Structures::logSenseParameter_t &logPageParam =
+        *(SCSI::Structures::logSenseParameter_t *) logParameter;
+      switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+        case SCSI::driveWriteErrorsPage::dataTemps:
+          driveStats["mountTemps"] = logPageParam.getU64Value();
+          break;
+        case SCSI::driveWriteErrorsPage::servoTemps:
+          driveStats["mountServoTemps"] = logPageParam.getU64Value();
+          break;
+        case SCSI::driveWriteErrorsPage::servoTransients:
+          driveStats["mountServoTransients"] = logPageParam.getU64Value();
+          break;
+        case SCSI::driveWriteErrorsPage::dataTransients:
+          driveStats["mountWriteTransients"] = logPageParam.getU64Value();
+          break;
+        case SCSI::driveWriteErrorsPage::totalRetries:
+          driveStats["mountTotalWriteRetries"] = logPageParam.getU64Value();
+          break;
+      }
+      logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+    }
+  }
+
+  // read FW errors
+  {
+    memset(dataBuff, 0, sizeof(dataBuff));
+
+    cdb.pageCode = SCSI::logSensePages::driveReadForwardErrors;
+    cdb.PC = 0x01; // Current Cumulative Values
+    SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+    sgh.setCDB(&cdb);
+    sgh.setDataBuffer(&dataBuff);
+    sgh.setSenseBuffer(&senseBuff);
+    sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+    /* Manage both system error and SCSI errors. */
+    cta::exception::Errnum::throwOnMinusOne(
+      m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+      "Failed SG_IO ioctl in DriveIBM3592::getDriveStats_readFWErrors");
+    SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getDriveStats");
+
+    SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+      *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+    unsigned char *endPage = dataBuff +
+      SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+    unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+    while (logParameter < endPage) {
+      SCSI::Structures::logSenseParameter_t &logPageParam =
+        *(SCSI::Structures::logSenseParameter_t *) logParameter;
+      switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+        case SCSI::driveReadErrorsPage::dataTemps:
+          driveStats["mountTemps"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::servoTemps:
+          driveStats["mountServoTemps"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::servoTransients:
+          driveStats["mountServoTransients"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::dataTransients:
+          driveStats["mountReadTransients"] = logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::totalRetries:
+          driveStats["mountTotalReadRetries"] = logPageParam.getU64Value();
+          break;
+      }
+      logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+    }
+  }
+
+  // read BW errors
+  {
+    memset(dataBuff, 0, sizeof(dataBuff));
+
+    cdb.pageCode = SCSI::logSensePages::driveReadBackwardErrors;
+    cdb.PC = 0x01; // Current Cumulative Values
+    SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+    sgh.setCDB(&cdb);
+    sgh.setDataBuffer(&dataBuff);
+    sgh.setSenseBuffer(&senseBuff);
+    sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+    /* Manage both system error and SCSI errors. */
+    cta::exception::Errnum::throwOnMinusOne(
+      m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+      "Failed SG_IO ioctl in DriveIBM3592::getDriveStats_readBWErrors");
+    SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::getDriveStats");
+
+    SCSI::Structures::logSenseLogPageHeader_t &logPageHeader =
+      *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+    unsigned char *endPage = dataBuff +
+      SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+    unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+    while (logParameter < endPage) {
+      SCSI::Structures::logSenseParameter_t &logPageParam =
+        *(SCSI::Structures::logSenseParameter_t *) logParameter;
+      switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+        case SCSI::driveReadErrorsPage::dataTemps:
+          driveStats["mountTemps"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::servoTemps:
+          driveStats["mountServoTemps"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::servoTransients:
+          driveStats["mountServoTransients"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::dataTransients:
+          driveStats["mountReadTransients"] += logPageParam.getU64Value();
+          break;
+        case SCSI::driveReadErrorsPage::totalRetries:
+          driveStats["mountTotalReadRetries"] += logPageParam.getU64Value();
+          break;
+      }
+      logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+    }
+  }
+  return driveStats;
+}
+
+std::map<std::string,uint32_t> drive::DriveT10000::getDriveStats() {
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::logSenseCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  std::map<std::string,uint32_t> driveStats;
+  unsigned char dataBuff[4096]; //big enough to fit all the results
+  memset(dataBuff, 0, sizeof (dataBuff));
+
+  cdb.pageCode = SCSI::logSensePages::vendorUniqueDriveStatistics;
+  cdb.PC = 0x01; // Current Cumulative Values
+  SCSI::Structures::setU16(cdb.allocationLength, sizeof(dataBuff));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&dataBuff);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  /* Manage both system error and SCSI errors. */
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveT10000::getDriveStats");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveT10000::getDriveStats");
+
+  SCSI::Structures::logSenseLogPageHeader_t & logPageHeader =
+    *(SCSI::Structures::logSenseLogPageHeader_t *) dataBuff;
+
+  unsigned char *endPage = dataBuff +
+    SCSI::Structures::toU16(logPageHeader.pageLength) + sizeof(logPageHeader);
+
+  unsigned char *logParameter = dataBuff + sizeof(logPageHeader);
+
+  while (logParameter < endPage) {
+    SCSI::Structures::logSenseParameter_t & logPageParam =
+      *(SCSI::Structures::logSenseParameter_t *) logParameter;
+    switch (SCSI::Structures::toU16(logPageParam.header.parameterCode)) {
+      case SCSI::vendorUniqueDriveStatistics::readRecoveryRetries:
+        driveStats["mountTotalReadRetries"] = logPageParam.getU64Value();
+        break;
+      case SCSI::vendorUniqueDriveStatistics::readTransientConditions:
+        driveStats["mountReadTransients"] = logPageParam.getU64Value();
+        break;
+      case SCSI::vendorUniqueDriveStatistics::writeTransientConditions:
+        driveStats["mountWriteTransients"] = logPageParam.getU64Value();
+        break;
+      case SCSI::vendorUniqueDriveStatistics::servoTepomporaries:
+        driveStats["mountServoTemps"] = logPageParam.getU64Value();
+        break;
+      case SCSI::vendorUniqueDriveStatistics::servoTransientConditions:
+        driveStats["mountServoTransients"] = logPageParam.getU64Value();
+        break;
+      case SCSI::vendorUniqueDriveStatistics::writeRecoveryRetries:
+        driveStats["mountTotalWriteRetries"] = logPageParam.getU64Value();
+        break;
+      case SCSI::vendorUniqueDriveStatistics::temporaryDriveErrors:
+        driveStats["mountTemps"] = logPageParam.getU64Value();
+        break;
+    }
+    logParameter += logPageParam.header.parameterLength + sizeof(logPageParam.header);
+  }
+  return driveStats;
+}
+
+std::string drive::DriveGeneric::getDriveFirmwareVersion() {
+  std::ifstream scsiProcFile;
+  try {
+    scsiProcFile.open("/proc/scsi/scsi", std::ios::in);
+    int currentLineNo = 0;
+    std::string line;
+    bool found = false;
+    while (getline(scsiProcFile, line)) {
+      if (std::string::npos != line.find("Type:   Sequential-Access", 0)) {
+        found = true;
+        break;
+      }
+      ++currentLineNo;
+    }
+    if (found) {
+      scsiProcFile.seekg(0, std::ios::beg);
+      for (int i = 0; i < currentLineNo - 2; ++i) {
+        // skipping lines
+        scsiProcFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
+      }
+    }
+    getline(scsiProcFile, line);
+    scsiProcFile.close();
+    return line.substr(line.find("Rev:") + 5);
+  }
+  catch(std::ios_base::failure) {
+    return std::string("");
+  }
+}
+
+/*
+ * Override as not implemented of all SCSI metrics functions for MHVTL virtual drives as SCSI log sense pages
+ * are not implemented as vendor(Oracle) specific, but inherits from DriveT10000.
+ */
+std::map<std::string,uint32_t> drive::DriveMHVTL::getTapeWriteErrors() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,uint32_t> drive::DriveMHVTL::getTapeReadErrors() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,uint32_t> drive::DriveMHVTL::getTapeNonMediumErrors() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
+std::map<std::string,float> drive::DriveMHVTL::getQualityStats(){
+  // No available data
+  return std::map<std::string,float>();
+}
+
+std::map<std::string,uint32_t> drive::DriveMHVTL::getDriveStats() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
 //------------------------------------------------------------------------------
 // testUnitReady
 //------------------------------------------------------------------------------
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
index ff887739203b4a0f8323dab98cf0dd7ff43ec07d..08423e4f58c2f925dec0b75db36e7c9f3338c379 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
@@ -53,6 +53,44 @@ namespace drive {
      */
     virtual compressionStats getCompression()  = 0;
 
+    /**
+     * Get write error information from the drive.
+     * @return writeErrorsStats
+     */
+    virtual std::map<std::string,uint32_t> getTapeWriteErrors();
+
+    /**
+     * Get read error information from the drive.
+     * @return readErrorsStats
+     */
+    virtual std::map<std::string,uint32_t> getTapeReadErrors();
+
+    /**
+     * Get error information (other than read/write) from the drive.
+     */
+    virtual std::map<std::string,uint32_t> getTapeNonMediumErrors();
+
+    /**
+     * Get quality-related metrics (ratings, efficiencies) from the drive.
+     */
+    virtual std::map<std::string,float> getQualityStats();
+
+    /**
+     * Get drive error information happened during mount from the drive.
+     */
+    virtual std::map<std::string,uint32_t> getDriveStats();
+
+    /**
+     * Get volume information happened during the mount.
+     */
+    virtual std::map<std::string,uint32_t> getVolumeStats();
+
+    /**
+     * Get the firmware revision of the drive.
+     * Reads it from /proc/scsi/scsi file.
+     */
+    virtual std::string getDriveFirmwareVersion();
+
     /**
      * Reset all statistics about data movements on the drive.
      * All cumulative and threshold log counter values will be reset to their
@@ -398,7 +436,11 @@ namespace drive {
     DriveT10000(SCSI::DeviceInfo di, System::virtualWrapper & sw) : DriveGeneric(di, sw) {
     }
 
-    virtual compressionStats getCompression() ;
+    virtual compressionStats getCompression();
+    virtual std::map<std::string,uint32_t> getTapeWriteErrors() ;
+    virtual std::map<std::string,uint32_t> getTapeReadErrors() ;
+    virtual std::map<std::string,float> getQualityStats();
+    virtual std::map<std::string,uint32_t> getDriveStats();
   };
   
   /**
@@ -417,6 +459,11 @@ namespace drive {
     virtual void setLogicalBlockProtection(const unsigned char method, 
       unsigned char methodLength, const bool enableLPBforRead, 
       const bool enableLBBforWrite);
+    virtual std::map<std::string,uint32_t> getTapeWriteErrors();
+    virtual std::map<std::string,uint32_t> getTapeReadErrors();
+    virtual std::map<std::string,uint32_t> getTapeNonMediumErrors();
+    virtual std::map<std::string,float> getQualityStats();
+    virtual std::map<std::string,uint32_t> getDriveStats();
   };
 
   class DriveLTO : public DriveGeneric {
@@ -425,7 +472,7 @@ namespace drive {
     DriveLTO(SCSI::DeviceInfo di, System::virtualWrapper & sw) : DriveGeneric(di, sw) {
     }
 
-    virtual compressionStats getCompression() ;
+    virtual compressionStats getCompression();
   };
 
   class DriveIBM3592 : public DriveGeneric {
@@ -434,7 +481,12 @@ namespace drive {
     DriveIBM3592(SCSI::DeviceInfo di, System::virtualWrapper & sw) : DriveGeneric(di, sw) {
     }
 
-    virtual compressionStats getCompression() ;
+    virtual compressionStats getCompression();
+    virtual std::map<std::string,uint32_t> getTapeWriteErrors();
+    virtual std::map<std::string,uint32_t> getTapeReadErrors();
+    virtual std::map<std::string,uint32_t> getVolumeStats();
+    virtual std::map<std::string,float> getQualityStats();
+    virtual std::map<std::string,uint32_t> getDriveStats();
   };
 
 }}}}
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp
index b24b7421889689817913238a9e1f960dde9d1a27..36ce1d5ef6c72281d7c44ca458b3b8f5c610d653 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp
@@ -172,7 +172,13 @@ namespace drive {
     
     virtual compressionStats getCompression()  = 0;
     virtual void clearCompressionStats()  = 0;
-    
+    virtual std::map<std::string,uint32_t> getTapeWriteErrors() = 0;
+    virtual std::map<std::string,uint32_t> getTapeReadErrors() = 0;
+    virtual std::map<std::string,uint32_t> getTapeNonMediumErrors() = 0;
+    virtual std::map<std::string,float> getQualityStats() = 0;
+    virtual std::map<std::string,uint32_t> getDriveStats() = 0;
+    virtual std::map<std::string,uint32_t> getVolumeStats() = 0;
+    virtual std::string getDriveFirmwareVersion() = 0;
     virtual deviceInfo getDeviceInfo()  = 0;
     virtual std::string getSerialNumber()  = 0;
     virtual void positionToLogicalObject(uint32_t blockId)  = 0;
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp
index 1e7ac7977b65df23f7ac34b4221a3854a365dec9..2bf23d0e71ea09ad19729a11c29ffa4c59087166 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp
@@ -45,17 +45,18 @@ TEST(castor_tape_drive_Drive, OpensCorrectly) {
   sysWrapper.delegateToFake();
   
   /* We expect the following calls: */
-  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
+  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(4));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
-  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4));
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
+
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -69,9 +70,16 @@ TEST(castor_tape_drive_Drive, OpensCorrectly) {
   for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
       i != dl.end(); i++) {
     if (castor::tape::SCSI::Types::tape == i->type) {
-      std::string expected_classid (typeid(castor::tape::tapeserver::drive::DriveT10000).name());
       std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface>drive(
         castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+      std::string expected_classid;
+      if (dynamic_cast<castor::tape::tapeserver::drive::DriveIBM3592 *>(drive.get())) {
+        expected_classid = std::string(typeid(castor::tape::tapeserver::drive::DriveIBM3592).name());
+      }
+      else if (dynamic_cast<castor::tape::tapeserver::drive::DriveT10000 *>(drive.get())) {
+        expected_classid = std::string(typeid(castor::tape::tapeserver::drive::DriveT10000).name());
+      }
+      else {/* Fill in other vendors in the future here. */}
       std::string found_classid (typeid(*drive).name());
       ASSERT_EQ(expected_classid, found_classid);
     }
@@ -85,17 +93,17 @@ TEST(castor_tape_drive_Drive, getPositionInfoAndPositionToLogicalObject) {
   sysWrapper.delegateToFake();
   
   /* We expect the following calls: */
-  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
+  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(4));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
-  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4));
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -134,17 +142,17 @@ TEST(castor_tape_drive_Drive, setDensityAndCompression) {
   sysWrapper.delegateToFake();
   
   /* We expect the following calls: */
-  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
+  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(4));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
-  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4));
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -179,17 +187,17 @@ TEST(castor_tape_drive_Drive, setStDriverOptions) {
   sysWrapper.delegateToFake();
   
   /* We expect the following calls: */
-  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
+  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(4));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
-  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4));
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -214,17 +222,17 @@ TEST(castor_tape_drive_Drive, getDeviceInfo) {
   sysWrapper.delegateToFake();
   
   /* We expect the following calls: */
-  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
+  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(4));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
-  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(4));
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -235,15 +243,22 @@ TEST(castor_tape_drive_Drive, getDeviceInfo) {
         castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
       castor::tape::tapeserver::drive::deviceInfo devInfo;
       
-      devInfo.isPIsupported = false;
       EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(2);   
       devInfo = drive->getDeviceInfo();
 
-      ASSERT_EQ("STK     ",devInfo.vendor);
-      ASSERT_EQ("T10000B         ",devInfo.product);
-      ASSERT_EQ("0104",devInfo.productRevisionLevel );
-      ASSERT_EQ("XYZZY_A2  ",devInfo.serialNumber );
-      ASSERT_TRUE(devInfo.isPIsupported);
+      if (dynamic_cast<castor::tape::tapeserver::drive::DriveIBM3592 *>(drive.get())) {
+        ASSERT_EQ("IBM     ",devInfo.vendor);
+        ASSERT_EQ("03592E08        ",devInfo.product);
+        ASSERT_EQ("460E",devInfo.productRevisionLevel );
+        ASSERT_EQ("XYZZY_A2  ",devInfo.serialNumber );
+      }
+      else if (dynamic_cast<castor::tape::tapeserver::drive::DriveIBM3592 *>(drive.get())) {
+        ASSERT_EQ("STK     ",devInfo.vendor);
+        ASSERT_EQ("T10000B         ",devInfo.product);
+        ASSERT_EQ("0104",devInfo.productRevisionLevel );
+        ASSERT_EQ("XYZZY_A2  ",devInfo.serialNumber );
+      }
+      else { /* Fill in other vendors in the future here. */ }
     }
   }
 }
@@ -255,23 +270,29 @@ TEST(castor_tape_drive_Drive, getCompressionAndClearCompressionStats) {
   sysWrapper.delegateToFake();
   
   /* We expect the following calls: */
-  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
+  EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(4));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
   EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(25);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(44);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(25);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(44);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
   for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
-      i != dl.end(); i++) {
-    if (castor::tape::SCSI::Types::tape == i->type) {
+    i != dl.end(); i++) {
+    /*
+     * The second condition relates to the fact that LTO drives and IBM 3592 have the same
+     * logSense page code for different metrics.
+     * The current test is written in such a way that does not really use vfs files. So, there
+     * is no need take into consideration the IBM tapes at all.
+     */
+    if (castor::tape::SCSI::Types::tape == i->type && i->product != "03592E08") {
       castor::tape::tapeserver::drive::DriveGeneric *drive;
       castor::tape::tapeserver::drive::compressionStats comp;
       
@@ -355,14 +376,14 @@ TEST(castor_tape_drive_Drive, getLBPInfo) {
   EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
   EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -394,14 +415,14 @@ TEST(castor_tape_drive_Drive, setLogicalBlockProtection) {
   EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
   EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -439,14 +460,14 @@ TEST(castor_tape_drive_Drive, disableLogicalBlockProtection) {
   EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(3));
   EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(30));
   EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(3));
-  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(3);
-  EXPECT_CALL(sysWrapper, open(_, _)).Times(21);
-  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(38);
+  EXPECT_CALL(sysWrapper, realpath(_, _)).Times(6);
+  EXPECT_CALL(sysWrapper, open(_, _)).Times(42);
+  EXPECT_CALL(sysWrapper, read(_, _, _)).Times(76);
   EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
   EXPECT_CALL(sysWrapper, ioctl(_,_,An<mtget*>())).Times(0);
-  EXPECT_CALL(sysWrapper, close(_)).Times(21);
-  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(3);
-  EXPECT_CALL(sysWrapper, stat(_,_)).Times(7);
+  EXPECT_CALL(sysWrapper, close(_)).Times(42);
+  EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(6);
+  EXPECT_CALL(sysWrapper, stat(_,_)).Times(14);
   
   /* Test: detect devices, then open the device files */
   castor::tape::SCSI::DeviceVector dl(sysWrapper);
@@ -474,6 +495,321 @@ TEST(castor_tape_drive_Drive, disableLogicalBlockProtection) {
   }
 }
 
+TEST(castor_tape_drive_Drive, getReadErrors) {
+  struct {
+    void operator()(castor::tape::System::mockWrapper &sysWrapper) {
+      EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(68));
+      EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, realpath(_, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, open(_, _)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76));
+      EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(4);
+      EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14));
+
+      /* Test: detect devices, then open the device files */
+      castor::tape::SCSI::DeviceVector dl(sysWrapper);
+      for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
+           i != dl.end(); i++) {
+        if (castor::tape::SCSI::Types::tape == i->type) {
+          std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(
+            castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+          std::map<std::string,uint32_t> readErrorsStats =
+            drive->getTapeReadErrors();
+          ASSERT_EQ(2, readErrorsStats["mountTotalCorrectedReadErrors"]);
+          ASSERT_EQ(2048, readErrorsStats["mountTotalReadBytesProcessed"]);
+          ASSERT_EQ(1, readErrorsStats["mountTotalUncorrectedReadErrors"]);
+        }
+      }
+    }
+  } test_functor;
+
+  castor::tape::System::mockWrapper sysWrapperSLC5;
+  castor::tape::System::mockWrapper sysWrapperSLC6;
+  sysWrapperSLC5.fake.setupSLC5();
+  sysWrapperSLC6.fake.setupSLC6();
+  sysWrapperSLC5.delegateToFake();
+  sysWrapperSLC6.delegateToFake();
+  test_functor(sysWrapperSLC5);
+  test_functor(sysWrapperSLC6);
+}
+
+TEST(castor_tape_drive_Drive, getWriteErrors) {
+  struct {
+    void operator()(castor::tape::System::mockWrapper &sysWrapper) {
+      EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(68));
+      EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, realpath(_, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, open(_, _)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76));
+      EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(4);
+      EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14));
+
+      /* Test: detect devices, then open the device files */
+      castor::tape::SCSI::DeviceVector dl(sysWrapper);
+      for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
+           i != dl.end(); i++) {
+        if (castor::tape::SCSI::Types::tape == i->type) {
+          std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(
+            castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+          std::map<std::string,uint32_t> writeErrorsStats =
+            drive->getTapeWriteErrors();
+          ASSERT_EQ(2, writeErrorsStats["mountTotalCorrectedWriteErrors"]);
+          ASSERT_EQ(2048, writeErrorsStats["mountTotalWriteBytesProcessed"]);
+          ASSERT_EQ(1, writeErrorsStats["mountTotalUncorrectedWriteErrors"]);
+        }
+      }
+    }
+  } test_functor;
+
+  castor::tape::System::mockWrapper sysWrapperSLC5;
+  castor::tape::System::mockWrapper sysWrapperSLC6;
+  sysWrapperSLC5.fake.setupSLC5();
+  sysWrapperSLC6.fake.setupSLC6();
+  sysWrapperSLC5.delegateToFake();
+  sysWrapperSLC6.delegateToFake();
+  test_functor(sysWrapperSLC5);
+  test_functor(sysWrapperSLC6);
+}
+
+TEST(castor_tape_drive_Drive, getNonMediumErrors) {
+  struct {
+    void operator()(castor::tape::System::mockWrapper &sysWrapper) {
+      EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(68));
+      EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, realpath(_, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, open(_, _)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76));
+      EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(4);
+      EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14));
+
+      /* Test: detect devices, then open the device files */
+      castor::tape::SCSI::DeviceVector dl(sysWrapper);
+      for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
+           i != dl.end(); i++) {
+        if (castor::tape::SCSI::Types::tape == i->type) {
+          std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(
+            castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+          std::map<std::string,uint32_t> nonMediumErrorsStats =
+            drive->getTapeNonMediumErrors();
+          ASSERT_EQ(3, nonMediumErrorsStats["mountTotalNonMediumErrorCounts"]);
+        }
+      }
+    }
+  } test_functor;
+
+  castor::tape::System::mockWrapper sysWrapperSLC5;
+  castor::tape::System::mockWrapper sysWrapperSLC6;
+  sysWrapperSLC5.fake.setupSLC5();
+  sysWrapperSLC6.fake.setupSLC6();
+  sysWrapperSLC5.delegateToFake();
+  sysWrapperSLC6.delegateToFake();
+  test_functor(sysWrapperSLC5);
+  test_functor(sysWrapperSLC6);
+}
+
+TEST(castor_tape_drive_Drive, getVolumeStats) {
+  struct {
+    void operator()(castor::tape::System::mockWrapper &sysWrapper) {
+      EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(68));
+      EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, realpath(_, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, open(_, _)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76));
+      EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(2);
+      EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14));
+  
+  
+      /* Test: detect devices, then open the device files */
+      castor::tape::SCSI::DeviceVector dl(sysWrapper);
+      for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
+           i != dl.end(); i++) {
+        if (castor::tape::SCSI::Types::tape == i->type) {
+          std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(
+            castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+          if (castor::tape::tapeserver::drive::DriveIBM3592* ibm_drive =
+              dynamic_cast<castor::tape::tapeserver::drive::DriveIBM3592*>(drive.get())) {
+            std::map<std::string,uint32_t> volumeStats =
+              ibm_drive->getVolumeStats();
+            ASSERT_EQ(true, volumeStats["validity"]);
+            ASSERT_EQ(18886754, volumeStats["lifetimeVolumeMounts"]);
+            ASSERT_EQ(16843223, volumeStats["lifetimeVolumeRecoveredReadErrors"]);
+            ASSERT_EQ(514, volumeStats["lifetimeVolumeUnrecoveredReadErrors"]);
+            ASSERT_EQ(16909057, volumeStats["lifetimeVolumeRecoveredWriteErrors"]);
+            ASSERT_EQ(1, volumeStats["lifetimeVolumeUnrecoveredWriteErrors"]);
+            ASSERT_EQ(20140815, volumeStats["volumeManufacturingDate"]);
+            ASSERT_EQ(33752868, volumeStats["lifetimeBOTPasses"]);
+            ASSERT_EQ(16908566, volumeStats["lifetimeMOTPasses"]);
+          }
+        }
+      }
+    }
+  } test_functor;
+
+  castor::tape::System::mockWrapper sysWrapperSLC5;
+  castor::tape::System::mockWrapper sysWrapperSLC6;
+  sysWrapperSLC5.fake.setupSLC5();
+  sysWrapperSLC6.fake.setupSLC6();
+  sysWrapperSLC5.delegateToFake();
+  sysWrapperSLC6.delegateToFake();
+  test_functor(sysWrapperSLC5);
+  test_functor(sysWrapperSLC6);
+}
+  
+TEST(castor_tape_drive_Drive, getQualityStats) {
+  struct {
+    void operator()(castor::tape::System::mockWrapper &sysWrapper) {
+      EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(68));
+      EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, realpath(_, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, open(_, _)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76));
+      EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(10);
+      EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14));
+  
+      /* Test: detect devices, then open the device files */
+      castor::tape::SCSI::DeviceVector dl(sysWrapper);
+      for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
+           i != dl.end(); i++) {
+        if (castor::tape::SCSI::Types::tape == i->type) {
+          std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(
+            castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+          std::map<std::string,float> qualityStats = drive->getQualityStats();
+          /*
+           * Assertions for common metrics are moved inside the special cases
+           * due to different scales and representation of the same quality metrics.
+           */
+          if (dynamic_cast<castor::tape::tapeserver::drive::DriveIBM3592 *>(drive.get())) {
+  
+            ASSERT_EQ(68, (int)qualityStats["lifetimeDriveEfficiencyPrct"]);
+            ASSERT_EQ(68, (int)qualityStats["lifetimeInterfaceEfficiency0Prct"]);
+            ASSERT_EQ(68, (int)qualityStats["lifetimeInterfaceEfficiency1Prct"]);
+            ASSERT_EQ(68, (int)qualityStats["lifetimeLibraryEfficiencyPrct"]);
+            ASSERT_EQ(96, (int)qualityStats["lifetimeReadEfficiencyPrct"]);
+            ASSERT_EQ(98, (int)qualityStats["lifetimeWriteEfficiencyPrct"]);
+            ASSERT_EQ(68, (int)qualityStats["lifetimeMediumEfficiencyPrct"]);
+  
+            ASSERT_EQ(68, (int)qualityStats["mountDriveEfficiencyPrct"]);
+            ASSERT_EQ(68, (int)qualityStats["mountInterfaceEfficiency0Prct"]);
+            ASSERT_EQ(68, (int)qualityStats["mountInterfaceEfficiency1Prct"]);
+            ASSERT_EQ(68, (int)qualityStats["mountLibraryEfficiencyPrct"]);
+            ASSERT_EQ(96, (int)qualityStats["mountReadEfficiencyPrct"]);
+            ASSERT_EQ(98, (int)qualityStats["mountWriteEfficiencyPrct"]);
+            ASSERT_EQ(68, (int)qualityStats["mountMediumEfficiencyPrct"]);
+          }
+          else if (dynamic_cast<castor::tape::tapeserver::drive::DriveT10000 *>(drive.get())) {
+  
+            ASSERT_EQ(87, (int)qualityStats["mountReadEfficiencyPrct"]);
+            ASSERT_EQ(100, (int)qualityStats["mountWriteEfficiencyPrct"]);
+            ASSERT_EQ(99, (int)qualityStats["lifetimeMediumEfficiencyPrct"]);
+            ASSERT_EQ(100, (int)qualityStats["mountReadBackCheckQualityIndexPrct"]);
+          }
+          else {
+            // write test code in case quality statistics are populated of other vendors
+          }
+        }
+      }
+    }
+  } test_functor;
+
+  castor::tape::System::mockWrapper sysWrapperSLC5;
+  castor::tape::System::mockWrapper sysWrapperSLC6;
+  sysWrapperSLC5.fake.setupSLC5();
+  sysWrapperSLC6.fake.setupSLC6();
+  sysWrapperSLC5.delegateToFake();
+  sysWrapperSLC6.delegateToFake();
+  test_functor(sysWrapperSLC5);
+  test_functor(sysWrapperSLC6);
+}
+
+TEST(castor_tape_drive_Drive, getDriveStats) {
+  struct {
+    void operator()(castor::tape::System::mockWrapper &sysWrapper) {
+      EXPECT_CALL(sysWrapper, opendir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, readdir(_)).Times(AtLeast(68));
+      EXPECT_CALL(sysWrapper, closedir(_)).Times(AtLeast(5));
+      EXPECT_CALL(sysWrapper, realpath(_, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, open(_, _)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, read(_, _, _)).Times(AtLeast(76));
+      EXPECT_CALL(sysWrapper, write(_, _, _)).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<mtget*>())).Times(0);
+      EXPECT_CALL(sysWrapper, ioctl(_, _, An<sg_io_hdr_t *>())).Times(8);
+      EXPECT_CALL(sysWrapper, close(_)).Times(AtLeast(42));
+      EXPECT_CALL(sysWrapper, readlink(_, _, _)).Times(AtLeast(6));
+      EXPECT_CALL(sysWrapper, stat(_, _)).Times(AtLeast(14));
+  
+      /* Test: detect devices, then open the device files */
+      castor::tape::SCSI::DeviceVector dl(sysWrapper);
+      for (std::vector<castor::tape::SCSI::DeviceInfo>::iterator i = dl.begin();
+           i != dl.end(); i++) {
+        if (castor::tape::SCSI::Types::tape == i->type) {
+          std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive(
+            castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
+          std::map<std::string,uint32_t> driveStats = drive->getDriveStats();
+  
+          /*
+           * Assertions for common metrics are moved inside the special cases
+           * due to different scales. Moreover, ibm gathers the statistics from multiple source
+           * So, this distinction aims to deduplicate as far as possible the tests of different
+           * drives in order for future changes to be easier to test.
+           */
+  
+          if (dynamic_cast<castor::tape::tapeserver::drive::DriveIBM3592 *>(drive.get())) {
+            ASSERT_EQ(687, driveStats["mountServoTemps"]);
+            ASSERT_EQ(771, driveStats["mountServoTransients"]);
+            ASSERT_EQ(753, driveStats["mountTemps"]);
+            ASSERT_EQ(497, driveStats["mountReadTransients"]);
+            ASSERT_EQ(258, driveStats["mountWriteTransients"]);
+            ASSERT_EQ(273, driveStats["mountTotalReadRetries"]);
+            ASSERT_EQ(306, driveStats["mountTotalWriteRetries"]);
+          }
+          else if (dynamic_cast<castor::tape::tapeserver::drive::DriveT10000 *>(drive.get())) {
+            ASSERT_EQ(531, driveStats["mountServoTemps"]);
+            ASSERT_EQ(137743, driveStats["mountServoTransients"]);
+            ASSERT_EQ(16777217, driveStats["mountTemps"]);
+            ASSERT_EQ(65794, driveStats["mountReadTransients"]);
+            ASSERT_EQ(16843266, driveStats["mountWriteTransients"]);
+            ASSERT_EQ(16909060, driveStats["mountTotalReadRetries"]);
+            ASSERT_EQ(65535, driveStats["mountTotalWriteRetries"]);
+          }
+        }
+      }
+    }
+  } test_functor;
+  castor::tape::System::mockWrapper sysWrapperSLC5;
+  castor::tape::System::mockWrapper sysWrapperSLC6;
+  sysWrapperSLC5.fake.setupSLC5();
+  sysWrapperSLC6.fake.setupSLC6();
+  sysWrapperSLC5.delegateToFake();
+  sysWrapperSLC6.delegateToFake();
+  test_functor(sysWrapperSLC5);
+  test_functor(sysWrapperSLC6);
+}
+
 TEST(castor_tape_drive_Drive, getTapeAlerts) {
 
   /**
diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp
index 5922947fc8205062b8873a82623f9f0bc6cf8835..758756afa7f2a013b962532dd70b784e7cc5a5a3 100644
--- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp
@@ -276,3 +276,62 @@ castor::tape::tapeserver::drive::lbpToUse
 bool castor::tape::tapeserver::drive::FakeDrive::hasTapeInPlace() {
   return true;
 }
+
+std::map<std::string,uint32_t> castor::tape::tapeserver::drive::FakeDrive::getTapeWriteErrors() {
+  std::map<std::string,uint32_t> writeErrorsStats;
+  writeErrorsStats["mountTotalCorrectedWriteErrors"] = 5;
+  writeErrorsStats["mountTotalWriteBytesProcessed"] = 4096;
+  writeErrorsStats["mountTotalUncorrectedWriteErrors"] = 1;
+
+  return writeErrorsStats;
+}
+
+std::map<std::string,uint32_t> castor::tape::tapeserver::drive::FakeDrive::getTapeReadErrors() {
+  std::map<std::string,uint32_t> readErrorsStats;
+  readErrorsStats["mountTotalCorrectedReadErrors"]= 5;
+  readErrorsStats["mountTotalReadBytesProcessed"] = 4096;
+  readErrorsStats["mountTotalUncorrectedReadErrors"]= 1;
+
+  return readErrorsStats;
+}
+
+std::map<std::string,uint32_t> castor::tape::tapeserver::drive::FakeDrive::getTapeNonMediumErrors() {
+  std::map<std::string,uint32_t> nonMediumErrorsStats;
+  nonMediumErrorsStats["mountTotalNonMediumErrorCounts"] = 2;
+
+  return nonMediumErrorsStats;
+}
+
+std::map<std::string,float> castor::tape::tapeserver::drive::FakeDrive::getQualityStats() {
+  // Only common IBM and Oracle stats are included in the return value;
+  std::map<std::string,float> qualityStats;
+  qualityStats["lifetimeMediumEfficiencyPrct"] = 100.0;
+  qualityStats["mountReadEfficiencyPrct"] = 100.0;
+  qualityStats["mountWriteEfficiencyPrct"] = 100.0;
+
+  return qualityStats;
+}
+
+std::map<std::string,uint32_t> castor::tape::tapeserver::drive::FakeDrive::getDriveStats() {
+  std::map<std::string,uint32_t> driveStats;
+
+  driveStats["mountTemps"] = 100;
+  driveStats["mountReadTransients"] = 10;
+  driveStats["mountWriteTransients"] = 10;
+  driveStats["mountTotalReadRetries"] = 25;
+  driveStats["mountTotalWriteRetries"] = 25;
+  driveStats["mountServoTemps"] = 10;
+  driveStats["mountServoTransients"] = 5;
+
+  return driveStats;
+}
+
+std::string castor::tape::tapeserver::drive::FakeDrive::getDriveFirmwareVersion() {
+  return std::string("123A");
+}
+
+std::map<std::string,uint32_t> castor::tape::tapeserver::drive::FakeDrive::getVolumeStats() {
+  // No available data
+  return std::map<std::string,uint32_t>();
+}
+
diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp
index 2bdd73982464bc8678529b26606991ea172bb5ef..fa9845f657a72357417b3d277aa0d31020ddde97 100644
--- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp
@@ -59,6 +59,13 @@ namespace drive {
     virtual ~FakeDrive() throw(){}
     virtual compressionStats getCompression() ;
     virtual void clearCompressionStats() ;
+    virtual std::map<std::string,uint32_t> getTapeWriteErrors();
+    virtual std::map<std::string,uint32_t> getTapeReadErrors();
+    virtual std::map<std::string,uint32_t> getTapeNonMediumErrors();
+    virtual std::map<std::string,float> getQualityStats();
+    virtual std::map<std::string,uint32_t> getDriveStats();
+    virtual std::map<std::string,uint32_t> getVolumeStats();
+    virtual std::string getDriveFirmwareVersion();
     virtual deviceInfo getDeviceInfo() ;
     virtual std::string getSerialNumber() ;
     virtual void positionToLogicalObject(uint32_t blockId) ;
diff --git a/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp b/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp
index 692c0d633714b284819ddfdb8ff2f4a9548f06fb..b8ce64335ce95f0fc1671c3ac57f38d443c382fe 100644
--- a/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp
+++ b/tapeserver/castor/tape/tapeserver/system/FileWrappers.cpp
@@ -252,9 +252,15 @@ int System::stDeviceFile::ioctlLogSense(sg_io_hdr_t * sgio_h) {
     return -1;
   }
   switch (cdb.pageCode) {
+    case SCSI::logSensePages::readErrors:
+      return logSenseReadErrorsPage(sgio_h);
+    case SCSI::logSensePages::writeErrors:
+      return logSenseWriteErrorsPage(sgio_h);
+    case SCSI::logSensePages::nonMediumErrors:
+      return logSenseNonMediumErrorsPage(sgio_h);
     case SCSI::logSensePages::sequentialAccessDevicePage:
       return logSenseSequentialAccessDevicePage(sgio_h);
-    case SCSI::logSensePages::dataCompression32h:
+    case SCSI::logSensePages::dataCompression32h: // SCSI::logSensePages::driveWriteErrors
       return logSenseDataCompression32h(sgio_h);
     case SCSI::logSensePages::blockBytesTransferred:
       return logSenseBlockBytesTransferred(sgio_h);
@@ -264,6 +270,534 @@ int System::stDeviceFile::ioctlLogSense(sg_io_hdr_t * sgio_h) {
   errno = EINVAL;
   return -1;
 }
+
+int System::stOracleT10000Device::ioctlLogSense(sg_io_hdr_t * sgio_h) {
+  int superRes = System::stDeviceFile::ioctlLogSense(sgio_h);
+  /*
+   * The following checks have to be redone because we don't know why the super
+   * function might have failed. It may be because of the checks, it may be because
+   * it did not find any page, it may be because the specific ioctl failed.
+   */
+  if (superRes == -1) {
+    if (SG_DXFER_FROM_DEV != sgio_h->dxfer_direction) {
+      errno = EINVAL;
+      return -1;
+    }
+    SCSI::Structures::logSenseCDB_t &cdb =
+      *(SCSI::Structures::logSenseCDB_t *) sgio_h->cmdp;
+    if (1 != cdb.PC || 0 == SCSI::Structures::toU16(cdb.allocationLength)) {
+      errno = EINVAL;
+      return -1;
+    }
+    /*
+     * Here we are parsing only Oracle T10000 specific pages.
+     */
+    switch (cdb.pageCode) {
+      case SCSI::logSensePages::vendorUniqueDriveStatistics:
+        return logSenseVendorUniqueDriveStatisticsPage(sgio_h);
+    }
+    errno = EINVAL;
+    return -1;
+  }
+  else
+    return superRes;
+}
+
+int System::stIBM3592DeviceFile::ioctlLogSense(sg_io_hdr_t * sgio_h) {
+  int superRes = System::stDeviceFile::ioctlLogSense(sgio_h);
+  /*
+   * The following checks have to be redone because we don't know why the super
+   * function might have failed. It may be because of the checks, it may be because
+   * it did not find any page, it may be because the specific ioctl failed.
+   */
+
+  /*
+   * In this function, we deliberately don't check the result of the parent function's
+   * output because we have a conflict between the LogSense codes (dataCompression32h and
+   * driveWriteErrors). So, even if the logSenseDataCompression32h() gets executed, we still want to execute
+   * the logSenseDriveWriteErrorsPage() function.
+   * Still, we need to **account for the redundant ioctl call** in the assertions.
+   */
+
+  if (SG_DXFER_FROM_DEV != sgio_h->dxfer_direction) {
+    errno = EINVAL;
+    return -1;
+  }
+  SCSI::Structures::logSenseCDB_t &cdb =
+    *(SCSI::Structures::logSenseCDB_t *) sgio_h->cmdp;
+  if (1 != cdb.PC || 0 == SCSI::Structures::toU16(cdb.allocationLength)) {
+    errno = EINVAL;
+    return -1;
+  }
+  /*
+   * Here we are parsing only IBM 3592 specific pages.
+   */
+  switch (cdb.pageCode) {
+    case SCSI::logSensePages::volumeStatistics:
+      return logSenseVolumeStatisticsPage(sgio_h);
+    case SCSI::logSensePages::driveWriteErrors:
+      return logSenseDriveWriteErrorsPage(sgio_h);
+    case SCSI::logSensePages::driveReadForwardErrors:
+      return logSenseDriveReadForwardErrorsPage(sgio_h);
+    case SCSI::logSensePages::driveReadBackwardErrors:
+      return logSenseDriveReadBackwardErrorsPage(sgio_h);
+    case SCSI::logSensePages::performanceCharacteristics:
+      return logSensePerformanceCharacteristicsPage(sgio_h);
+  }
+  if (superRes == -1) {
+    errno = EINVAL;
+    return -1;
+  }
+  else
+    return superRes;
+}
+
+int System::stOracleT10000Device::logSenseReadErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x03, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x74, 0x04, // 0x00
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x74, 0x04, // 0x10
+    0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x74, 0x08, // 0x20
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x74, 0x04, 0x00, 0x00, 0x00, 0x01  // 0x30
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseReadErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x03, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x60, 0x02, 0x00, 0x02, // 0x00
+    0x00, 0x05, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x60, 0x02, 0x00, 0x01  // 0x10
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stOracleT10000Device::logSenseWriteErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x02, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x74, 0x04, // 0x00
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x74, 0x04, // 0x10
+    0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x74, 0x08, // 0x20
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x74, 0x04, 0x00, 0x00, 0x00, 0x01  // 0x30
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseWriteErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x02, 0x00, 0x00, 0x1c, 0x00, 0x02, 0x60, 0x02, 0x00, 0x00, 0x00, 0x03, 0x60, 0x02, 0x00, 0x02, // 0x00
+    0x00, 0x05, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x60, 0x02, 0x00, 0x01  // 0x10
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stOracleT10000Device::logSenseNonMediumErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x60, 0x04, 0x00, 0x00, 0x00, 0x03 // 0x00
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseNonMediumErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x74, 0x04,  0x00, 0x00, 0x00, 0x03 // 0x00
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseVolumeStatisticsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x57, 0x01, 0x02, 0x4c, 0x00, 0x00, 0x43, 0x01, 0x01, 0x00, 0x01, 0x43, 0x04, 0x01, 0x20, 0x30, //0x00
+    0x62, 0x00, 0x02, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xce, 0xf8, 0x00, 0x03, 0x43, //0x10
+    0x04, 0x01, 0x02, 0x03, 0x01, 0x00, 0x04, 0x43, 0x02, 0x00, 0x01, 0x00, 0x05, 0x43, 0x02, 0x00, //0x20
+    0x04, 0x00, 0x06, 0x43, 0x02, 0x00, 0x00, 0x00, 0x07, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, //0x30
+    0x16, 0x98, 0x68, 0x00, 0x08, 0x43, 0x04, 0x01, 0x01, 0x01, 0xd7, 0x00, 0x09, 0x43, 0x02, 0x02, //0x40
+    0x02, 0x00, 0x0c, 0x43, 0x02, 0x00, 0x00, 0x00, 0x0d, 0x43, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x43, //0x50
+    0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x0f, 0x43, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x10, 0x43, //0x60
+    0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0x98, 0x2b, 0x00, 0x11, 0x43, 0x08, 0x00, 0x00, 0x00, //0x70
+    0x00, 0x00, 0x71, 0xad, 0x59, 0x00, 0x12, 0x43, 0x02, 0x00, 0x00, 0x00, 0x13, 0x43, 0x02, 0x00, //0x80
+    0xc3, 0x00, 0x14, 0x43, 0x06, 0x00, 0x00, 0x00, 0x00, 0x7a, 0x82, 0x00, 0x15, 0x43, 0x06, 0x00, //0x90
+    0x00, 0x00, 0x00, 0x2c, 0x2f, 0x00, 0x16, 0x43, 0x04, 0x00, 0x98, 0x96, 0x80, 0x00, 0x17, 0x43, //0xa0
+    0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x40, 0x41, 0x20, 0x31, 0x34, 0x37, 0x45, 0x42, 0x30, 0x32, //0xb0
+    0x35, 0x36, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0xc0
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x41, 0x41, 0x08, 0x32, 0x30, 0x32, //0xd0
+    0x30, 0x32, 0x30, 0x32, 0x30, 0x00, 0x42, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0xe0
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0xf0
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x43, 0x41, 0x08, 0x49, 0x42, 0x4d, //0x100
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x44, 0x41, 0x04, 0x55, 0x31, 0x30, 0x37, 0x00, 0x45, 0x41, //0x110
+    0x08, 0x33, 0x35, 0x39, 0x32, 0x4a, 0x44, 0x47, 0x35, 0x00, 0x46, 0x41, 0x08, 0x32, 0x30, 0x31, //0x120
+    0x34, 0x30, 0x38, 0x31, 0x35, 0x00, 0x80, 0x43, 0x01, 0x00, 0x00, 0x81, 0x43, 0x01, 0x00, 0x00, //0x130
+    0x82, 0x43, 0x01, 0x00, 0x01, 0x00, 0x43, 0x04, 0x00, 0x00, 0x00, 0x2e, 0x01, 0x01, 0x43, 0x04, //0x140
+    0x02, 0x03, 0x07, 0x24, 0x01, 0x02, 0x43, 0x04, 0x01, 0x02, 0x01, 0x16, 0x02, 0x00, 0x43, 0x0a, //0x150
+    0x09, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x43, 0x0a, 0x09, 0x00, //0x160
+    0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0x43, 0x08, 0x07, 0x00, 0x00, 0x00, //0x170
+    0x00, 0x98, 0x96, 0x80, 0x02, 0x03, 0x43, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, //0x180
+    0x02, 0x04, 0x43, 0x08, 0x07, 0x00, 0x00, 0x00, 0x00, 0x98, 0x96, 0x79, 0x03, 0x00, 0x43, 0xb0, //0x190
+    0x2c, 0x00, 0x00, 0x00, 0x49, 0x42, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x37, //0x1a0
+    0x38, 0x44, 0x38, 0x34, 0x39, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0x1b0
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2c, 0x00, 0x00, 0x01, //0x1c0
+    0x49, 0x42, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x37, 0x38, 0x44, 0x38, 0x34, //0x1d0
+    0x39, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0x1e0
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2c, 0x00, 0x00, 0x02, 0x49, 0x42, 0x4d, 0x20, //0x1f0
+    0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x37, 0x38, 0x44, 0x38, 0x34, 0x39, 0x41, 0x20, 0x20, //0x200
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0x210
+    0x20, 0x20, 0x20, 0x20, 0x2c, 0x00, 0x00, 0x03, 0x49, 0x42, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, //0x220
+    0x30, 0x30, 0x30, 0x37, 0x38, 0x44, 0x38, 0x34, 0x39, 0x41, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, //0x230
+    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20  //0x240
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stOracleT10000Device::logSenseVendorUniqueDriveStatisticsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x3d, 0x00, 0x0c, 0x08, 0x01, 0x00, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x74, 0x04,  // 0x00 
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x74, 0x04,  // 0x10 
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x74, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x05, 0x74, 0x04,  // 0x20
+    0x00, 0x01, 0x01, 0x02, 0x01, 0x06, 0x74, 0x04, 0x01, 0x01, 0x02, 0x02, 0x01, 0x07, 0x74, 0x04,  // 0x30
+    0x00, 0x00, 0x02, 0x13, 0x01, 0x08, 0x74, 0x04, 0x00, 0x02, 0x1a, 0x0f, 0x01, 0x09, 0x74, 0x04,  // 0x40
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x0a, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x74, 0x04,  // 0x50 
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0d, 0x74, 0x04,  // 0x60 
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x74, 0x04, 0x00, 0x00, 0x01, 0x9a, 0x01, 0x10, 0x74, 0x04,  // 0x70 
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x74, 0x04,  // 0x80 
+    0x00, 0x00, 0xff, 0xff, 0x01, 0x14, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x15, 0x74, 0x04,  // 0x90
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x16, 0x74, 0x04, 0x00, 0x00, 0x00, 0x65, 0x01, 0x17, 0x74, 0x04,  // 0xa0 
+    0x00, 0x00, 0x00, 0x01, 0x01, 0x18, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x74, 0x04,  // 0xb0 
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x21, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x22, 0x74, 0x04,  // 0xc0 
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x74, 0x04,  // 0xd0 
+    0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x74, 0x04,  // 0xe0 
+    0x01, 0x00, 0x00, 0x01, 0x02, 0x04, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x74, 0x08,  // 0xf0
+    0x00, 0x00, 0x00, 0x00, 0x0f, 0xa8, 0x03, 0x70, 0x03, 0x01, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00,  // 0x100
+    0x0f, 0xb0, 0x54, 0x58, 0x03, 0x02, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x110
+    0x03, 0x03, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x74, 0x08,  // 0x120
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf9, 0x03, 0x05, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00,  // 0x130
+    0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf9,  // 0x140
+    0x03, 0x07, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0x74, 0x08,  // 0x150
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x03, 0x09, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00,  // 0x160
+    0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x74, 0x04, 0x00, 0x00, 0x00, 0x07, 0x03, 0x0c, 0x74, 0x08,  // 0x170
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0d, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00,  // 0x180
+    0x00, 0x00, 0x0f, 0x8d, 0x03, 0x0e, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0f, 0x74, 0x08,  // 0x190
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x03, 0x10, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00,  // 0x1a0
+    0x00, 0x00, 0x52, 0xa0, 0x03, 0x11, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xf1,  // 0x1b0
+    0x03, 0x12, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x7f, 0x03, 0x13, 0x74, 0x08,  // 0x1c0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x14, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00,  // 0x1d0
+    0x00, 0x00, 0x00, 0x00, 0x03, 0x15, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x1e0
+    0x03, 0x16, 0x74, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x74, 0x04,  // 0x1f0
+    0x00, 0x00, 0x03, 0xde, 0x04, 0x01, 0x74, 0x04, 0x00, 0x00, 0x36, 0xaf, 0x04, 0x02, 0x74, 0x04,  // 0x200
+    0x00, 0x00, 0x3e, 0x80, 0x04, 0x03, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x74, 0x04,  // 0x210
+    0x00, 0x00, 0x00, 0x00, 0x04, 0x07, 0x74, 0x04, 0x00, 0x00, 0x03, 0xe8, 0x04, 0x08, 0x74, 0x04,  // 0x220
+    0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x74, 0x40, 0x00, 0x00, 0x01, 0x63, 0x00, 0x00, 0x00, 0x05,  // 0x230
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x240
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x250
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x260
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x74, 0x10, 0x00, 0x00, 0x53, 0x65,  // 0x270
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x01, 0x74, 0x10,  // 0x280
+    0x00, 0x00, 0x53, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x290
+    0x12, 0x00, 0x74, 0x20, 0x00, 0x00, 0x53, 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,  // 0x2a0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,  // 0x2b0
+    0x00, 0x00, 0x00, 0x00, 0x12, 0x01, 0x74, 0x20, 0x00, 0x00, 0x53, 0x58, 0x00, 0x00, 0x00, 0x00,  // 0x2c0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,  // 0x2d0
+    0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x12, 0x02, 0x74, 0x20, 0x00, 0x00, 0x53, 0x65,  // 0x2e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x2f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x03, 0x74, 0x20,  // 0x300
+    0x00, 0x00, 0x53, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x310
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x320
+    0x13, 0x10, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x330
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x340
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x350
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x360
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x370
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x380
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x390
+    0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2d, 0x00, 0x00, 0x00, 0x00,  // 0x3a0
+    0x00, 0x00, 0x25, 0x99, 0x13, 0x11, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0b,  // 0x3b0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,  // 0x3c0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x3d0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x3e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x3f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x400
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x410
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x420
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x20, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00,  // 0x430
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x440
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x450
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x460
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x470
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x480
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x490
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,  // 0x4a0
+    0x00, 0x00, 0x03, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xd5, 0x13, 0x21, 0x74, 0x80,  // 0x4b0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x24,  // 0x4c0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x4d0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x4e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x4f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x500
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x510
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x520
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x530
+    0x14, 0x00, 0x74, 0x80, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c,  // 0x540
+    0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c,  // 0x550
+    0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c,  // 0x560
+    0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c,  // 0x570
+    0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c,  // 0x580
+    0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6a,  // 0x590
+    0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0x6c,  // 0x5a0
+    0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c, 0x00, 0x00, 0x01, 0x6c,  // 0x5b0
+    0x00, 0x00, 0x01, 0x6c, 0x14, 0x02, 0x74, 0x80, 0x00, 0x00, 0x22, 0x01, 0x00, 0x00, 0x0c, 0xb6,  // 0x5c0
+    0x00, 0x00, 0x1a, 0x70, 0x00, 0x00, 0x1c, 0xf7, 0x00, 0x00, 0x1b, 0x11, 0x00, 0x00, 0x13, 0x98,  // 0x5d0
+    0x00, 0x00, 0x22, 0x21, 0x00, 0x00, 0x09, 0xea, 0x00, 0x00, 0x0d, 0xe5, 0x00, 0x00, 0x0c, 0x4e,  // 0x5e0
+    0x00, 0x00, 0x0b, 0x07, 0x00, 0x00, 0x14, 0x07, 0x00, 0x00, 0x21, 0xd9, 0x00, 0x00, 0x17, 0x3d,  // 0x5f0
+    0x00, 0x00, 0x1a, 0x70, 0x00, 0x00, 0x16, 0x2b, 0x00, 0x00, 0x16, 0xb2, 0x00, 0x00, 0x28, 0xc7,  // 0x600
+    0x00, 0x00, 0x12, 0x8a, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x14, 0x66, 0x00, 0x00, 0x18, 0x8a,  // 0x610
+    0x00, 0x00, 0x3d, 0xee, 0x00, 0x00, 0x1e, 0x8d, 0x00, 0x00, 0x0f, 0xf5, 0x00, 0x00, 0x1d, 0xf6,  // 0x620
+    0x00, 0x00, 0x11, 0xb1, 0x00, 0x00, 0x11, 0x68, 0x00, 0x00, 0x2d, 0xb4, 0x00, 0x00, 0x18, 0xd3,  // 0x630
+    0x00, 0x00, 0x1d, 0x7f, 0x00, 0x00, 0x1d, 0x4e, 0x14, 0x04, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00,  // 0x640
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x650
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x660
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x670
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x680
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x690
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x6a0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x6b0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x05, 0x74, 0x80,  // 0x6c0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x6d0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x6e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x6f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x700
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x710
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x720
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x730
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x740
+    0x14, 0x06, 0x74, 0x80, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0e,  // 0x750
+    0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d,  // 0x760
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01,  // 0x770
+    0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x0a,  // 0x780
+    0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02,  // 0x790
+    0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x5e,  // 0x7a0
+    0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x04,  // 0x7b0
+    0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0a,  // 0x7c0
+    0x00, 0x00, 0x00, 0x08, 0x15, 0x00, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x7d0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x7e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x7f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x800
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x810
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x820
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x830
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x840
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x01, 0x74, 0x80, 0x00, 0x00, 0x01, 0x42,  // 0x850
+    0x00, 0x00, 0x02, 0x1d, 0x00, 0x00, 0x01, 0x72, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x74,  // 0x860
+    0x00, 0x00, 0x01, 0xae, 0x00, 0x00, 0x01, 0x53, 0x00, 0x00, 0x02, 0x3c, 0x00, 0x00, 0x01, 0xff,  // 0x870
+    0x00, 0x00, 0x02, 0x26, 0x00, 0x00, 0x02, 0x17, 0x00, 0x00, 0x01, 0xb8, 0x00, 0x00, 0x01, 0x35,  // 0x880
+    0x00, 0x00, 0x01, 0x9b, 0x00, 0x00, 0x01, 0x77, 0x00, 0x00, 0x01, 0xaf, 0x00, 0x00, 0x01, 0xa3,  // 0x890
+    0x00, 0x00, 0x01, 0x17, 0x00, 0x00, 0x01, 0xc5, 0x00, 0x00, 0x01, 0x8f, 0x00, 0x00, 0x01, 0xb4,  // 0x8a0
+    0x00, 0x00, 0x01, 0x7d, 0x00, 0x00, 0x00, 0xb3, 0x00, 0x00, 0x01, 0x6b, 0x00, 0x00, 0x01, 0xe7,  // 0x8b0
+    0x00, 0x00, 0x01, 0x65, 0x00, 0x00, 0x01, 0xc6, 0x00, 0x00, 0x01, 0xca, 0x00, 0x00, 0x01, 0x0a,  // 0x8c0
+    0x00, 0x00, 0x01, 0x85, 0x00, 0x00, 0x01, 0x54, 0x00, 0x00, 0x01, 0x66, 0x15, 0x02, 0x74, 0x80,  // 0x8d0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x8e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x8f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x900
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x910
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x920
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x930
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x940
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x950
+    0x15, 0x03, 0x74, 0x80, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x960
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x970
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x980
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x990
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x9a0
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x9b0
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x9c0
+    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00,  // 0x9d0
+    0x00, 0x00, 0x04, 0x00, 0x15, 0x04, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x9e0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x9f0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa00
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa10
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa20
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa30
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa40
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa50
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x05, 0x74, 0x80, 0x00, 0x00, 0x00, 0x00,  // 0xa60
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa70
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa80
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xa90
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xaa0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xab0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xac0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0xad0
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x05, 0x74, 0x04,  // 0xae0
+    0x00, 0x00, 0x00, 0x00, 0x24, 0x06, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x24, 0x07, 0x74, 0x04,  // 0xaf0
+    0x00, 0x00, 0x4d, 0x5a, 0x24, 0x08, 0x74, 0x04, 0x00, 0x00, 0x4d, 0x5a, 0x25, 0x00, 0x74, 0x04,  // 0xb00
+    0x28, 0x00, 0x28, 0x28, 0x25, 0x01, 0x74, 0x04, 0x28, 0x00, 0x28, 0x28, 0x25, 0x02, 0x74, 0x04,  // 0xb10
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x03, 0x74, 0x04, 0x00, 0x00, 0x00, 0x04, 0x25, 0x04, 0x74, 0x04,  // 0xb20
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x05, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x06, 0x74, 0x04,  // 0xb30
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x07, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x08, 0x74, 0x04,  // 0xb40
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x09, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0a, 0x74, 0x04,  // 0xb50
+    0x00, 0x01, 0x1b, 0x15, 0x25, 0x0b, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0c, 0x74, 0x04,  // 0xb60
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x0d, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x0e, 0x74, 0x04,  // 0xb70
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x0f, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x10, 0x74, 0x04,  // 0xb80
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x11, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x12, 0x74, 0x04,  // 0xb90
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x13, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x14, 0x74, 0x04,  // 0xba0
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x15, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x16, 0x74, 0x04,  // 0xbb0
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x17, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x18, 0x74, 0x04,  // 0xbc0
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x19, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x1a, 0x74, 0x04,  // 0xbd0
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x1b, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x1c, 0x74, 0x04,  // 0xbe0
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x1d, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00, 0x25, 0x1e, 0x74, 0x04,  // 0xbf0
+    0x00, 0x00, 0x00, 0x00, 0x25, 0x1f, 0x74, 0x04, 0x00, 0x00, 0x00, 0x00   // 0xc00
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseDriveWriteErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x32, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x01, 0x60, 0x02, 0x01, 0x01, // 0x00
+    0x00, 0x02, 0x60, 0x02, 0x01, 0x02, 0x00, 0x03, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x60, 0x02, // 0x10
+    0x00, 0x00, 0x00, 0x05, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x60, 0x02, 0x00, 0xac, 0x00, 0x07, // 0x20
+    0x60, 0x02, 0x01, 0x22, 0x00, 0x08, 0x60, 0x02, 0x01, 0x32, 0x00, 0x09, 0x60, 0x02, 0x00, 0x00, // 0x30
+    0x00, 0x0a, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x60, 0x02, // 0x40
+    0x00, 0x00, 0x00, 0x0d, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0f, // 0x50
+    0x60, 0x02, 0x00, 0x00, 0x00, 0x10, 0x60, 0x02, 0x00, 0x00, 0x00, 0x11, 0x60, 0x02, 0x00, 0x00  // 0x60
+  };
+
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseDriveReadForwardErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x34, 0x00, 0x00, 0xba, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x01, 0x60, 0x02, 0x01, 0x01,  //0x00
+    0x00, 0x02, 0x60, 0x02, 0x00, 0xff, 0x00, 0x03, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x60, 0x02,  //0x10
+    0x00, 0x00, 0x00, 0x05, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x60, 0x02, 0x01, 0x01, 0x00, 0x07,  //0x20
+    0x60, 0x02, 0x00, 0xcf, 0x00, 0x08, 0x60, 0x02, 0x00, 0x00, 0x00, 0x09, 0x60, 0x02, 0x00, 0x00,  //0x30
+    0x00, 0x0a, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x60, 0x02,  //0x40
+    0x00, 0x00, 0x00, 0x0d, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0f,  //0x50
+    0x60, 0x02, 0x00, 0x00, 0x00, 0x10, 0x60, 0x02, 0x00, 0x00, 0x00, 0x11, 0x60, 0x02, 0x00, 0x00,  //0x60
+    0x00, 0x12, 0x60, 0x02, 0x00, 0x00, 0x00, 0x13, 0x60, 0x02, 0x00, 0x00, 0x00, 0x14, 0x60, 0x02,  //0x70
+    0x00, 0x00, 0x00, 0x15, 0x60, 0x02, 0x01, 0x11, 0x00, 0x16, 0x60, 0x02, 0x00, 0x00, 0x00, 0x17,  //0x80
+    0x60, 0x02, 0x00, 0x00, 0x00, 0x18, 0x60, 0x02, 0x00, 0x00, 0x00, 0x19, 0x60, 0x02, 0x00, 0x00,  //0x90
+    0x00, 0x1a, 0x60, 0x02, 0x00, 0x00, 0x00, 0x1b, 0x60, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x60, 0x02,  //0xa0
+    0x00, 0x00, 0x00, 0x1d, 0x60, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x60, 0x02, 0x00, 0x00  //0xb0
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSenseDriveReadBackwardErrorsPage(sg_io_hdr_t * sgio_h) {
+  unsigned char output[] = {
+    0x36, 0x00, 0x00, 0xba, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x01, 0x60, 0x02, 0x01, 0x01,  //0x00
+    0x00, 0x02, 0x60, 0x02, 0x00, 0xf2, 0x00, 0x03, 0x60, 0x02, 0x00, 0x00, 0x00, 0x04, 0x60, 0x02,  //0x10
+    0x00, 0x00, 0x00, 0x05, 0x60, 0x02, 0x00, 0x00, 0x00, 0x06, 0x60, 0x02, 0x01, 0x02, 0x00, 0x07,  //0x20
+    0x60, 0x02, 0x01, 0x00, 0x00, 0x08, 0x60, 0x02, 0x00, 0x00, 0x00, 0x09, 0x60, 0x02, 0x00, 0x00,  //0x30
+    0x00, 0x0a, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0b, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0c, 0x60, 0x02,  //0x40
+    0x00, 0x00, 0x00, 0x0d, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0e, 0x60, 0x02, 0x00, 0x00, 0x00, 0x0f,  //0x50
+    0x60, 0x02, 0x00, 0x00, 0x00, 0x10, 0x60, 0x02, 0x00, 0x00, 0x00, 0x11, 0x60, 0x02, 0x00, 0x00,  //0x60
+    0x00, 0x12, 0x60, 0x02, 0x00, 0x00, 0x00, 0x13, 0x60, 0x02, 0x00, 0x00, 0x00, 0x14, 0x60, 0x02,  //0x70
+    0x00, 0x00, 0x00, 0x15, 0x60, 0x02, 0x00, 0x00, 0x00, 0x16, 0x60, 0x02, 0x00, 0x00, 0x00, 0x17,  //0x80
+    0x60, 0x02, 0x00, 0x00, 0x00, 0x18, 0x60, 0x02, 0x00, 0x00, 0x00, 0x19, 0x60, 0x02, 0x00, 0x00,  //0x90
+    0x00, 0x1a, 0x60, 0x02, 0x00, 0x00, 0x00, 0x1b, 0x60, 0x02, 0x00, 0x00, 0x00, 0x1c, 0x60, 0x02,  //0xa0
+    0x00, 0x00, 0x00, 0x1d, 0x60, 0x02, 0x00, 0x00, 0x00, 0x1e, 0x60, 0x02, 0x00, 0x00  //0xb0
+  };
+  if (sizeof (output) > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, sizeof (output));
+  return 0;
+}
+
+int System::stIBM3592DeviceFile::logSensePerformanceCharacteristicsPage(sg_io_hdr_t * sgio_h) {
+  SCSI::Structures::logSenseCDB_t* cdb = (SCSI::Structures::logSenseCDB_t*) (sgio_h->cmdp);
+  unsigned char *output;
+  unsigned int output_size = 0;
+  if(cdb->subPageCode == 0x80 || cdb->subPageCode == 0x40) {
+    unsigned char output_80[] = {
+      0x77, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x60, 0x01, 0x50, 0x00, 0x01, 0x60, 0x01, 0x50, 0x00, 0x10, // 0x00
+      0x60, 0x01, 0x01, 0x00, 0x11, 0x60, 0x01, 0x50, 0x00, 0x12, 0x60, 0x01, 0x50, 0x00, 0x1a, 0x60, // 0x10
+      0x01, 0x50  // 0x20
+    };
+    output = output_80;
+    output_size = sizeof(output_80);
+  }
+  else if(cdb->subPageCode == 0x91 || cdb->subPageCode == 0x51) { ;
+    unsigned char output_91[] = {
+           0x77, 0x91, 0x00, 0xd0, 0x01, 0x02, 0x60, 0x04, 0x00, 0x00, 0x05, 0x59, 0x02, 0x02, 0x60, 0x04, //0x00
+           0x00, 0x00, 0x10, 0x4b, 0x03, 0x02, 0x60, 0x04, 0x00, 0x11, 0x34, 0x7d, 0x03, 0xd0, 0x60, 0x04, //0x10
+           0x00, 0x60, 0x1a, 0xd3, 0x04, 0x02, 0x60, 0x04, 0x00, 0x0f, 0x7c, 0x0b, 0x04, 0xd0, 0x60, 0x04, //0x20
+           0x00, 0x62, 0xf3, 0x75, 0x05, 0x02, 0x60, 0x04, 0x00, 0x02, 0xb1, 0x68, 0x05, 0xd4, 0x60, 0x04, //0x30
+           0x00, 0x00, 0x05, 0x1b, 0x06, 0x02, 0x60, 0x04, 0x00, 0x20, 0x49, 0x13, 0x07, 0x02, 0x60, 0x04, //0x40
+           0x00, 0x06, 0xa7, 0xe9, 0x08, 0x02, 0x60, 0x04, 0x00, 0x00, 0x72, 0xcf, 0x09, 0x02, 0x60, 0x04, //0x50
+           0x00, 0x00, 0x00, 0x00, 0x0a, 0x02, 0x60, 0x04, 0x00, 0x00, 0x00, 0x2a, 0x0c, 0x02, 0x60, 0x04, //0x60
+           0x00, 0x4d, 0xcb, 0x5c, 0x0c, 0x0e, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x12, 0x60, 0x04, //0x70
+           0x00, 0x4d, 0xcb, 0x5c, 0x0c, 0x1e, 0x60, 0x04, 0x00, 0x00, 0x07, 0x03, 0x0c, 0x22, 0x60, 0x04, //0x80
+           0x00, 0x00, 0x00, 0x00, 0x0c, 0x2e, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xa2, 0x60, 0x04, //0x90
+           0x00, 0x00, 0x22, 0x39, 0x0c, 0xae, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x14, 0x60, 0x04, //0xa0
+           0x00, 0x02, 0x23, 0xac, 0x0d, 0x24, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xa4, 0x60, 0x04, //0xb0
+           0x00, 0x00, 0x00, 0x00, 0x0d, 0xf0, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf1, 0x60, 0x04, //0xc0
+           0x00, 0x00, 0x00, 0x00 //0xd0
+    };
+    output = output_91;
+    output_size = sizeof(output_91);
+  }
+  if (output_size > sgio_h->dxfer_len) {
+    errno = EINVAL;
+    return -1;
+  }
+  memcpy(sgio_h->dxferp, output, output_size);
+  return 0;
+}
+
+
+
+
+
+
+
+
+
 int System::stDeviceFile::logSenseSequentialAccessDevicePage(sg_io_hdr_t * sgio_h) {
   /**
    * This is a real reply from the enterprise T10000C STK drive. 
@@ -579,7 +1113,7 @@ int System::stDeviceFile::modeSelectControlDataProtection(sg_io_hdr_t * sgio_h)
   return 0;
 }
 
-int System::stDeviceFile::ioctlInquiry(sg_io_hdr_t * sgio_h) {
+int System::stOracleT10000Device::ioctlInquiry(sg_io_hdr_t * sgio_h) {
  if (SG_DXFER_FROM_DEV != sgio_h->dxfer_direction) {
     errno = EINVAL;
     return -1;
@@ -630,3 +1164,55 @@ int System::stDeviceFile::ioctlInquiry(sg_io_hdr_t * sgio_h) {
   }
   return 0;
 }
+
+int System::stIBM3592DeviceFile::ioctlInquiry(sg_io_hdr_t * sgio_h) {
+  if (SG_DXFER_FROM_DEV != sgio_h->dxfer_direction) {
+    errno = EINVAL;
+    return -1;
+  }
+  SCSI::Structures::inquiryCDB_t & cdb =
+    *(SCSI::Structures::inquiryCDB_t *) sgio_h->cmdp;
+
+  if (0 == cdb.EVPD && 0 == cdb.pageCode) {
+    /* the Standard Inquiry Data is returned*/
+    SCSI::Structures::inquiryData_t & inqData =
+      *(SCSI::Structures::inquiryData_t *) sgio_h->dxferp;
+    if (sizeof (inqData) > sgio_h->dxfer_len) {
+      errno = EINVAL;
+      return -1;
+    }
+    /* fill the replay with random data */
+    srandom(SCSI::Commands::INQUIRY);
+    memset(sgio_h->dxferp, random(), sizeof (inqData));
+    /* We fill only fields we need.
+     * The emptiness in the strings fields we fill with spaces.
+     * And we do not need '\0' in the end of strings. For the tests
+     * there are mhvtl data.
+     */
+    const char *prodId = "03592E08                      ";
+    memcpy(inqData.prodId, prodId, sizeof (inqData.prodId));
+    const char *prodRevLvl = "460E                      ";
+    memcpy(inqData.prodRevLvl, prodRevLvl, sizeof (inqData.prodRevLvl));
+    const char *T10Vendor = "IBM                        ";
+    memcpy(inqData.T10Vendor, T10Vendor, sizeof (inqData.T10Vendor));
+  } else if (1 == cdb.EVPD && SCSI::inquiryVPDPages::unitSerialNumber == cdb.pageCode) {
+    /* the unit serial number VPD page is returned*/
+    SCSI::Structures::inquiryUnitSerialNumberData_t & inqSerialData =
+      *(SCSI::Structures::inquiryUnitSerialNumberData_t *) sgio_h->dxferp;
+    if (sizeof (inqSerialData) > sgio_h->dxfer_len) {
+      errno = EINVAL;
+      return -1;
+    }
+    /* fill the replay with random data */
+    srandom(SCSI::Commands::INQUIRY);
+    memset(sgio_h->dxferp, random(), sgio_h->dxfer_len);
+    const char serialNumber[11] = "XYZZY_A2  ";
+    memcpy(inqSerialData.productSerialNumber, serialNumber, 10);
+    inqSerialData.pageLength = 10;
+  } else {
+    errno = EINVAL;
+    return -1;
+  }
+  return 0;
+}
+
diff --git a/tapeserver/castor/tape/tapeserver/system/FileWrappers.hpp b/tapeserver/castor/tape/tapeserver/system/FileWrappers.hpp
index 6d7083f42cfbe86fc0df0c96583935139f53e629..e8648c67f17eaeca8d3c0b1d867a8aac9e5d7ad7 100644
--- a/tapeserver/castor/tape/tapeserver/system/FileWrappers.hpp
+++ b/tapeserver/castor/tape/tapeserver/system/FileWrappers.hpp
@@ -73,7 +73,7 @@ namespace System {
     virtual int ioctl(unsigned long int request, struct mtop * mt_cmd);
     virtual int ioctl(unsigned long int request, struct mtget * mt_status);
     virtual int ioctl(unsigned long int request, sg_io_hdr_t * sgio_h);
-  private:
+  protected:
     struct mtget m_mtStat;
     struct mtop m_mtCmd;
     uint32_t blockID;  
@@ -90,7 +90,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlReadPosition(sg_io_hdr_t * sgio_h);
+    virtual int ioctlReadPosition(sg_io_hdr_t * sgio_h);
     
     /**
      * This function handles LOG_SELECT CDB and only checks the CDB for the 
@@ -101,7 +101,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlLogSelect(sg_io_hdr_t * sgio_h);
+    virtual int ioctlLogSelect(sg_io_hdr_t * sgio_h);
     
     /**
      * This function handles LOCATE_10 CDB and only checks the CDB for the 
@@ -112,7 +112,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlLocate10(sg_io_hdr_t * sgio_h);
+    virtual int ioctlLocate10(sg_io_hdr_t * sgio_h);
     
     /**
      * This function handles LOG_SENSE CDB and prepares the replay with
@@ -123,7 +123,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlLogSense(sg_io_hdr_t * sgio_h);
+    virtual int ioctlLogSense(sg_io_hdr_t * sgio_h);
     
     /**
      * This function handles MODE_SENSE_6 CDB and prepares the replay with
@@ -134,7 +134,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlModSense6(sg_io_hdr_t * sgio_h);
+    virtual int ioctlModSense6(sg_io_hdr_t * sgio_h);
     
     /**
      * This function handles MODE_SELECT_6 CDB and only checks the CDB for the
@@ -145,7 +145,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlModSelect6(sg_io_hdr_t * sgio_h);
+    virtual int ioctlModSelect6(sg_io_hdr_t * sgio_h);
     
     /**
      * This function handles INQUIRY CDB and prepares the standard inquiry
@@ -156,8 +156,32 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int ioctlInquiry(sg_io_hdr_t * sgio_h);
-    
+    virtual int ioctlInquiry(sg_io_hdr_t * sgio_h) = 0;
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to ReadErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseReadErrorsPage(sg_io_hdr_t * sgio_h) = 0;
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to WriteErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseWriteErrorsPage(sg_io_hdr_t * sgio_h) = 0;
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to NonMediumErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseNonMediumErrorsPage(sg_io_hdr_t * sgio_h) = 0;
+
     /**
      * This function prepares the replay with compression statistics for 
      * LOG SENSE CDB with log page Sequential Access Device Page. We use this 
@@ -168,7 +192,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int logSenseSequentialAccessDevicePage(sg_io_hdr_t * sgio_h);
+    virtual int logSenseSequentialAccessDevicePage(sg_io_hdr_t * sgio_h);
     
     /**
      * This function prepares the replay with compression statistics for 
@@ -180,7 +204,7 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int logSenseDataCompression32h(sg_io_hdr_t * sgio_h);
+    virtual int logSenseDataCompression32h(sg_io_hdr_t * sgio_h);
     
     /**
      * This function prepares the replay with compression statistics for 
@@ -192,7 +216,8 @@ namespace System {
      * @return        Returns 0 in success and 
      *                -1 with appropriate  errno if an error occurred.
      */
-    int logSenseBlockBytesTransferred(sg_io_hdr_t * sgio_h);
+    virtual int logSenseBlockBytesTransferred(sg_io_hdr_t * sgio_h);
+
     /**
      * This function replies with a pre-cooked error record. As with the real devices,
      * many parameter codes get reported with a flag set to 0, and a few will
@@ -249,6 +274,142 @@ namespace System {
      */
     int modeSelectControlDataProtection(sg_io_hdr_t * sgio_h);
   };
+
+  /**
+   * Specific st device class for IBM 3592.
+   * Used to test vendor specific features.
+   */
+  class stIBM3592DeviceFile : public stDeviceFile {
+  public:
+    /**
+     * This function handles LOG_SENSE CDB and prepares the replay with
+     * compression data.
+     *
+     * @param sgio_h  The pointer to the sg_io_hdr_t structure with
+     *                ioctl call data
+     * @return        Returns 0 in success and
+     *                -1 with appropriate  errno if an error occurred.
+     */
+    virtual int ioctlLogSense(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to ReadErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseReadErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to WriteErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseWriteErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to NonMediumErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseNonMediumErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to VolumeStatisticsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseVolumeStatisticsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to driveWriteErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseDriveWriteErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to ReadForwardErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseDriveReadForwardErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to ReadBackwardErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseDriveReadBackwardErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to PerformanceCharacteristicsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSensePerformanceCharacteristicsPage(sg_io_hdr_t * sgio_h);
+
+    virtual int ioctlInquiry(sg_io_hdr_t * sgio_h);
+  };
+
+  /**
+   * Specific st device class for Oracle T10000D.
+   * Used to test vendor specific features.
+   */
+  class stOracleT10000Device : public stDeviceFile {
+  public:
+    /**
+     * This function handles LOG_SENSE CDB and prepares the replay with
+     * compression data.
+     *
+     * @param sgio_h  The pointer to the sg_io_hdr_t structure with
+     *                ioctl call data
+     * @return        Returns 0 in success and
+     *                -1 with appropriate  errno if an error occurred.
+     */
+    virtual int ioctlLogSense(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to ReadErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseReadErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to WriteErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseWriteErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to NonMediumErrorsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseNonMediumErrorsPage(sg_io_hdr_t * sgio_h);
+
+    /**
+     * Simulates the response of a LogSense ioctl from the drive to VendorUniqueDriveStatisticsPage.
+     * @param sgio_h The pointer to the sg_io_hdr_t structure with
+                     ioctl call data.
+     * @return       Returns 0 in success and -1 with appropriate errno if an error has occurred.
+     */
+    virtual int logSenseVendorUniqueDriveStatisticsPage(sg_io_hdr_t * sgio_h);
+
+    virtual int ioctlInquiry(sg_io_hdr_t * sgio_h);
+  };
 } // namespace System
 } // namespace tape
 } // namespace castor
diff --git a/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp b/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp
index 82fc91d6099dfaa2f684b665f4d75bbac78824a6..70995e3427b9afca86167e587b9eeb1d5c8a01d8 100644
--- a/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp
+++ b/tapeserver/castor/tape/tapeserver/system/Wrapper.cpp
@@ -213,18 +213,22 @@ void System::fakeWrapper::referenceFiles() {
   for (std::map<std::string, regularFile>::iterator i = m_regularFiles.begin();
           i != m_regularFiles.end(); i++)
     m_files[i->first] = &m_regularFiles[i->first];
-  for (std::map<std::string, stDeviceFile>::iterator i = m_stFiles.begin();
+  for (std::map<std::string, stDeviceFile *>::iterator i = m_stFiles.begin();
           i != m_stFiles.end(); i++)
-    m_files[i->first] = &m_stFiles[i->first]; 
+    m_files[i->first] = m_stFiles[i->first]; 
 }
 /**
- * Destructor: delete leftover drive objects
+ * Destructor: delete leftover drive and device objects
  */
 System::fakeWrapper::~fakeWrapper() {
   for (auto d=m_pathToDrive.begin(); d!=m_pathToDrive.end(); d++) {
     delete d->second;
     d->second = NULL;
   }
+
+  for (std::map<std::string, stDeviceFile *>::iterator i = m_stFiles.begin();
+       i != m_stFiles.end(); i++)
+    delete m_stFiles[i->first];
 }
 
 System::mockWrapper::mockWrapper() {
@@ -278,6 +282,22 @@ void System::fakeWrapper::setupSLC5() {
    * Setup an tree similar to what we'll find in
    * and SLC5 system with mvhtl library (one media exchanger, 2 drives)
    */
+
+  /**************************************************************************
+   *
+   *  == VFS Setup ==
+   *
+   *    - SLC5
+   *    3.0.0.0 oracle mediumx        sg2
+   *    3.0.1.0 oracle tape0          sg0  st0   nst0
+   *    3.0.2.0 oracle tape1          sg1  st1   nst1
+   *    2.0.0.0 ibm mediumx           sg5
+   *    2.0.1.0 ibm tape0             sg3  st2   nst2
+   *    2.0.2.0 ibm tape1             sg4  st3   nst3
+   *
+   *
+   **************************************************************************/
+
   /*
    * First of, the description of all devices in sysfs.
    * In SLC5, sysfs is mounted on /sys/. If other mount point appear in the
@@ -286,9 +306,10 @@ void System::fakeWrapper::setupSLC5() {
    */
   m_directories["/sys/bus/scsi/devices"].push_back(".");
   m_directories["/sys/bus/scsi/devices"].push_back("..");
-  m_directories["/sys/bus/scsi/devices"].push_back("3:0:0:0");
-  m_directories["/sys/bus/scsi/devices"].push_back("3:0:1:0");
-  m_directories["/sys/bus/scsi/devices"].push_back("3:0:2:0");
+  // Oracle
+  m_directories["/sys/bus/scsi/devices"].push_back("3:0:0:0"); // mediumx
+  m_directories["/sys/bus/scsi/devices"].push_back("3:0:1:0"); // tape0
+  m_directories["/sys/bus/scsi/devices"].push_back("3:0:2:0"); // tape1
   m_realpathes["/sys/bus/scsi/devices/3:0:0:0"]
           = "/sys/devices/pseudo_0/adapter0/host3/target3:0:0/3:0:0:0";
   m_realpathes["/sys/bus/scsi/devices/3:0:1:0"]
@@ -408,8 +429,135 @@ void System::fakeWrapper::setupSLC5() {
   m_stats["/dev/st1"].st_mode = S_IFCHR;
   m_stats["/dev/nst1"].st_rdev = makedev(9, 129);
   m_stats["/dev/nst1"].st_mode = S_IFCHR;
-  m_stFiles["/dev/nst0"];
-  m_stFiles["/dev/nst1"];
+  m_stFiles["/dev/nst0"] = new stOracleT10000Device();
+  m_stFiles["/dev/nst1"] = new stOracleT10000Device();
+
+  // IBM
+  m_directories["/sys/bus/scsi/devices"].push_back("2:0:0:0"); // mediumx
+  m_directories["/sys/bus/scsi/devices"].push_back("2:0:1:0"); // tape0
+  m_directories["/sys/bus/scsi/devices"].push_back("2:0:2:0"); // tape1
+  m_realpathes["/sys/bus/scsi/devices/2:0:0:0"]
+    = "/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0";
+  m_realpathes["/sys/bus/scsi/devices/2:0:1:0"]
+    = "/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0";
+  m_realpathes["/sys/bus/scsi/devices/2:0:2:0"]
+    = "/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0/type"] = "8\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/type"] = "1\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/type"] = "1\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0/vendor"] = "IBM     \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/vendor"] = "IBM     \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/vendor"] = "IBM     \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0/model"] = "03584L22        \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/model"] = "03592E08         \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/model"] = "03592E08         \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0/rev"] = "F030\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/rev"] = "460E\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/rev"] = "460E\n";
+  m_links["/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0/generic"]
+    = "../../../../../../class/scsi_generic/sg5";
+  m_links["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/generic"]
+    = "../../../../../../class/scsi_generic/sg3";
+  m_links["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/generic"]
+    = "../../../../../../class/scsi_generic/sg4";
+  m_stats["/dev/sg3"].st_rdev = makedev(21, 3);
+  m_stats["/dev/sg3"].st_mode = S_IFCHR;
+  m_stats["/dev/sg4"].st_rdev = makedev(21, 4);
+  m_stats["/dev/sg4"].st_mode = S_IFCHR;
+  m_stats["/dev/sg5"].st_rdev = makedev(21, 5);
+  m_stats["/dev/sg5"].st_mode = S_IFCHR;
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:0/2:0:0:0/generic/dev"] = "21:5\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/generic/dev"] = "21:3\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/generic/dev"] = "21:4\n";
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back(".");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("..");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("bus");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("delete");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("device_blocked");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("driver");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("generic");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("iocounterbits");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("iodone_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("ioerr_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("iorequest_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("model");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("power");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("queue_depth");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("queue_type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("rescan");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("rev");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_device:2:0:1:0");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_generic:sg3");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_level");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:nst2");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:nst2a");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:nst2l");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:nst2m");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:st2");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:st2a");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:st2l");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("scsi_tape:st2m");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("state");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("subsystem");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("tape");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("timeout");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("uevent");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0"].push_back("vendor");
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/scsi_tape:st2/dev"] =
+    "9:2\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:1/2:0:1:0/scsi_tape:nst2/dev"] =
+    "9:130\n";
+  m_stats["/dev/st2"].st_rdev = makedev(9, 2);
+  m_stats["/dev/st2"].st_mode = S_IFCHR;
+  m_stats["/dev/nst2"].st_rdev = makedev(9, 130);
+  m_stats["/dev/nst2"].st_mode = S_IFCHR;
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back(".");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("..");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("bus");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("delete");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("device_blocked");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("driver");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("generic");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("iocounterbits");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("iodone_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("ioerr_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("iorequest_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("model");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("power");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("queue_depth");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("queue_type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("rescan");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("rev");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_device:2:0:2:0");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_generic:sg4");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_level");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:nst3");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:nst3a");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:nst3l");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:nst3m");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:st3");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:st3a");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:st3l");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("scsi_tape:st3m");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("state");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("subsystem");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("tape");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("timeout");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("uevent");
+  m_directories["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0"].push_back("vendor");
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/scsi_tape:st3/dev"] =
+    "9:3\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host2/target2:0:2/2:0:2:0/scsi_tape:nst3/dev"] =
+    "9:131\n";
+  m_stats["/dev/st3"].st_rdev = makedev(9, 3);
+  m_stats["/dev/st3"].st_mode = S_IFCHR;
+  m_stats["/dev/nst3"].st_rdev = makedev(9, 131);
+  m_stats["/dev/nst3"].st_mode = S_IFCHR;
+  m_stFiles["/dev/nst2"] = new stIBM3592DeviceFile();
+  m_stFiles["/dev/nst3"] = new stIBM3592DeviceFile();
+
   referenceFiles();
 }
 
@@ -424,9 +572,25 @@ void System::fakeWrapper::setupSLC6() {
    * In SLC6, sysfs is mounted on /sys/. If other mount point appear in the
    * future, we'll have to provide /proc/mounts (and use it).
    */
+  /**************************************************************************
+   *
+   *  == VFS Setup ==
+   *
+   *    - SLC6
+   *    0.0.0.0 hdd                   sg0
+   *    6.0.0.0 oracle mediumx        sg3
+   *    6.0.1.0 oracle tape0          sg1  st0   nst0
+   *    6.0.2.0 oracle tape1          sg2  st1   nst1
+   *    5.0.0.0 ibm mediumx           sg6
+   *    5.0.1.0 ibm tape0             sg4  st2   nst2
+   *    5.0.2.0 ibm tape1             sg5  st3   nst3
+   *
+   *
+   **************************************************************************/
   m_directories["/sys/bus/scsi/devices"].push_back(".");
   m_directories["/sys/bus/scsi/devices"].push_back("..");
   m_directories["/sys/bus/scsi/devices"].push_back("0:0:0:0"); /* disk */
+  // Oracle - host 6
   m_directories["/sys/bus/scsi/devices"].push_back("6:0:0:0"); /* mediumx */
   m_directories["/sys/bus/scsi/devices"].push_back("6:0:1:0"); /* tape */
   m_directories["/sys/bus/scsi/devices"].push_back("6:0:2:0"); /* tape */
@@ -462,7 +626,7 @@ void System::fakeWrapper::setupSLC6() {
   m_realpathes["/sys/bus/scsi/devices/host4"]
           = "/sys/devices/pci0000:00/0000:00:1f.2/host4";
   m_realpathes["/sys/bus/scsi/devices/host5"]
-          = "/sys/devices/pci0000:00/0000:00:1f.2/host5";
+          = "/sys/devices/pseudo_0/adapter0/host5";
   m_realpathes["/sys/bus/scsi/devices/host6"]
           = "/sys/devices/pseudo_0/adapter0/host6";
   m_realpathes["/sys/bus/scsi/devices/target0:0:0"]
@@ -620,8 +784,170 @@ void System::fakeWrapper::setupSLC6() {
   m_stats["/dev/nst1"].st_rdev = makedev(9, 129);
   m_stats["/dev/nst1"].st_mode = S_IFCHR;
 
-  m_stFiles["/dev/nst0"];
-  m_stFiles["/dev/nst1"];
+  m_stFiles["/dev/nst0"] = new stOracleT10000Device();
+  m_stFiles["/dev/nst1"]= new stOracleT10000Device();
+
+  // IBM - host 5
+  m_directories["/sys/bus/scsi/devices"].push_back("5:0:0:0"); /* mediumx */
+  m_directories["/sys/bus/scsi/devices"].push_back("5:0:1:0"); /* tape */
+  m_directories["/sys/bus/scsi/devices"].push_back("5:0:2:0"); /* tape */
+
+  m_directories["/sys/bus/scsi/devices"].push_back("target5:0:0");
+  m_directories["/sys/bus/scsi/devices"].push_back("target5:0:1");
+  m_directories["/sys/bus/scsi/devices"].push_back("target5:0:2");
+
+  m_realpathes["/sys/bus/scsi/devices/5:0:0:0"]
+    = "/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0";
+  m_realpathes["/sys/bus/scsi/devices/5:0:1:0"]
+    = "/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0";
+  m_realpathes["/sys/bus/scsi/devices/5:0:2:0"]
+    = "/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0";
+
+  m_realpathes["/sys/bus/scsi/devices/target5:0:0"]
+    = "/sys/devices/pseudo_0/adapter0/host5/target5:0:0";
+  m_realpathes["/sys/bus/scsi/devices/target5:0:1"]
+    = "/sys/devices/pseudo_0/adapter0/host5/target5:0:1";
+  m_realpathes["/sys/bus/scsi/devices/target5:0:2"]
+    = "/sys/devices/pseudo_0/adapter0/host5/target5:0:2";
+
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0/type"] = "8\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/type"] = "1\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/type"] = "1\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0/vendor"] = "IBM     \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/vendor"] = "IBM     \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/vendor"] = "IBM     \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0/model"] = "03584L22        \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/model"] = "03592E08         \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/model"] = "03592E08         \n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0/rev"] = "F030\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/rev"] = "460E\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/rev"] = "460E\n";
+
+  m_links["/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0/generic"]
+    = "scsi_generic/sg6";
+  m_links["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/generic"]
+    = "scsi_generic/sg4";
+  m_links["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/generic"]
+    = "scsi_generic/sg5";
+
+  m_stats["/dev/sg4"].st_rdev = makedev(21, 4);
+  m_stats["/dev/sg4"].st_mode = S_IFCHR;
+  m_stats["/dev/sg5"].st_rdev = makedev(21, 5);
+  m_stats["/dev/sg5"].st_mode = S_IFCHR;
+  m_stats["/dev/sg6"].st_rdev = makedev(21, 6);
+  m_stats["/dev/sg6"].st_mode = S_IFCHR;
+
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:0/5:0:0:0/generic/dev"]  = "21:6\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/generic/dev"] = "21:4\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/generic/dev"] = "21:5\n";
+
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back(".");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("..");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("bsg");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("delete");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("device_blocked");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("dh_state");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("driver");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("evt_media_change");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("generic");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("iocounterbits");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("iodone_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("ioerr_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("iorequest_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("modalias");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("model");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("power");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("queue_depth");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("queue_ramp_up_period");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("queue_type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("rescan");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("rev");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("scsi_device");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("scsi_generic");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("scsi_level");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("scsi_tape");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("state");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("subsystem");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("tape");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("timeout");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("uevent");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0"].push_back("vendor");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back(".");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("..");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("nst2"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("nst2a"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("nst2l"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("nst2m"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("st2"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("st2a"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("st2l"); // not really sure
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape"].push_back("st2m"); // not really sure
+
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape/st2/dev"] =
+    "9:2\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:1/5:0:1:0/scsi_tape/nst2/dev"] =
+    "9:130\n";
+  m_stats["/dev/st2"].st_rdev = makedev(9, 2);
+  m_stats["/dev/st2"].st_mode = S_IFCHR;
+  m_stats["/dev/nst2"].st_rdev = makedev(9, 130);
+  m_stats["/dev/nst2"].st_mode = S_IFCHR;
+
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back(".");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("..");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("bsg");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("delete");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("device_blocked");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("dh_state");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("driver");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("evt_media_change");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("generic");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("iocounterbits");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("iodone_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("ioerr_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("iorequest_cnt");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("modalias");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("model");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("power");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("queue_depth");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("queue_ramp_up_period");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("queue_type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("rescan");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("rev");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("scsi_device");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("scsi_generic");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("scsi_level");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("scsi_tape");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("state");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("subsystem");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("tape");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("timeout");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("type");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("uevent");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0"].push_back("vendor");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back(".");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("..");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("nst3");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("nst3a");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("nst3l");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("nst3m");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("st3");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("st3a");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("st3l");
+  m_directories["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape"].push_back("st3m");
+
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape/st3/dev"] =
+    "9:3\n";
+  m_regularFiles["/sys/devices/pseudo_0/adapter0/host5/target5:0:2/5:0:2:0/scsi_tape/nst3/dev"] =
+    "9:131\n";
+  m_stats["/dev/st3"].st_rdev = makedev(9, 3);
+  m_stats["/dev/st3"].st_mode = S_IFCHR;
+  m_stats["/dev/nst3"].st_rdev = makedev(9, 131);
+  m_stats["/dev/nst3"].st_mode = S_IFCHR;
+
+  m_stFiles["/dev/nst2"] = new stIBM3592DeviceFile();
+  m_stFiles["/dev/nst3"] = new stIBM3592DeviceFile();
+
   referenceFiles();
 }
 
diff --git a/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp b/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp
index 326579a215e20050ce6062d946db629eba3f3814..5fe8c41f873eaa22c00829e10e754a8af0dab656 100644
--- a/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp
+++ b/tapeserver/castor/tape/tapeserver/system/Wrapper.hpp
@@ -144,7 +144,7 @@ namespace System {
     std::map<std::string, vfsFile *> m_files;
     std::map<std::string, struct stat> m_stats;
     std::map<std::string, regularFile> m_regularFiles;
-    std::map<std::string, stDeviceFile> m_stFiles;
+    std::map<std::string, stDeviceFile *> m_stFiles;
     std::map<std::string, castor::tape::tapeserver::drive::DriveInterface *> m_pathToDrive;
     void setupSLC5();
     void setupSLC6();