diff options
Diffstat (limited to 'sbe/sbefw/sbeFifoMsgUtils.C')
-rw-r--r-- | sbe/sbefw/sbeFifoMsgUtils.C | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/sbe/sbefw/sbeFifoMsgUtils.C b/sbe/sbefw/sbeFifoMsgUtils.C new file mode 100644 index 00000000..d86208ad --- /dev/null +++ b/sbe/sbefw/sbeFifoMsgUtils.C @@ -0,0 +1,245 @@ +/* + * @file: ppe/sbe/sbefw/sbeFifoMsgUtils.C + * + * @brief This file contains the SBE FIFO Access Common Utility Functions + * + */ + +#include "sbefifo.H" +#include "sbetrace.H" +#include "sbe_sp_intf.H" +#include "sbeFifoMsgUtils.H" +#include "sbeerrorcodes.H" +#include "assert.h" + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeUpFifoDeq_mult (uint32_t &io_len, + uint32_t *o_pData, + const bool i_isEotExpected, + const bool i_flush) +{ + #define SBE_FUNC " sbeUpFifoDeq_mult " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_len = 0; + + // If Caller didn't request flush operation + // and passed a non-zero valid length, we + // would expect a valid buffer + if ((!i_flush) && (io_len > 0)) + { + assert ( NULL != o_pData) + } + + do + { + sbeFifoEntry_t l_data = {0}; + + // Read Double word from the Upstream FIFO; + // The DW data represents the first 32 bits of data word entry + // followed by the status bits. + + // Bit 0-31 : Data + // Bit 32 : Data valid flag + // Bit 33 : EOT flag + // Bit 34-63 : Status (2-31) + // Valid : EOT + // 1 : 0 -> data=message + // 0 : 1 -> data=dummy_data of EOT operation + // 0 : 0 -> data=dummy_data + // 1 : 1 -> Not used + + l_rc = sbeUpFifoDeq ( reinterpret_cast<uint64_t*>(&l_data) ); + + if (l_rc) + { + // Error while dequeueing from upstream FIFO + SBE_ERROR(SBE_FUNC"sbeUpFifoDeq failed," + "l_rc=[0x%08X]", l_rc); + // @TODO RTC via : 132295 + // RC refactoring - reserve 3 bits in SBE RC for PCBPIB + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + SBE_DEBUG(SBE_FUNC"sbeUpFifoDeq, " + "l_data.fifo_data=[0x%08X],", + l_data.fifo_data); + + // If FIFO reset is requested + if(l_data.statusOrReserved.req_upfifo_reset) + { + // @TODO via RTC : 126147 + // Review reset loop flow in here. + // Received a FIFO reset request + l_rc = SBE_FIFO_RESET_RECEIVED; + break; + } + + // if EOT flag is set, clear EOT and + // set the RC accordingly + if (l_data.statusOrReserved.eot_flag) + { + l_rc = sbeUpFifoAckEot(); + if (l_rc) + { + // Error while ack'ing EOT in upstream FIFO + SBE_ERROR(SBE_FUNC"sbeUpFifoAckEot failed," + "l_rc=[0x%08X]", l_rc); + + // Collect FFDC and save off the l_rc + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + // Successfully Ack'ed the EOT in upstream FIFO + if ( ((!i_isEotExpected) || (l_len != io_len)) + && (!i_flush) ) + { + if (l_len < io_len) + { + // Unexpected EOT, got insufficient data + l_rc = SBE_SEC_UNEXPECTED_EOT_INSUFFICIENT_DATA ; + } + else + { + // Unexpected EOT, got excess data + l_rc = SBE_SEC_UNEXPECTED_EOT_EXCESS_DATA ; + } + } + break; + } + + // if Upstream FIFO is empty, + if (l_data.statusOrReserved.fifo_empty) + { + continue; + } + + if ((!i_flush) && (l_len < io_len)) + { + o_pData[l_len] = l_data.fifo_data; + } + + ++l_len; + + } while(i_flush || i_isEotExpected || (l_len < io_len)); + + // Return the length of entries dequeued. + io_len = l_len; + return l_rc; + + #undef SBE_FUNC +} + +////////////////////////////////////////////////////// +////////////////////////////////////////////////////// +uint32_t sbeDownFifoEnq_mult (uint32_t &io_len, + const uint32_t *i_pData) +{ + #define SBE_FUNC " sbeDownFifoEnq_mult " + uint32_t l_rc = SBE_SEC_OPERATION_SUCCESSFUL; + uint32_t l_len = 0; + + do + { + sbeDownFifoStatusReg_t l_status = {0}; + + // Read the down stream FIFO status + l_rc = sbeDownFifoGetStatus (reinterpret_cast<uint64_t *>(&l_status)); + if (l_rc) + { + // Error while reading downstream FIFO status + SBE_ERROR(SBE_FUNC"sbeDownFifoGetStatus failed, " + "l_rc=[0x%08X]", l_rc); + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + // Check if there was a FIFO reset request from SP + if (l_status.downfifo_status.req_upfifo_reset) + { + // @TODO via RTC : 126147 + // Review reset loop flow in here. + // Received an upstream FIFO reset request + SBE_ERROR(SBE_FUNC"Received reset request"); + l_rc = SBE_FIFO_RESET_RECEIVED; + break; + } + + // Check if downstream FIFO is full + if (l_status.downfifo_status.fifo_full) + { + // Downstream FIFO is full + SBE_INFO(SBE_FUNC"Downstream FIFO is full"); + continue; + } + + // PIB write data format: + // Bit 0 - 31 : Data + // Bit 32 - 63 : Unused + + sbeFifoEntry_t l_data = {0}; + + l_data.fifo_data = *(i_pData+l_len); + + SBE_DEBUG(SBE_FUNC"Downstream fifo data entry[0x%08X]", + l_data.fifo_data); + + // Write the data into the downstream FIFO + l_rc = sbeDownFifoEnq ( *(reinterpret_cast<uint64_t*>(&l_data)) ); + if (l_rc) + { + SBE_ERROR(SBE_FUNC"sbeDownFifoEnq failed, " + "l_rc[0x%08X]", l_rc); + // @TODO RTC via : 132295 + // RC refactoring - reserve 3 bits in SBE RC for PCBPIB + l_rc = SBE_SEC_FIFO_ACCESS_FAILURE; + break; + } + + ++l_len; + + } while(l_len<io_len); + + io_len = l_len; + return l_rc; + #undef SBE_FUNC +} + +//////////////////////////////////////////////////////// +//////////////////////////////////////////////////////// +void sbeBuildMinRespHdr ( uint32_t *io_pBuf, + uint32_t &io_curIndex, + const uint16_t i_primStatus, + const uint16_t i_secStatus, + const uint32_t i_pcbpibStatus, + const uint32_t i_startIndex ) +{ + do + { + if (!io_pBuf) + { + break; + } + + io_pBuf[io_curIndex] = sbeBuildRespHeaderMagicCodeCmdClass(); + io_pBuf[++io_curIndex] = sbeBuildRespHeaderStatusWordLocal( + i_primStatus, i_secStatus); + + // Pcb-Pib error is optional, + // not needed for success case + if ( (i_primStatus != SBE_PRI_OPERATION_SUCCESSFUL) || + (i_pcbpibStatus != SBE_PCB_PIB_ERROR_NONE) ) + { + io_pBuf[++io_curIndex] = i_pcbpibStatus; + } + + // Somehow this compiler isn't allowing the + // index pre-increment for the last array entry + // directly embedded into the assignment + ++io_curIndex; + io_pBuf[io_curIndex] = io_curIndex - i_startIndex + 1; + + } while(false); +} |