Attn: use phal library for get TI info calls

Switch from using pdbg library sbe_mpipl_get_ti_info() to using phal
library getTiInfo() for retrieving pointer to TI info shared memory
region.

Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I916d9195493b2759eed1695b36b9ae156b37be7e
diff --git a/attn/attn_handler.cpp b/attn/attn_handler.cpp
index 566b2f7..718828a 100644
--- a/attn/attn_handler.cpp
+++ b/attn/attn_handler.cpp
@@ -4,6 +4,10 @@
 #include <libpdbg_sbe.h>
 }
 
+#ifdef CONFIG_PHAL_API
+#include <libphal.H>
+#endif
+
 #include <analyzer/analyzer_main.hpp>
 #include <attn/attention.hpp>
 #include <attn/attn_common.hpp>
@@ -47,6 +51,18 @@
 /** @brief Determine if attention is active and not masked */
 bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn);
 
+#ifdef CONFIG_PHAL_API
+/** @brief Handle phal sbe exception */
+void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e,
+                             uint32_t procNum);
+#endif
+
+/** @brief Get static TI info data based on host state */
+void getStaticTiInfo(uint8_t*& tiInfoPtr);
+
+/** @brief Check if TI info data is valid */
+bool tiInfoValid(uint8_t* tiInfo);
+
 /**
  * @brief The main attention handler logic
  *
@@ -260,9 +276,31 @@
 
     bool tiInfoStatic = false; // assume TI info was provided (not created)
 
-    if (attnProc != nullptr)
+    // need proc target to get dynamic TI info
+    if (nullptr != attnProc)
     {
-        // The processor PIB target is required for get TI info chipop
+#ifdef CONFIG_PHAL_API
+        trace<level::INFO>("using libphal to get TI info");
+
+        // phal library uses proc target for get ti info
+        if (PDBG_TARGET_ENABLED == pdbg_target_probe(attnProc))
+        {
+            try
+            {
+                // get dynamic TI info
+                openpower::phal::sbe::getTiInfo(attnProc, &tiInfo, &tiInfoLen);
+            }
+            catch (openpower::phal::exception::SbeError& e)
+            {
+                // library threw an exception
+                uint32_t procNum = pdbg_target_index(attnProc);
+                phalSbeExceptionHandler(e, procNum);
+            }
+        }
+#else
+        trace<level::INFO>("using libpdbg to get TI info");
+
+        // pdbg library uses pib target for get ti info
         char path[16];
         sprintf(path, "/proc%d/pib", pdbg_target_index(attnProc));
         pdbg_target* tiInfoTarget = pdbg_target_from_path(nullptr, path);
@@ -272,99 +310,30 @@
             if (PDBG_TARGET_ENABLED == pdbg_target_probe(tiInfoTarget))
             {
                 sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen);
-
-                // If TI info not available use default based on host state
-                if (nullptr == tiInfo)
-                {
-                    trace<level::INFO>("TI info data ptr is invalid");
-
-                    util::dbus::HostRunningState runningState =
-                        util::dbus::hostRunningState();
-
-                    std::string stateString = "host state unknown";
-
-                    if ((util::dbus::HostRunningState::Started ==
-                         runningState) ||
-                        (util::dbus::HostRunningState::Unknown == runningState))
-                    {
-                        if (util::dbus::HostRunningState::Started ==
-                            runningState)
-                        {
-                            stateString = "host started";
-                        }
-                        tiInfo = (uint8_t*)defaultPhypTiInfo;
-                    }
-                    else
-                    {
-                        stateString = "host not started";
-                        tiInfo      = (uint8_t*)defaultHbTiInfo;
-                    }
-
-                    // trace host state
-                    trace<level::INFO>(stateString.c_str());
-
-                    tiInfoStatic = true; // using our TI info
-                }
             }
         }
+#endif
     }
 
-    bool tiInfoValid = false; // TI area data not valid or not available
-
-    // If TI area exists and is marked valid we can assume TI occurred
-    if ((nullptr != tiInfo) && (0 != tiInfo[0]))
+    // dynamic TI info is not available
+    if (nullptr == tiInfo)
     {
-        TiDataArea* tiDataArea = (TiDataArea*)tiInfo;
-
-        std::stringstream ss; // string stream object for tracing
-        std::string strobj;   // string object for tracing
-
-        // trace a few known TI data area values
-        ss.str(std::string()); // empty the stream
-        ss.clear();            // clear the stream
-        ss << "TI data command = 0x" << std::setw(2) << std::setfill('0')
-           << std::hex << (int)tiDataArea->command;
-        strobj = ss.str();
-        trace<level::INFO>(strobj.c_str());
-
-        // Another check for valid TI Info since it has been seen that
-        // tiInfo[0] != 0 but TI info is not valid
-        if (0xa1 == tiDataArea->command)
-        {
-            tiInfoValid = true;
-
-            // trace some more data since TI info appears valid
-            ss.str(std::string()); // empty the stream
-            ss.clear();            // clear the stream
-            ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0')
-               << std::hex << (int)tiDataArea->hbTerminateType;
-            strobj = ss.str();
-            trace<level::INFO>(strobj.c_str());
-
-            ss.str(std::string()); // empty the stream
-            ss.clear();            // clear the stream
-            ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0')
-               << std::hex << (int)tiDataArea->srcFormat;
-            strobj = ss.str();
-            trace<level::INFO>(strobj.c_str());
-
-            ss.str(std::string()); // empty the stream
-            ss.clear();            // clear the stream
-            ss << "TI data source = 0x" << std::setw(2) << std::setfill('0')
-               << std::hex << (int)tiDataArea->source;
-            strobj = ss.str();
-            trace<level::INFO>(strobj.c_str());
-
-            if (true == (i_attention->getConfig()->getFlag(enTerminate)))
-            {
-                // Call TI special attention handler
-                rc = tiHandler(tiDataArea);
-            }
-        }
+        trace<level::INFO>("TI info data ptr is invalid");
+        getStaticTiInfo(tiInfo);
+        tiInfoStatic = true;
     }
 
-    // TI area is available but was not valid data
-    if (false == tiInfoValid)
+    // check TI info for validity and handle
+    if (true == tiInfoValid(tiInfo))
+    {
+        // TI info is valid handle TI if support enabled
+        if (true == (i_attention->getConfig()->getFlag(enTerminate)))
+        {
+            // Call TI special attention handler
+            rc = tiHandler((TiDataArea*)tiInfo);
+        }
+    }
+    else
     {
         trace<level::INFO>("TI info NOT valid");
 
@@ -375,10 +344,10 @@
             if (true == (i_attention->getConfig()->getFlag(enTerminate)))
             {
                 // Call TI special attention handler
-                rc = tiHandler(nullptr);
+                rc = tiHandler((TiDataArea*)tiInfo);
             }
         }
-        // breakpoint is default special attention when TI info NOT valid
+        // configured to handle breakpoint as default special attention
         else
         {
             // breakpoint handling may be disabled
@@ -390,12 +359,17 @@
         }
     }
 
-    // release TI data buffer
-    if ((nullptr != tiInfo) && (false == tiInfoStatic))
+    // release TI data buffer if not ours
+    if (false == tiInfoStatic)
     {
-        free(tiInfo);
+        // sanity check
+        if (nullptr != tiInfo)
+        {
+            free(tiInfo);
+        }
     }
 
+    // trace non-successful exit condition
     if (RC_SUCCESS != rc)
     {
         trace<level::INFO>("Special attn not handled");
@@ -463,4 +437,117 @@
 
     return rc;
 }
+
+#ifdef CONFIG_PHAL_API
+/**
+ * @brief Handle phal sbe exception
+ *
+ * @param[in] e - exception object
+ * @param[in] procNum - processor number associated with sbe exception
+ */
+void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e,
+                             uint32_t procNum)
+{
+    // trace exception details
+    std::string traceMsg = std::string(e.what());
+    trace<level::ERROR>(traceMsg.c_str());
+
+    // Handle SBE chipop timeout error
+    if (e.errType() == openpower::phal::exception::SBE_CHIPOP_NOT_ALLOWED)
+    {
+        eventPhalSbeChipop(procNum);
+    }
+}
+#endif
+
+/**
+ * @brief Get static TI info data based on host state
+ *
+ * @param[out] tiInfo - pointer to static TI info data
+ */
+void getStaticTiInfo(uint8_t*& tiInfo)
+{
+    util::dbus::HostRunningState runningState = util::dbus::hostRunningState();
+
+    // assume host state is unknown
+    std::string stateString = "host state unknown";
+
+    if ((util::dbus::HostRunningState::Started == runningState) ||
+        (util::dbus::HostRunningState::Unknown == runningState))
+    {
+        if (util::dbus::HostRunningState::Started == runningState)
+        {
+            stateString = "host started";
+        }
+        tiInfo = (uint8_t*)defaultPhypTiInfo;
+    }
+    else
+    {
+        stateString = "host not started";
+        tiInfo      = (uint8_t*)defaultHbTiInfo;
+    }
+
+    // trace host state
+    trace<level::INFO>(stateString.c_str());
+}
+
+/**
+ * @brief Check if TI info data is valid
+ *
+ * @param[in] tiInfo - pointer to TI info data
+ * @return true if TI info data is valid, else false
+ */
+bool tiInfoValid(uint8_t* tiInfo)
+{
+    bool tiInfoValid = false; // assume TI info invalid
+
+    // TI info data[0] non-zero indicates TI info valid (usually)
+    if ((nullptr != tiInfo) && (0 != tiInfo[0]))
+    {
+        TiDataArea* tiDataArea = (TiDataArea*)tiInfo;
+
+        std::stringstream ss; // string stream object for tracing
+        std::string strobj;   // string object for tracing
+
+        // trace a few known TI data area values
+        ss.str(std::string()); // empty the stream
+        ss.clear();            // clear the stream
+        ss << "TI data command = 0x" << std::setw(2) << std::setfill('0')
+           << std::hex << (int)tiDataArea->command;
+        strobj = ss.str();
+        trace<level::INFO>(strobj.c_str());
+
+        // Another check for valid TI Info since it has been seen that
+        // tiInfo[0] != 0 but TI info is not valid
+        if (0xa1 == tiDataArea->command)
+        {
+            tiInfoValid = true;
+
+            // trace some more data since TI info appears valid
+            ss.str(std::string()); // empty the stream
+            ss.clear();            // clear the stream
+            ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0')
+               << std::hex << (int)tiDataArea->hbTerminateType;
+            strobj = ss.str();
+            trace<level::INFO>(strobj.c_str());
+
+            ss.str(std::string()); // empty the stream
+            ss.clear();            // clear the stream
+            ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0')
+               << std::hex << (int)tiDataArea->srcFormat;
+            strobj = ss.str();
+            trace<level::INFO>(strobj.c_str());
+
+            ss.str(std::string()); // empty the stream
+            ss.clear();            // clear the stream
+            ss << "TI data source = 0x" << std::setw(2) << std::setfill('0')
+               << std::hex << (int)tiDataArea->source;
+            strobj = ss.str();
+            trace<level::INFO>(strobj.c_str());
+        }
+    }
+
+    return tiInfoValid;
+}
+
 } // namespace attn