diff options
Diffstat (limited to 'src/sbefw/sbecmdscomaccess.C')
-rw-r--r-- | src/sbefw/sbecmdscomaccess.C | 495 |
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 +} + |