diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
index fac9acb12b9c11cee2c41bbedd64358ce5d823a6..0da6ca6dbb42233e1d271a11c6d1da8cab210776 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
@@ -334,6 +334,39 @@ drive::positionInfo drive::DriveGeneric::getPositionInfo()
   return posInfo;
 }
 
+/**
+ * Return physical position of the drive.
+ *
+ * @return physicalPositionInfo class. This contains the wrap and linear position (LPOS).
+ */
+drive::physicalPositionInfo drive::DriveGeneric::getPhysicalPositionInfo()
+{
+  SCSI::Structures::requestSenseCDB_t cdb;
+  SCSI::Structures::requestSenseData_t requestSenseData;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  SCSI::Structures::LinuxSGIO_t sgh;
+
+  // The full Request Sense data record is 96 bytes. However, we are only interested in
+  // the PHYSICAL WRAP and LPOS fields (bytes 29-33) so we can discard the rest.
+  cdb.allocationLength = 34;
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&requestSenseData);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  // Manage both system error and SCSI errors
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveGeneric::getPhysicalPositionInfo");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in getPhysicalPositionInfo:");
+
+  physicalPositionInfo posInfo;
+  posInfo.wrap = requestSenseData.physicalWrap;
+  posInfo.lpos = SCSI::Structures::toU32(requestSenseData.relativeLPOSValue);
+  return posInfo;
+}
+
 /**
  * Get tape alert information from the drive. There is a quite long list of possible tape alerts.
  * They are described in SSC-4, section 4.2.20: TapeAlert application client interface.
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
index dba963280f5e5766233464862648f6da9f118ce2..f1431d23462aa303e08dff1c58bed149eed8529d 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
@@ -132,7 +132,14 @@ namespace drive {
      * on the dirty data still in the write buffer.
      */
     virtual positionInfo getPositionInfo() ;
-    
+
+    /**
+     * Return physical position of the drive.
+     *
+     * @return physicalPositionInfo class. This contains the wrap and linear position (LPOS).
+     */
+    virtual physicalPositionInfo getPhysicalPositionInfo();
+
     /**
      * Get tape alert information from the drive. There is a quite long list of possible tape alerts.
      * They are described in SSC-4, section 4.2.20: TapeAlert application client interface
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp
index 3065307422161f70e1e49e751bab32500c559a70..9dfbdd7ac6075e7b35cc1cf083c287068c9d6c7b 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp
@@ -111,12 +111,12 @@ namespace drive {
     uint32_t lpos;
     /**
      * FORWARD means the current direction is away from the
-     * physical beginning of tape. REVERSE means the current
+     * physical beginning of tape. BACKWARD means the current
      * direction is towards the physical beginning of tape.
      */
-    enum Direction_t { FORWARD, REVERSE };
+    enum Direction_t { FORWARD, BACKWARD };
     Direction_t direction() {
-      return wrap & 1 ? REVERSE : FORWARD;
+      return wrap & 1 ? BACKWARD : FORWARD;
     }
   };
 
@@ -212,6 +212,7 @@ namespace drive {
     virtual std::string getSerialNumber()  = 0;
     virtual void positionToLogicalObject(uint32_t blockId)  = 0;
     virtual positionInfo getPositionInfo()  = 0;
+    virtual physicalPositionInfo getPhysicalPositionInfo() = 0;
     virtual std::vector<uint16_t> getTapeAlertCodes() = 0;
     virtual std::vector<std::string> getTapeAlerts(const std::vector<uint16_t>&) = 0;
     virtual std::vector<std::string> getTapeAlertsCompact (const std::vector<uint16_t>&) = 0;
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp
index a5eea9d290de33831daccc75bce2c68a4c2130cc..cec6b287111811ac7b77aaefc961890a6b403d53 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveTest.cpp
@@ -113,7 +113,8 @@ TEST(castor_tape_drive_Drive, getPositionInfoAndPositionToLogicalObject) {
       std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drive (
         castor::tape::tapeserver::drive::createDrive(*i, sysWrapper));
       castor::tape::tapeserver::drive::positionInfo posInfo;
-      
+      castor::tape::tapeserver::drive::physicalPositionInfo physicalPosInfo;
+
       EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1);      
       posInfo = drive->getPositionInfo();
 
@@ -121,7 +122,13 @@ TEST(castor_tape_drive_Drive, getPositionInfoAndPositionToLogicalObject) {
       ASSERT_EQ(0x12EFCDABU,posInfo.oldestDirtyObject);
       ASSERT_EQ(0xABCDEFU,posInfo.dirtyObjectsCount);
       ASSERT_EQ(0x12EFCDABU,posInfo.dirtyBytesCount);
-      
+
+      EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1);      
+      physicalPosInfo = drive->getPhysicalPositionInfo();
+      ASSERT_EQ(0x0, physicalPosInfo.wrap);
+      ASSERT_EQ(0x0, physicalPosInfo.lpos);
+      ASSERT_EQ(castor::tape::tapeserver::drive::physicalPositionInfo::FORWARD, physicalPosInfo.direction());
+
       EXPECT_CALL(sysWrapper, ioctl(_,_,An<sg_io_hdr_t*>())).Times(1);      
       drive->positionToLogicalObject(0xABCDEF0);
       
diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp
index a93c10a6dd15c92f2c9cd06c09e23940eea85b02..903fa0ddf20c259739170277b7340e399a1a4978 100644
--- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.cpp
@@ -81,6 +81,7 @@ void castor::tape::tapeserver::drive::FakeDrive::positionToLogicalObject(uint32_
   }
   m_currentPosition = blockId;
 }
+
 castor::tape::tapeserver::drive::positionInfo castor::tape::tapeserver::drive::FakeDrive::getPositionInfo()  {
   positionInfo pos;
   pos.currentPosition = m_currentPosition;
@@ -90,6 +91,13 @@ castor::tape::tapeserver::drive::positionInfo castor::tape::tapeserver::drive::F
   return pos;
 }
 
+castor::tape::tapeserver::drive::physicalPositionInfo castor::tape::tapeserver::drive::FakeDrive::getPhysicalPositionInfo() {
+  physicalPositionInfo pos;
+  pos.lpos = 0;
+  pos.wrap = m_currentPosition;
+  return pos;
+}
+
 std::vector<uint16_t> castor::tape::tapeserver::drive::FakeDrive::getTapeAlertCodes() {
   std::vector<uint16_t> empty;
   return empty;
diff --git a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp
index 4313c41795790b9c67ddd06ac1128d71fb9ab1c6..fbadd76acf29f627ab683e0f33aa066b38a7f64a 100644
--- a/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/FakeDrive.hpp
@@ -71,6 +71,7 @@ namespace drive {
     virtual std::string getSerialNumber() ;
     virtual void positionToLogicalObject(uint32_t blockId) ;
     virtual positionInfo getPositionInfo() ;
+    virtual physicalPositionInfo getPhysicalPositionInfo();
     virtual std::vector<uint16_t> getTapeAlertCodes();
     virtual std::vector<std::string> getTapeAlerts(const std::vector<uint16_t>&) ;
     virtual std::vector<std::string> getTapeAlertsCompact(const std::vector<uint16_t>&) ;