summaryrefslogtreecommitdiffstats
path: root/src/sbefw/sbecmdscomaccess.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/sbefw/sbecmdscomaccess.C')
-rw-r--r--src/sbefw/sbecmdscomaccess.C495
1 files changed, 495 insertions, 0 deletions
diff --git a/src/sbefw/sbecmdscomaccess.C b/src/sbefw/sbecmdscomaccess.C
new file mode 100644
index 00000000..e99ce89f
--- /dev/null
+++ b/src/sbefw/sbecmdscomaccess.C
@@ -0,0 +1,495 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/sbefw/sbecmdscomaccess.C $ */
+/* */
+/* OpenPOWER sbe Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+/*
+ * @file: ppe/sbe/sbefw/sbecmdscomaccess.C
+ *
+ * @brief This file contains the SBE SCOM Access chipOps
+ *
+ */
+
+#include "sbecmdscomaccess.H"
+#include "sbefifo.H"
+#include "sbe_sp_intf.H"
+#include "sbetrace.H"
+#include "sbescom.H"
+#include "sbeutil.H"
+#include "sbeFifoMsgUtils.H"
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbeGetScom (uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeGetScom "
+ SBE_ENTER(SBE_FUNC);
+
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ sbeGetScomReqMsg_t l_getScomReqMsg;
+
+ do
+ {
+ uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status;
+ uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ;
+
+ // Will attempt to dequeue two entries for
+ // the scom addresses plus the expected
+ // EOT entry at the end
+
+ uint32_t l_len2dequeue = sizeof(l_getScomReqMsg)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_getScomReqMsg);
+
+ // If FIFO access failure
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Let command processor routine to handle the RC.
+ break;
+ }
+
+ uint32_t l_sbeDownFifoRespBuf[6] = {0};
+ uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE;
+ uint32_t l_len2enqueue = 0;
+ uint32_t l_index = 0;
+
+ uint64_t l_addr = ( (uint64_t)l_getScomReqMsg.hiAddr << 32) |
+ l_getScomReqMsg.lowAddr;
+ uint64_t l_scomData = 0;
+ SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]",
+ l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr);
+ l_rc = checkIndirectAndDoScom(true, l_addr,
+ l_scomData, l_pcbpibStatus);
+
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"getscom failed, l_pcbpibStatus[0x%08X], "
+ "scomAddr[0x%08X%08X]", l_pcbpibStatus,
+ l_getScomReqMsg.hiAddr, l_getScomReqMsg.lowAddr);
+ l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ l_secStatus = l_rc;
+ }
+ else // successful scom
+ {
+ SBE_DEBUG(SBE_FUNC"getscom succeeds, l_scomData[0x%016X]",
+ l_scomData);
+
+ l_sbeDownFifoRespBuf[0] = (uint32_t)(l_scomData>>32);
+ l_sbeDownFifoRespBuf[1] = (uint32_t)(l_scomData);
+
+ // Push the data into downstream FIFO
+ l_len2enqueue = 2;
+ l_rc = sbeDownFifoEnq_mult (l_len2enqueue,
+ &l_sbeDownFifoRespBuf[0]);
+ if (l_rc)
+ {
+ // will let command processor routine
+ // handle the failure
+ break;
+ }
+ l_index = 2;
+ } // end successful scom
+
+ // Build the response header packet
+
+ uint32_t l_curIndex = l_index ;
+ sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0],
+ l_curIndex,
+ l_primStatus,
+ l_secStatus,
+ l_pcbpibStatus,
+ l_index);
+
+ // Now enqueue into the downstream FIFO
+ l_len2enqueue = ++l_curIndex - l_index;
+ l_rc = sbeDownFifoEnq_mult (l_len2enqueue,
+ &l_sbeDownFifoRespBuf[l_index]);
+ if (l_rc)
+ {
+ // will let command processor routine
+ // handle the failure
+ break;
+ }
+
+ } while(false);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+/////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbePutScom (uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbePutScom "
+ SBE_ENTER(SBE_FUNC);
+
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ sbePutScomReqMsg_t l_putScomReqMsg;
+
+ do
+ {
+ uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status;
+ uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ;
+
+ // Will attempt to dequeue four entries for
+ // the scom address (two entries) and the
+ // corresponding data (two entries) plus
+ // the expected EOT entry at the end
+
+ uint32_t l_len2dequeue = sizeof(l_putScomReqMsg)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_putScomReqMsg);
+
+ // If FIFO access failure
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Let command processor routine to handle the RC.
+ break;
+ }
+
+ uint64_t l_scomData = 0;
+ uint32_t l_sbeDownFifoRespBuf[4] = {0};
+ uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE;
+ uint32_t l_len2enqueue = 0;
+ // successfully dequeued two entries for
+ // scom address followed by the EOT entry
+
+ // Data entry 0 : Scom Register Address (0..31)
+ // Data entry 1 : Scom Register Address (32..63)
+ // Data entry 2 : Scom Register Data (0..31)
+ // Data entry 3 : Scom Register Data (32..63)
+ // For Direct SCOM, will ignore entry 0
+
+ l_scomData = l_putScomReqMsg.getScomData();
+
+ uint64_t l_addr = ( (uint64_t) l_putScomReqMsg.hiAddr << 32) |
+ l_putScomReqMsg.lowAddr;
+ SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]",
+ l_putScomReqMsg.hiAddr, l_putScomReqMsg.lowAddr);
+ l_rc = checkIndirectAndDoScom(false, l_addr,
+ l_scomData, l_pcbpibStatus);
+
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"putscom failed, l_pcbpibStatus[0x%08X]",
+ l_pcbpibStatus);
+ SBE_ERROR(SBE_FUNC"putscom failure data, "
+ "scomAddr[0x%08X%08X], "
+ "scomData[0x%08X%08X]",
+ l_putScomReqMsg.hiAddr,
+ l_putScomReqMsg.lowAddr,
+ SBE::higher32BWord(l_scomData),
+ SBE::lower32BWord(l_scomData));
+ l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ l_secStatus = l_rc;
+ }
+
+ // Build the response header packet
+
+ uint32_t l_curIndex = 0;
+ sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0],
+ l_curIndex,
+ l_primStatus,
+ l_secStatus,
+ l_pcbpibStatus);
+
+ // Now enqueue into the downstream FIFO
+ l_len2enqueue = ++l_curIndex;
+ l_rc = sbeDownFifoEnq_mult (l_len2enqueue, &l_sbeDownFifoRespBuf[0]);
+ if (l_rc)
+ {
+ // will let command processor routine
+ // handle the failure
+ break;
+ }
+
+ } while(false);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+
+//////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbeModifyScom (uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeModifyScom "
+ SBE_ENTER(SBE_FUNC);
+
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+
+ sbeModifyScomReqMsg_t l_modifyScomMsg;
+
+ do
+ {
+ uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status;
+ uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ;
+
+ // Will attempt to dequeue the following entries:
+ // Entry 1 : Operation Mode
+ // Entry 2 : Scom Register Address (0..31)
+ // Entry 3 : Scom Register Address (32..63)
+ // Entry 4 : Modifying Data (0..31)
+ // Entry 5 : Modifying Data (32..63)
+ // Entry 6 : EOT entry at the end
+
+ uint32_t l_len2dequeue = sizeof(l_modifyScomMsg)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len2dequeue, (uint32_t *)&l_modifyScomMsg);
+
+ // If FIFO access failure
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Let command processor routine to handle the RC.
+ break;
+ }
+
+ uint32_t l_sbeDownFifoRespBuf[4] = {0};
+ uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE;
+ uint32_t l_len2enqueue = 0;
+
+ // Modifying Data
+ uint64_t l_modifyingData = l_modifyScomMsg.getModifyingData();
+
+ SBE_DEBUG(SBE_FUNC"OpMode[0x%02X], modifyingData[0x%016X]",
+ l_modifyScomMsg.opMode,
+ SBE::higher32BWord(l_modifyingData),
+ SBE::lower32BWord(l_modifyingData));
+
+ // The following steps need to be done as part of this command :
+ // 1. Read Register Data (getscom)
+ // 2. 'AND' the Mask with the data read from register
+ // 3. 'OR' the modifying data with the result of step 2
+ // 4. Write the result of step 3 into the register (putscom)
+ do
+ {
+ // Check for a valid OpMode
+ if ( (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_OR) &&
+ (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_AND) &&
+ (l_modifyScomMsg.opMode != SBE_MODIFY_MODE_XOR) )
+ {
+ // Invalid Data passed
+ SBE_ERROR(SBE_FUNC"Invalid OpMode");
+ l_primStatus = SBE_PRI_INVALID_DATA;
+ l_secStatus = SBE_SEC_GENERIC_FAILURE_IN_EXECUTION;
+ break;
+ }
+
+ uint64_t l_addr = ( (uint64_t) l_modifyScomMsg.hiAddr << 32) |
+ l_modifyScomMsg.lowAddr;
+ uint64_t l_scomData = 0;
+ SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X]",
+ l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr);
+ l_rc = checkIndirectAndDoScom(true, l_addr,
+ l_scomData, l_pcbpibStatus);
+
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"getscom failed, l_pcbpibStatus[0x%08X],"
+ " ScomAddress[0x%08X %08X]", l_pcbpibStatus,
+ l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr);
+ l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ l_secStatus = l_rc;
+ break;
+ }
+
+ if (l_modifyScomMsg.opMode == SBE_MODIFY_MODE_OR)
+ {
+ l_modifyingData |= l_scomData;
+ }
+ else if (l_modifyScomMsg.opMode == SBE_MODIFY_MODE_AND)
+ {
+ l_modifyingData &= l_scomData;
+ }
+ else
+ {
+ l_modifyingData ^= l_scomData;
+ }
+
+ // Write the modified data
+ l_rc = checkIndirectAndDoScom(false, l_addr,
+ l_modifyingData, l_pcbpibStatus);
+
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"putscom failed, l_pcbpibStatus[0x%08X],"
+ " ScomAddress[0x%08X%08X]", l_pcbpibStatus,
+ l_modifyScomMsg.hiAddr, l_modifyScomMsg.lowAddr);
+ SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]",
+ SBE::higher32BWord(l_modifyingData),
+ SBE::lower32BWord(l_modifyingData));
+ l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ l_secStatus = l_rc;
+ break;
+ }
+ } while (false);
+
+ // Build the response header packet
+
+ uint32_t l_curIndex = 0;
+ sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0],
+ l_curIndex,
+ l_primStatus,
+ l_secStatus,
+ l_pcbpibStatus);
+
+ // Now enqueue into the downstream FIFO
+ l_len2enqueue = ++l_curIndex;
+ l_rc = sbeDownFifoEnq_mult (l_len2enqueue,
+ (uint32_t *)&l_sbeDownFifoRespBuf);
+ if (l_rc)
+ {
+ // will let command processor routine
+ // handle the failure
+ break;
+ }
+
+ } while(false);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+/////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbePutScomUnderMask (uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbePutScomUnderMask "
+ SBE_ENTER(SBE_FUNC);
+
+ uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL;
+ sbePutScomUnderMaskReqMsg_t l_putScomUmaskMsg;
+
+ do
+ {
+ uint16_t l_primStatus = g_sbeCmdRespHdr.prim_status;
+ uint16_t l_secStatus = g_sbeCmdRespHdr.sec_status ;
+
+ // Will attempt to dequeue the following entries:
+ // Entry 1 : Scom Register Address (0..31)
+ // Entry 2 : Scom Register Address (32..63)
+ // Entry 3 : Modifying Data (0..31)
+ // Entry 4 : Modifying Data (32..63)
+ // Entry 5 : Mask Data (0..31)
+ // Entry 6 : Mask Data (32..63)
+ // Entry 7 : EOT entry at the end
+
+ uint32_t l_len2dequeue = sizeof(l_putScomUmaskMsg)/sizeof(uint32_t);
+ l_rc = sbeUpFifoDeq_mult (l_len2dequeue,
+ (uint32_t *)&l_putScomUmaskMsg);
+
+ // If FIFO access failure
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL)
+ {
+ // Let command processor routine to handle the RC.
+ break;
+ }
+
+ uint32_t l_sbeDownFifoRespBuf[4] = {0};
+ uint32_t l_pcbpibStatus = SBE_PCB_PIB_ERROR_NONE;
+ uint32_t l_len2enqueue = 0;
+
+ SBE_DEBUG(SBE_FUNC"scomAddr[0x%08X%08X],"
+ "modifyingData[0x%08X%08X]",
+ l_putScomUmaskMsg.hiAddr,
+ l_putScomUmaskMsg.lowAddr,
+ l_putScomUmaskMsg.hiInputData,
+ l_putScomUmaskMsg.lowInputData);
+ SBE_INFO(SBE_FUNC"maskData[0x%08X%08X]",
+ l_putScomUmaskMsg.hiMaskData,
+ l_putScomUmaskMsg.lowMaskData);
+
+ // PutScomUnderMask formula:
+ // dest_reg = (dest_reg & ~input_mask) | (input_data & input_mask)
+
+ do
+ {
+ uint64_t l_scomData = 0;
+
+ uint64_t l_addr = ( (uint64_t) l_putScomUmaskMsg.hiAddr << 32) |
+ l_putScomUmaskMsg.lowAddr;
+ l_rc = checkIndirectAndDoScom(true, l_addr,
+ l_scomData, l_pcbpibStatus);
+
+ if (l_rc == SBE_SEC_OPERATION_SUCCESSFUL) // scom success
+ {
+ l_putScomUmaskMsg.getScomData(l_scomData);
+
+ // Write the modified data
+ l_rc = checkIndirectAndDoScom(false, l_addr,
+ l_scomData, l_pcbpibStatus);
+ }
+
+ if (l_rc != SBE_SEC_OPERATION_SUCCESSFUL) // scom failed
+ {
+ SBE_ERROR(SBE_FUNC"scom failed, l_pcbpibStatus[0x%08X], "
+ "ScomAddress[0x%08X%08X]", l_pcbpibStatus,
+ l_putScomUmaskMsg.hiAddr,
+ l_putScomUmaskMsg.lowAddr);
+ SBE_ERROR(SBE_FUNC"modifyingData[0x%08X%08X]"
+ "maskData[0x%08X%08X]",
+ l_putScomUmaskMsg.hiInputData,
+ l_putScomUmaskMsg.lowInputData,
+ l_putScomUmaskMsg.hiMaskData,
+ l_putScomUmaskMsg.lowMaskData);
+
+ l_primStatus = SBE_PRI_GENERIC_EXECUTION_FAILURE;
+ l_secStatus = l_rc;
+ break;
+ }
+ } while (false);
+
+ // Build the response header packet
+ uint32_t l_curIndex = 0;
+ sbeBuildMinRespHdr(&l_sbeDownFifoRespBuf[0],
+ l_curIndex,
+ l_primStatus,
+ l_secStatus,
+ l_pcbpibStatus);
+
+ // Now enqueue into the downstream FIFO
+ l_len2enqueue = ++l_curIndex;
+ l_rc = sbeDownFifoEnq_mult (l_len2enqueue, &l_sbeDownFifoRespBuf[0]);
+ if (l_rc)
+ {
+ // will let command processor routine
+ // handle the failure
+ break;
+ }
+ } while(false);
+
+ SBE_EXIT(SBE_FUNC);
+ return l_rc;
+ #undef SBE_FUNC
+}
+
+/////////////////////////////////////////////////////
+//////////////////////////////////////////////////////
+uint32_t sbeMultiScom (uint8_t *i_pArg)
+{
+ #define SBE_FUNC " sbeMultiScom "
+ return 0;
+ #undef SBE_FUNC
+}
+
OpenPOWER on IntegriCloud