Change FSI behavior for 4.10

Latest FSI code changes paths and endianness, so we need to update
Targeting and flip the CFAM data endian when necessary.
Also update the test case to use the new 4.10 path style.

Change-Id: I35cdedf4b9723ee0f8291d0abf4467dbfd99b334
Signed-off-by: Edward A. James <eajames@us.ibm.com>
diff --git a/cfam_access.cpp b/cfam_access.cpp
index 25b811c..83afdc7 100644
--- a/cfam_access.cpp
+++ b/cfam_access.cpp
@@ -55,6 +55,8 @@
         throw std::runtime_error(msg);
     }
 
+    data = target->swapEndian(data);
+
     rc = write(target->getCFAMFD(), &data, cfamRegSize);
     if (rc < 0)
     {
@@ -95,7 +97,7 @@
         throw std::runtime_error(msg);
     }
 
-    return data;
+    return target->swapEndian(data);
 }
 
 
diff --git a/targeting.cpp b/targeting.cpp
index c5118c1..1237025 100644
--- a/targeting.cpp
+++ b/targeting.cpp
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#include <endian.h>
 #include <experimental/filesystem>
 #include <phosphor-logging/log.hpp>
 #include <regex>
@@ -56,17 +58,41 @@
 }
 
 
+static uint32_t noEndianSwap(uint32_t data)
+{
+    return data;
+}
+
+static uint32_t endianSwap(uint32_t data)
+{
+    return htobe32(data);
+}
+
 Targeting::Targeting(const std::string& fsiMasterDev,
                      const std::string& fsiSlaveDir) :
     fsiMasterPath(fsiMasterDev),
     fsiSlaveBasePath(fsiSlaveDir)
 {
+    swap_endian_t swapper = endianSwap;
+    std::regex exp{"fsi1/slave@([0-9]{2}):00", std::regex::extended};
+
+    if (!fs::exists(fsiMasterPath))
+    {
+        std::regex expOld{"hub@00/slave@([0-9]{2}):00", std::regex::extended};
+
+        //Fall back to old (4.7) path
+        exp = expOld;
+        fsiMasterPath = fsiMasterDevPathOld;
+        fsiSlaveBasePath = fsiSlaveBaseDirOld;
+
+        //And don't swap the endianness of CFAM data
+        swapper = noEndianSwap;
+    }
+
     //Always create P0, the FSI master.
-    targets.push_back(std::make_unique<Target>(0, fsiMasterPath));
+    targets.push_back(std::make_unique<Target>(0, fsiMasterPath, swapper));
 
     //Find the the remaining P9s dynamically based on which files show up
-    std::regex exp{"hub@00/slave@([0-9]{2}):00", std::regex::extended};
-
     for (auto& file : fs::directory_iterator(fsiSlaveBasePath))
     {
         std::smatch match;
@@ -83,7 +109,7 @@
 
             path += "/raw";
 
-            targets.push_back(std::make_unique<Target>(pos, path));
+            targets.push_back(std::make_unique<Target>(pos, path, swapper));
         }
     }
 
diff --git a/targeting.hpp b/targeting.hpp
index 8ab8eda..d5b99fd 100644
--- a/targeting.hpp
+++ b/targeting.hpp
@@ -10,9 +10,16 @@
 {
 
 constexpr auto fsiMasterDevPath =
+    "/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/raw";
+constexpr auto fsiMasterDevPathOld =
     "/sys/devices/platform/fsi-master/slave@00:00/raw";
 
-constexpr auto fsiSlaveBaseDir = "/sys/devices/platform/fsi-master/slave@00:00/hub@00/";
+constexpr auto fsiSlaveBaseDir =
+    "/sys/devices/platform/gpio-fsi/fsi0/slave@00:00/00:00:00:0a/";
+constexpr auto fsiSlaveBaseDirOld =
+    "/sys/devices/platform/fsi-master/slave@00:00/hub@00/";
+
+typedef uint32_t (*swap_endian_t)(uint32_t);
 
 /**
  * Represents a specific P9 processor in the system.  Used by
@@ -27,9 +34,11 @@
          *
          * @param[in] - The logical position of the target
          * @param[in] - The sysfs device path
+         * @param[in] - The function pointer for swapping endianness
          */
-        Target(size_t position, const std::string& devPath) :
-            pos(position), cfamPath(devPath)
+        Target(size_t position, const std::string& devPath,
+               const swap_endian_t swapper) :
+            pos(position), cfamPath(devPath), doSwapEndian(swapper)
         {
         }
 
@@ -61,6 +70,16 @@
          */
         int getCFAMFD();
 
+        /**
+         * Returns correct byte-order data. (May or may not swap it depending
+         * on the function received during construction from Targeting and the
+         * host endianness).
+         */
+        inline uint32_t swapEndian(uint32_t data) const
+        {
+            return doSwapEndian(data);
+        }
+
     private:
 
         /**
@@ -77,6 +96,11 @@
          * The file descriptor to use for read/writeCFAMReg
          */
         std::unique_ptr<openpower::util::FileDescriptor> cfamFD;
+
+        /**
+         * The function pointer for swapping endianness
+         */
+        const swap_endian_t doSwapEndian;
 };
 
 
@@ -137,12 +161,12 @@
         /**
          * The path to the fsi-master sysfs device to access
          */
-        const std::string fsiMasterPath;
+        std::string fsiMasterPath;
 
         /**
          * The path to the fsi slave sysfs base directory
          */
-        const std::string fsiSlaveBasePath;
+        std::string fsiSlaveBasePath;
 
         /**
          * A container of Targets in the system
diff --git a/test/utest.cpp b/test/utest.cpp
index 6303335..d085862 100644
--- a/test/utest.cpp
+++ b/test/utest.cpp
@@ -43,7 +43,7 @@
 
             _slaveBaseDir = path;
 
-            _slaveDir = _slaveBaseDir / "hub@00";
+            _slaveDir = _slaveBaseDir / "fsi1";
             fs::create_directory(_slaveDir);
         }