diff options
author | Dzuy Nguyen <dzuy@us.ibm.com> | 2016-10-18 16:12:49 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-11-14 21:23:45 -0500 |
commit | 3d95d418377ac2ede6d9ab217637cd53158736e9 (patch) | |
tree | 91e16626a9c2ad1e309b1e7265a3cbbd3bd9c938 /src | |
parent | e5a6100ab5f1b18e6458f22fe74141d33d6d8f02 (diff) | |
download | talos-hostboot-3d95d418377ac2ede6d9ab217637cd53158736e9.tar.gz talos-hostboot-3d95d418377ac2ede6d9ab217637cd53158736e9.zip |
Add sbe_psu FFDC error handling.
Turn sbe_psudd into singleton.
Add handle FFDCError function
Change-Id: If84bb2bafcca685c8d31c664f7005de056e96c4c
RTC: 144313
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/31468
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Prachi Gupta <pragupta@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/include/usr/sbeio/sbe_psudd.H | 1010 | ||||
-rw-r--r-- | src/include/usr/util/utilbyte.H | 121 | ||||
-rw-r--r-- | src/makefile | 1 | ||||
-rw-r--r-- | src/usr/sbeio/makefile | 2 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_coreStateControl.C | 38 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_psudd.C | 225 | ||||
-rw-r--r-- | src/usr/sbeio/sbe_systemConfig.C | 18 | ||||
-rw-r--r-- | src/usr/sbeio/test/makefile | 33 | ||||
-rw-r--r-- | src/usr/sbeio/test/sbe_ffdctest.H | 221 | ||||
-rw-r--r-- | src/usr/scan/scandd.C | 32 | ||||
-rw-r--r-- | src/usr/scan/scandd.H | 2 |
11 files changed, 1173 insertions, 530 deletions
diff --git a/src/include/usr/sbeio/sbe_psudd.H b/src/include/usr/sbeio/sbe_psudd.H index fbdd51008..eb0869396 100644 --- a/src/include/usr/sbeio/sbe_psudd.H +++ b/src/include/usr/sbeio/sbe_psudd.H @@ -35,489 +35,573 @@ #include <sys/time.h> #include <errl/errlentry.H> +#include <util/singleton.H> namespace SBEIO { - //----------------------------------------------------------------------------- // Interfaces to the SBE PSU device driver to be used by clients // within this component. //----------------------------------------------------------------------------- - /** - * @brief enums for SBE command class - */ - - // BYTE 6 options - enum psuCommandClass - { - SBE_PSU_CLASS_UNKNOWN = 0, - SBE_PSU_CLASS_CORE_STATE = 0xD1, - SBE_PSU_PUT_RING_FROM_IMAGE_CMD = 0xD3, - SBE_PSU_GENERIC_MESSAGE = 0xD7 - }; - - /** - * @brief enums for SBE core state control commands - */ - // BYTE 7 options - enum psuCoreStateControlCommands - { - SBE_CMD_CONTROL_DEADMAN_LOOP = 0x01, - - }; - - /** - * @brief enums for SBEPutRing From Image message commands - */ - // BYTE 7 options - enum putRingCommandFromImageCommands - { - SBE_CMD_CONTROL_PUTRING = 0x01 - }; - - - /** - * @brief enums for SBE generic message commands - */ - //BYTE 7 options - enum psuGenericMessageCommands - { - SBE_CMD_CONTROL_SYSTEM_CONFIG = 0x06 - }; - - /** - * @brief enums for SBE core state control flags - */ - //BYTE 2 & 3, Control Flags - enum psuDeadManControlFlags - { - SBE_DMCONTROL_START = 0x01, - SBE_DMCONTROL_STOP = 0x02, - SBE_DMCONTROL_RESPONSE_REQUIRED = 0x0100, - SBE_DMCONTROL_ACK_REQUIRED = 0x0200, - }; - - /** - * @brief enums for SBE system config control flags - */ - //BYTE 2 & 3, Control Flags - enum psuSystemConfigControlFlags - { - SBE_REQUIRE_RESPONSE = 0x0100, - SBE_REQUIRE_ACK = 0x0200, - }; - - /** - * @brief non reserved word enums - * - * Shows which of the request and response msg registers are - * not reserved. Reserved registers do not need to be written - * or read. - * - * This is a 4 bit field: - * 0x1 - Reg 0 is non-reserved (read or write this reg) - * 0x2 - Reg 1 is non-reserved (read or write this reg) - * 0x4 - Reg 2 is non-reserved (read or write this reg) - * 0x8 - Reg 3 is non-reserved (read or write this reg) - */ - enum psuCoreStateControlNonReservedMsgs - { - SBE_DMCONTROL_START_REQ_USED_REGS = 0x03, - SBE_DMCONTROL_START_RSP_USED_REGS = 0x01, - SBE_DMCONTROL_STOP_REQ_USED_REGS = 0x01, - SBE_DMCONTROL_STOP_RSP_USED_REGS = 0x01, - }; - - /** - * @brief non reserved word enums - * - * Shows which of the request and response msg registers are - * not reserved. Reserved registers do not need to be written - * or read. - * - * This is a 4 bit field: - * 0x1 - Reg 0 is non-reserved (read or write this reg) - * 0x2 - Reg 1 is non-reserved (read or write this reg) - * 0x4 - Reg 2 is non-reserved (read or write this reg) - * 0x8 - Reg 3 is non-reserved (read or write this reg) - */ - enum psuSystemConfigNonReservedMsgs - { - SBE_SYSTEM_CONFIG_REQ_USED_REGS = 0x03, - SBE_SYSTEM_CONFIG_RSP_USED_REGS = 0x01, - }; - - /** - * @brief Struct for PSU command message format - * - */ - union psuCommand - { - struct //raw +/** @class SbePsu + * @brief Class for SBE/PSU communication +*/ + +class SbePsu +{ + public: + + /** + * @brief get the instance of this class + * + * @return the (one and only) instance of SbePsu + */ + + static SbePsu & getTheInstance(); + + /** + * @brief enums for SBE command class + */ + + // BYTE 6 options + enum psuCommandClass + { + SBE_PSU_CLASS_UNKNOWN = 0, + SBE_PSU_CLASS_CORE_STATE = 0xD1, + SBE_PSU_PUT_RING_FROM_IMAGE_CMD = 0xD3, + SBE_PSU_GENERIC_MESSAGE = 0xD7 + }; + + /** + * @brief enums for SBE core state control commands + */ + + // BYTE 7 options + enum psuCoreStateControlCommands + { + SBE_CMD_CONTROL_DEADMAN_LOOP = 0x01, + + }; + + /** + * @brief enums for SBEPutRing From Image message commands + */ + // BYTE 7 options + enum putRingCommandFromImageCommands { - uint64_t mbxReg0; - uint64_t mbxReg1; - uint64_t mbxReg2; - uint64_t mbxReg3; - } PACKED; - struct //common and direct fields + SBE_CMD_CONTROL_PUTRING = 0x01 + }; + + /** + * @brief enums for SBE generic message commands + */ + //BYTE 7 options + enum psuGenericMessageCommands { - // mbxReg 0 - uint16_t reserved; - uint16_t controlFlags; - uint16_t seqID; - uint8_t commandClass; - uint8_t command; - // mbxReg 1 - uint32_t dataWord2; - uint32_t dataWord3; - // mbxReg 2 - uint32_t dataWord4; - uint32_t dataWord5; - // mbxReg 3 - uint32_t dataWord6; - uint32_t dataWord7; - } PACKED; - struct //indirect + SBE_CMD_CONTROL_SYSTEM_CONFIG = 0x06 + }; + + /** + * @brief enums for SBE core state control flags + */ + //BYTE 2 & 3, Control Flags + enum psuDeadManControlFlags { - // mbxReg 0 - uint16_t indirect_reserved; - uint16_t indirect_controlFlags; - uint16_t indirect_seqID; - uint8_t indirect_commandClass; - uint8_t indirect_command; - // mbxReg 1 - uint32_t indirect_dataWord2; - uint32_t indirect_dataWord3; - // mbxReg 2 - uint32_t indirect_dataWord4; - uint32_t indirect_dataWord5; - // mbxReg 3 - uint64_t indirect_address; // Data address (Mainstore/PBA) - } PACKED; - struct //controlDeadmanLoop + SBE_DMCONTROL_START = 0x01, + SBE_DMCONTROL_STOP = 0x02, + SBE_DMCONTROL_RESPONSE_REQUIRED = 0x0100, + SBE_DMCONTROL_ACK_REQUIRED = 0x0200, + }; + + /** + * @brief enums for SBE system config control flags + */ + //BYTE 2 & 3, Control Flags + enum psuSystemConfigControlFlags { - uint16_t cd1_ControlDeadmanLoop_Reserved; - uint16_t cd1_ControlDeadmanLoop_ControlFlags; - uint16_t cd1_ControlDeadmanLoop_SeqID; - uint8_t cd1_ControlDeadmanLoop_CommandClass; - uint8_t cd1_ControlDeadmanLoop_Command; - uint64_t cd1_ControlDeadmanLoop_WaitTime ; - uint64_t cd1_ControlDeadmanLoop_MbxReg2reserved; - uint64_t cd1_ControlDeadmanLoop_MbxReg3reserved; - } PACKED; - struct //setSystemConfig + SBE_REQUIRE_RESPONSE = 0x0100, + SBE_REQUIRE_ACK = 0x0200, + }; + + /** + * @brief non reserved word enums + * + * Shows which of the request and response msg registers are + * not reserved. Reserved registers do not need to be written + * or read. + * + * This is a 4 bit field: + * 0x1 - Reg 0 is non-reserved (read or write this reg) + * 0x2 - Reg 1 is non-reserved (read or write this reg) + * 0x4 - Reg 2 is non-reserved (read or write this reg) + * 0x8 - Reg 3 is non-reserved (read or write this reg) + */ + enum psuCoreStateControlNonReservedMsgs { - uint16_t cd2_SetSystemConfig_Reserved; - uint16_t cd2_SetSystemConfig_ControlFlags; - uint16_t cd2_SetSystemConfig_SeqID; - uint8_t cd2_SetSystemConfig_CommandClass; - uint8_t cd2_SetSystemConfig_Command; - uint64_t cd2_SetSystemConfig_SystemFabricIdMap ; - uint64_t cd2_SetSystemConfig_MbxReg2reserved; - uint64_t cd2_SetSystemConfig_MbxReg3reserved; - } PACKED; - - struct //for 'Put Ring from Image' message + SBE_DMCONTROL_START_REQ_USED_REGS = 0x03, + SBE_DMCONTROL_START_RSP_USED_REGS = 0x01, + SBE_DMCONTROL_STOP_REQ_USED_REGS = 0x01, + SBE_DMCONTROL_STOP_RSP_USED_REGS = 0x01, + }; + + /** + * @brief non reserved word enums + * + * Shows which of the request and response msg registers are + * not reserved. Reserved registers do not need to be written + * or read. + * + * This is a 4 bit field: + * 0x1 - Reg 0 is non-reserved (read or write this reg) + * 0x2 - Reg 1 is non-reserved (read or write this reg) + * 0x4 - Reg 2 is non-reserved (read or write this reg) + * 0x8 - Reg 3 is non-reserved (read or write this reg) + */ + enum psuSystemConfigNonReservedMsgs { - uint16_t cd3_PutRing_Reserved; //Mbx Reg 0 - uint16_t cd3_PutRing_ControlFlags; //Mbx Reg 0 - uint16_t cd3_PutRing_SeqID; //Mbx Reg 0 - uint8_t cd3_PutRing_CommandClass; //Mbx Reg 0 - uint8_t cd3_PutRing_Command; //Mbx Reg 0 - uint16_t cd3_PutRing_TargetType; //Mbx Reg 1 - uint8_t cd3_PutRing_Reserved1; //Mbx Reg 1 - uint8_t cd3_PutRing_ChipletID; //Mbx Reg 1 - uint16_t cd3_PutRing_RingID; //Mbx Reg 1 - uint16_t cd3_PutRing_RingMode; //Mbx Reg 1 - uint64_t cd3_PutRing_ReservedMbxReg2; //Mbx Reg 2 - uint64_t cd3_PutRing_ReservedMbxReg3; //Mbx Reg 3 - }PACKED; - - psuCommand(uint16_t i_controlFlags, //Mbx Reg 0 input - uint8_t i_commandClass, //Mbx Reg 0 input - uint8_t i_command) : //Mbx Reg 0 input - - //setting BYTE 0 & 1 Mbx Reg 0 - reserved (0), - //setting BYTE 2 & 3 Mbx Reg 0 - controlFlags(i_controlFlags), - //setting BYTE 4 & 5 Mbx Reg 0 - seqID(0), - //setting BYTE 6 Mbx Reg 0 - commandClass(i_commandClass), - //setting BYTE 7 Mbx Reg 0 - command(i_command), - //setting BYTE 8- Byte 11 - Mbx Reg 1 - dataWord2(0), - //setting BYTE 12- Byte 15 - Mbx Reg 1 - dataWord3(0), - //setting BYTE 16- Byte 19 - Mbx Reg 2 - dataWord4(0), - //setting BYTE 20- Byte 23 - Mbx Reg 2 - dataWord5(0), - //setting BYTE 24- Byte 27 - Mbx Reg 3 - dataWord6(0), - //setting BYTE 28- Byte 31 - Mbx Reg 3 - dataWord7(0) + SBE_SYSTEM_CONFIG_REQ_USED_REGS = 0x03, + SBE_SYSTEM_CONFIG_RSP_USED_REGS = 0x01, + }; + + /** + * @brief Struct for PSU command message format + * + */ + union psuCommand { - } - - }; - - /** - * @brief Struct for PSU response message format - * - */ - union psuResponse - { - struct //raw + struct //raw + { + uint64_t mbxReg0; + uint64_t mbxReg1; + uint64_t mbxReg2; + uint64_t mbxReg3; + } PACKED; + struct //common and direct fields + { + // mbxReg 0 + uint16_t reserved; + uint16_t controlFlags; + uint16_t seqID; + uint8_t commandClass; + uint8_t command; + // mbxReg 1 + uint32_t dataWord2; + uint32_t dataWord3; + // mbxReg 2 + uint32_t dataWord4; + uint32_t dataWord5; + // mbxReg 3 + uint32_t dataWord6; + uint32_t dataWord7; + } PACKED; + struct //indirect + { + // mbxReg 0 + uint16_t indirect_reserved; + uint16_t indirect_controlFlags; + uint16_t indirect_seqID; + uint8_t indirect_commandClass; + uint8_t indirect_command; + // mbxReg 1 + uint32_t indirect_dataWord2; + uint32_t indirect_dataWord3; + // mbxReg 2 + uint32_t indirect_dataWord4; + uint32_t indirect_dataWord5; + // mbxReg 3 + uint64_t indirect_address; // Data address (Mainstore/PBA) + } PACKED; + struct //controlDeadmanLoop + { + uint16_t cd1_ControlDeadmanLoop_Reserved; + uint16_t cd1_ControlDeadmanLoop_ControlFlags; + uint16_t cd1_ControlDeadmanLoop_SeqID; + uint8_t cd1_ControlDeadmanLoop_CommandClass; + uint8_t cd1_ControlDeadmanLoop_Command; + uint64_t cd1_ControlDeadmanLoop_WaitTime ; + uint64_t cd1_ControlDeadmanLoop_MbxReg2reserved; + uint64_t cd1_ControlDeadmanLoop_MbxReg3reserved; + } PACKED; + + struct //setSystemConfig + { + uint16_t cd2_SetSystemConfig_Reserved; + uint16_t cd2_SetSystemConfig_ControlFlags; + uint16_t cd2_SetSystemConfig_SeqID; + uint8_t cd2_SetSystemConfig_CommandClass; + uint8_t cd2_SetSystemConfig_Command; + uint64_t cd2_SetSystemConfig_SystemFabricIdMap ; + uint64_t cd2_SetSystemConfig_MbxReg2reserved; + uint64_t cd2_SetSystemConfig_MbxReg3reserved; + } PACKED; + + struct //for 'Put Ring from Image' message + { + uint16_t cd3_PutRing_Reserved; //Mbx Reg 0 + uint16_t cd3_PutRing_ControlFlags; //Mbx Reg 0 + uint16_t cd3_PutRing_SeqID; //Mbx Reg 0 + uint8_t cd3_PutRing_CommandClass; //Mbx Reg 0 + uint8_t cd3_PutRing_Command; //Mbx Reg 0 + uint16_t cd3_PutRing_TargetType; //Mbx Reg 1 + uint8_t cd3_PutRing_Reserved1; //Mbx Reg 1 + uint8_t cd3_PutRing_ChipletID; //Mbx Reg 1 + uint16_t cd3_PutRing_RingID; //Mbx Reg 1 + uint16_t cd3_PutRing_RingMode; //Mbx Reg 1 + uint64_t cd3_PutRing_ReservedMbxReg2; //Mbx Reg 2 + uint64_t cd3_PutRing_ReservedMbxReg3; //Mbx Reg 3 + } PACKED; + + psuCommand(uint16_t i_controlFlags, //Mbx Reg 0 input + uint8_t i_commandClass, //Mbx Reg 0 input + uint8_t i_command) : //Mbx Reg 0 input + + //setting BYTE 0 & 1 Mbx Reg 0 + reserved (0), + //setting BYTE 2 & 3 Mbx Reg 0 + controlFlags(i_controlFlags), + //setting BYTE 4 & 5 Mbx Reg 0 + seqID(0), + //setting BYTE 6 Mbx Reg 0 + commandClass(i_commandClass), + //setting BYTE 7 Mbx Reg 0 + command(i_command), + //setting BYTE 8- Byte 11 - Mbx Reg 1 + dataWord2(0), + //setting BYTE 12- Byte 15 - Mbx Reg 1 + dataWord3(0), + //setting BYTE 16- Byte 19 - Mbx Reg 2 + dataWord4(0), + //setting BYTE 20- Byte 23 - Mbx Reg 2 + dataWord5(0), + //setting BYTE 24- Byte 27 - Mbx Reg 3 + dataWord6(0), + //setting BYTE 28- Byte 31 - Mbx Reg 3 + dataWord7(0) + { + } + + }; + + /** + * @brief Struct for PSU response message format + * + */ + union psuResponse + { + struct //raw + { + uint64_t mbxReg4; + uint64_t mbxReg5; + uint64_t mbxReg6; + uint64_t mbxReg7; + } PACKED; + struct //common and direct fields + { + // mbxReg 4 + uint16_t primaryStatus; + uint16_t secondaryStatus; + uint16_t seqID; + uint8_t commandClass; + uint8_t command; + // mbxReg 5 + uint32_t respWord0; + uint32_t respWord1; + // mbxReg 6 + uint32_t respWord2; + uint32_t respWord3; + // mbxReg 7 + uint32_t respWord4; + uint32_t respWord5; + } PACKED; + struct // indirect fields + { + // mbxReg 4 + uint16_t indirect_primaryStatus; + uint16_t indirect_secondaryStatus; + uint16_t indirect_seqID; + uint8_t indirect_commandClass; + uint8_t indirect_command; + // mbxReg 5 + uint32_t indirect_respWord0; + uint32_t indirect_respWord1; + // mbxReg 6 + uint32_t indirect_respWord2; + uint32_t indirect_respWord3; + // mbxReg 7 + uint32_t indirect_reserved; + uint32_t indirect_size; //Size in dbl words for Indirect data + } PACKED; + psuResponse() : + primaryStatus (0xffff), //invalid status + secondaryStatus (0xffff), //invalid status + seqID (0xffff), //unlikely seq ID + commandClass (0xff), //invalid command class + command (0xff), //invalid command + respWord0 (0), + respWord1 (0), + respWord2 (0), + respWord3 (0), + respWord4 (0), + respWord5 (0) + { + } + + }; + + /** + * @brief timeout values + * + */ + static const uint64_t MAX_PSU_SHORT_TIMEOUT_NS=100*NS_PER_MSEC; //=100ms + + /** + * @brief enums for primary SBE response + * + */ + enum sbePrimResponse { - uint64_t mbxReg4; - uint64_t mbxReg5; - uint64_t mbxReg6; - uint64_t mbxReg7; - } PACKED; - struct //common and direct fields + SBE_PRI_OPERATION_SUCCESSFUL = 0x00, + SBE_PRI_INVALID_COMMAND = 0x01, + SBE_PRI_INVALID_DATA = 0x02, + SBE_PRI_SEQUENCE_ERROR = 0x03, + SBE_PRI_INTERNAL_ERROR = 0x04, + SBE_PRI_GENERIC_EXECUTION_FAILURE = 0xFE, + }; + + /** + * @brief enums for secondary SBE response + * Discuss on SBE_SEC_INVALID_TARGET_ID_PASSED + * + */ + enum sbeSecondaryResponse { - // mbxReg 4 - uint16_t primaryStatus; - uint16_t secondaryStatus; - uint16_t seqID; - uint8_t commandClass; - uint8_t command; - // mbxReg 5 - uint32_t respWord0; - uint32_t respWord1; - // mbxReg 6 - uint32_t respWord2; - uint32_t respWord3; - // mbxReg 7 - uint32_t respWord4; - uint32_t respWord5; - } PACKED; - struct // indirect fields + SBE_SEC_OPERATION_SUCCESSFUL = 0x00, + SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED = 0x01, + SBE_SEC_COMMAND_NOT_SUPPORTED = 0x02, + SBE_SEC_INVALID_ADDRESS_PASSED = 0x03, + SBE_SEC_INVALID_TARGET_TYPE_PASSED = 0x04, + SBE_SEC_INVALID_TARGET_ID_PASSED = 0x05, + SBE_SEC_SPECIFIED_TARGET_NOT_PRESENT = 0x06, + SBE_SEC_SPECIFIED_TARGET_NOT_FUNCTIONAL = 0x07, + SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE = 0x08, + SBE_SEC_FUNCTIONALITY_NOT_SUPPORTED = 0x09, + SBE_SEC_GENERIC_FAILURE_IN_EXECUTION = 0x0A, + SBE_SEC_BACKLISTED_ACCESS = 0x0B, + SBE_SEC_OS_FAILURE = 0x0C, + SBE_SEC_HOST_MBX_REG_ACCESS_FAILURE = 0x0D, + SBE_SEC_INSUFFICIENT_DATA_PASSED = 0x0E, + SBE_SEC_EXCESS_DATA_PASSED = 0x0F, + SBE_SEC_SBE_BUSY_TO_HANDLE_COMMAND = 0x10, + }; + + enum SBE_TARGET_TYPES { + + SBE_TARGET_TYPE_PROC = 0x00, + SBE_TARGET_TYPE_EX = 0x01, + SBE_TARGET_TYPE_PERV = 0x02, + SBE_TARGET_TYPE_MCS = 0x03, + SBE_TARGET_TYPE_TOTAL , + SBE_TARGET_TYPE_UNKNOWN = 0xFF + }; + + /** + * @Brief perform SBE PSU chip-op + * + * @param[in] i_pPsuRequest Pointer to PSU request commands + * @param[out] o_pPsuResponse Pointer to PSU response + * @param[in] i_timeout Time out for response + * @param[in] i_reqMsgs 4 bit mask telling which regs to write + * @param[in] i_rspMsgs 4 bit mask telling which regs to read + */ + errlHndl_t performPsuChipOp(psuCommand * i_pPsuCommand, + psuResponse * o_pPsuResponse, + const uint64_t i_timeout, + uint8_t i_reqMsgs, + uint8_t i_rspMsgs); + + protected: + + /** + * @Brief Constructor + */ + + SbePsu(); + + /** + * @Brief Destructor + */ + + ~SbePsu(); + + /** + * @brief parse the FFDC package from buffer + * @param[in] io_errl Error Entry object + * @retval: true == success, false == failure + */ + + bool handleFFDCError(ERRORLOG::ErrlEntry * io_errl); + + /** + * @brief populate the iv_ffdcPackageBuffer + * @param[in] i_data FFDC error data + * @param[in] i_len data buffer len to copy + */ + + void writeFFDCBuffer(void * i_data, uint8_t i_len); + + private: + //--------------------------------------------------------------------- + // Local definitions for the device driver + //--------------------------------------------------------------------- + + /** + * @brief Write FFDC package buffer - holds information exchanged + * between SBE and HB + */ + void * iv_ffdcPackageBuffer; + + /** + * @brief Magic byte in FFDC header + */ + const uint16_t ffdcMagicByte = 0xFFDC; + + /** + * @brief each FFDC word is 4 byte long + */ + const uint8_t ffdcWordLen = 4; + + /** + * @brief difference between package length and N words + */ + const uint8_t ffdcPadLen = 6; + + /** + * @brief FFDC package needs to be 2 pages + */ + const uint8_t ffdcPackageSize = 2; + + /** + * @brief byte pad before word data begins + */ + const uint8_t wordPadding = 12; + + /** + * @brief zero out the FFDC package buffer + */ + void initFFDCPackageBuffer(); + + /** + * @brief Write request to PSU + * + * @param[in] i_target Master proc to use for scoms + * @param[in] i_pPsuRequest Pointer to PSU request commands + * @param[in] i_reqMsgs 4 bit mask telling which regs to write + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t writeRequest(TARGETING::Target * i_target, + psuCommand * i_pPsuRequest, + uint8_t i_reqMsgs); + /** + * @brief Read response from PSU + * + * @param[in] i_target Master proc to use for scoms + * @param[in] i_pPsuRequest Pointer to PSU request commands + * @param[out] o_pPsuResponse Pointer to PSU response + * @param[in] i_timeout Time out for response + * @param[in] i_rspMsgs 4 bit mask telling which regs to read + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t readResponse(TARGETING::Target * i_target, + psuCommand * i_pPsuRequest, + psuResponse * o_pPsuResponse, + const uint64_t i_timeout, + uint8_t i_rspMsgs); + /** + * @brief Poll for response ready to be read + * + * @param[in] i_target Master proc to use for scoms + * @param[in] i_timeout Time out for response + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t pollForPsuComplete(TARGETING::Target * i_target, + const uint64_t i_timeout); + /** + * @brief Read Scom wrapper + * + * @param[in] i_target Master proc to use for scoms + * @param[in] i_addr Scom address + * @param[out] o_pData Pointer to returned data + * @param[in] i_trace Trace control to avoid overruning + * trace buffer when polling for + * response ready to be read + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t readScom(TARGETING::Target * i_target, + uint64_t i_addr, + uint64_t * o_pData, + bool i_trace=true); + + /** + * @brief Write Scom wrapper + * + * @param[in] i_target Master proc to use for scoms + * @param[in] i_addr Scom address + * @param[in] i_pData Pointer to data to write + * + * @return errlHndl_t Error log handle on failure. + */ + errlHndl_t writeScom(TARGETING::Target * i_target, + uint64_t i_addr, + uint64_t * i_pData); + + /** + * @brief SBE PSU register addresses + */ + enum psuRegs { - // mbxReg 4 - uint16_t indirect_primaryStatus; - uint16_t indirect_secondaryStatus; - uint16_t indirect_seqID; - uint8_t indirect_commandClass; - uint8_t indirect_command; - // mbxReg 5 - uint32_t indirect_respWord0; - uint32_t indirect_respWord1; - // mbxReg 6 - uint32_t indirect_respWord2; - uint32_t indirect_respWord3; - // mbxReg 7 - uint32_t indirect_reserved; - uint32_t indirect_size; //Size in dbl words for Indirect data - } PACKED; - psuResponse() : - primaryStatus (0xffff), //invalid status - secondaryStatus (0xffff), //invalid status - seqID (0xffff), //unlikely seq ID - commandClass (0xff), //invalid command class - command (0xff), //invalid command - respWord0 (0), - respWord1 (0), - respWord2 (0), - respWord3 (0), - respWord4 (0), - respWord5 (0) + PSU_HOST_SBE_MBOX0_REG = 0x000D0050, + PSU_HOST_SBE_MBOX1_REG = 0x000D0051, + PSU_HOST_SBE_MBOX2_REG = 0x000D0052, + PSU_HOST_SBE_MBOX3_REG = 0x000D0053, + PSU_HOST_SBE_MBOX4_REG = 0x000D0054, + PSU_HOST_SBE_MBOX5_REG = 0x000D0055, + PSU_HOST_SBE_MBOX6_REG = 0x000D0056, + PSU_HOST_SBE_MBOX7_REG = 0x000D0057, + PSU_SBE_DOORBELL_REG_RW = 0x000D0060, + PSU_SBE_DOORBELL_REG_AND = 0x000D0061, + PSU_SBE_DOORBELL_REG_OR = 0x000D0062, + PSU_HOST_DOORBELL_REG_RW = 0x000D0063, + PSU_HOST_DOORBELL_REG_AND = 0x000D0064, + PSU_HOST_DOORBELL_REG_OR = 0x000D0065, + }; + + /** + * @brief SBE PSU door bell register + */ + enum sbeDoorbellReg { - } - - }; - - /** - * @brief timeout values - * - */ - const uint64_t MAX_PSU_SHORT_TIMEOUT_NS = 100*NS_PER_MSEC; //=100ms - const uint64_t MAX_PSU_LONG_TIMEOUT_NS = 30000*NS_PER_MSEC; //=30 seconds - - /** - * @brief enums for primary SBE response - * - */ - enum sbePrimResponse - { - SBE_PRI_OPERATION_SUCCESSFUL = 0x00, - SBE_PRI_INVALID_COMMAND = 0x01, - SBE_PRI_INVALID_DATA = 0x02, - SBE_PRI_SEQUENCE_ERROR = 0x03, - SBE_PRI_INTERNAL_ERROR = 0x04, - SBE_PRI_GENERIC_EXECUTION_FAILURE = 0xFE, - }; - - /** - * @brief enums for secondary SBE response - * Discuss on SBE_SEC_INVALID_TARGET_ID_PASSED - * - */ - enum sbeSecondaryResponse - { - SBE_SEC_OPERATION_SUCCESSFUL = 0x00, - SBE_SEC_COMMAND_CLASS_NOT_SUPPORTED = 0x01, - SBE_SEC_COMMAND_NOT_SUPPORTED = 0x02, - SBE_SEC_INVALID_ADDRESS_PASSED = 0x03, - SBE_SEC_INVALID_TARGET_TYPE_PASSED = 0x04, - SBE_SEC_INVALID_TARGET_ID_PASSED = 0x05, - SBE_SEC_SPECIFIED_TARGET_NOT_PRESENT = 0x06, - SBE_SEC_SPECIFIED_TARGET_NOT_FUNCTIONAL = 0x07, - SBE_SEC_COMMAND_NOT_ALLOWED_IN_THIS_STATE = 0x08, - SBE_SEC_FUNCTIONALITY_NOT_SUPPORTED = 0x09, - SBE_SEC_GENERIC_FAILURE_IN_EXECUTION = 0x0A, - SBE_SEC_BACKLISTED_ACCESS = 0x0B, - SBE_SEC_OS_FAILURE = 0x0C, - SBE_SEC_HOST_MBX_REG_ACCESS_FAILURE = 0x0D, - SBE_SEC_INSUFFICIENT_DATA_PASSED = 0x0E, - SBE_SEC_EXCESS_DATA_PASSED = 0x0F, - SBE_SEC_SBE_BUSY_TO_HANDLE_COMMAND = 0x10, - }; - - - /** - * @Brief perform SBE PSU chip-op - * - * @param[in] i_pPsuRequest Pointer to PSU request commands - * @param[out] o_pPsuResponse Pointer to PSU response - * @param[in] i_timeout Time out for response - * @param[in] i_reqMsgs 4 bit mask telling which regs to write - * @param[in] i_rspMsgs 4 bit mask telling which regs to read - */ - errlHndl_t performPsuChipOp(psuCommand * i_pPsuCommand, - psuResponse * o_pPsuResponse, - const uint64_t i_timeout, - uint8_t i_reqMsgs, - uint8_t i_rspMsgs); + // Doorbell Register to trigger SBE interrupt + // psu_sbe_interrupt_msg_available. Set by host firmware to inform + // the SBE about a waiting message in the Host/SBE Mailbox Registers + SBE_DOORBELL =0x8000000000000000, + }; + enum hostDoorbellReg + { + // Doorbell Register for Host Bridge interrupt. Set by the SBE to + // inform host firmware about a response message in the Host/SBE + // Mailbox Registers + HOST_RESPONSE_WAITING = 0x8000000000000000, + HOST_CLEAR_RESPONSE_WAITING = 0x7FFFFFFFFFFFFFFF, + }; -//----------------------------------------------------------------------------- -// Local definitions for the device driver -//----------------------------------------------------------------------------- - /** - * @brief Write request to PSU - * - * @param[in] i_target Master proc to use for scoms - * @param[in] i_pPsuRequest Pointer to PSU request commands - * @param[in] i_reqMsgs 4 bit mask telling which regs to write - * - * @return errlHndl_t Error log handle on failure. - */ - errlHndl_t writeRequest(TARGETING::Target * i_target, - psuCommand * i_pPsuRequest, - uint8_t i_reqMsgs); - /** - * @brief Read response from PSU - * - * @param[in] i_target Master proc to use for scoms - * @param[in] i_pPsuRequest Pointer to PSU request commands - * @param[out] o_pPsuResponse Pointer to PSU response - * @param[in] i_timeout Time out for response - * @param[in] i_rspMsgs 4 bit mask telling which regs to read - * - * @return errlHndl_t Error log handle on failure. - */ - errlHndl_t readResponse(TARGETING::Target * i_target, - psuCommand * i_pPsuRequest, - psuResponse * o_pPsuResponse, - const uint64_t i_timeout, - uint8_t i_rspMsgs); - /** - * @brief Poll for response ready to be read - * - * @param[in] i_target Master proc to use for scoms - * @param[in] i_timeout Time out for response - * - * @return errlHndl_t Error log handle on failure. - */ - errlHndl_t pollForPsuComplete(TARGETING::Target * i_target, - const uint64_t i_timeout); - /** - * @brief Read Scom wrapper - * - * @param[in] i_target Master proc to use for scoms - * @param[in] i_addr Scom address - * @param[out] o_pData Pointer to returned data - * @param[in] i_trace Trace control to avoid overruning trace buffer - * when polling for response ready to be read - * - * @return errlHndl_t Error log handle on failure. - */ - errlHndl_t readScom(TARGETING::Target * i_target, - uint64_t i_addr, - uint64_t * o_pData, - bool i_trace=true); - - /** - * @brief Write Scom wrapper - * - * @param[in] i_target Master proc to use for scoms - * @param[in] i_addr Scom address - * @param[in] i_pData Pointer to data to write - * - * @return errlHndl_t Error log handle on failure. - */ - errlHndl_t writeScom(TARGETING::Target * i_target, - uint64_t i_addr, - uint64_t * i_pData); - - /** - * @brief SBE PSU register addresses - */ - enum psuRegs - { - PSU_HOST_SBE_MBOX0_REG = 0x000D0050, - PSU_HOST_SBE_MBOX1_REG = 0x000D0051, - PSU_HOST_SBE_MBOX2_REG = 0x000D0052, - PSU_HOST_SBE_MBOX3_REG = 0x000D0053, - PSU_HOST_SBE_MBOX4_REG = 0x000D0054, - PSU_HOST_SBE_MBOX5_REG = 0x000D0055, - PSU_HOST_SBE_MBOX6_REG = 0x000D0056, - PSU_HOST_SBE_MBOX7_REG = 0x000D0057, - PSU_SBE_DOORBELL_REG_RW = 0x000D0060, - PSU_SBE_DOORBELL_REG_AND = 0x000D0061, - PSU_SBE_DOORBELL_REG_OR = 0x000D0062, - PSU_HOST_DOORBELL_REG_RW = 0x000D0063, - PSU_HOST_DOORBELL_REG_AND = 0x000D0064, - PSU_HOST_DOORBELL_REG_OR = 0x000D0065, - }; - - /** - * @brief SBE PSU door bell register - */ - enum sbeDoorbellReg - { - // Doorbell Register to trigger SBE interrupt - // psu_sbe_interrupt_msg_available. Set by host firmware to inform - // the SBE about a waiting message in the Host/SBE Mailbox Registers - SBE_DOORBELL =0x8000000000000000, - }; - enum hostDoorbellReg - { - // Doorbell Register for Host Bridge interrupt. Set by the SBE to - // inform host firmware about a response message in the Host/SBE - // Mailbox Registers - HOST_RESPONSE_WAITING = 0x8000000000000000, - HOST_CLEAR_RESPONSE_WAITING = 0x7FFFFFFFFFFFFFFF, - }; - - - enum SBE_TARGET_TYPES { - - SBE_TARGET_TYPE_PROC = 0x00, - SBE_TARGET_TYPE_EX = 0x01, - SBE_TARGET_TYPE_PERV = 0x02, - SBE_TARGET_TYPE_MCS = 0x03, - SBE_TARGET_TYPE_TOTAL , - SBE_TARGET_TYPE_UNKNOWN = 0xFF - }; - - -} +}; // End of Class SbePsu + +} // End of namespace SBEIO #endif diff --git a/src/include/usr/util/utilbyte.H b/src/include/usr/util/utilbyte.H new file mode 100644 index 000000000..15bea7c75 --- /dev/null +++ b/src/include/usr/util/utilbyte.H @@ -0,0 +1,121 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/util/utilbyte.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* 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 */ + +#ifndef UTILBYTE_H +#define UTILBYTE_H + +/** + * @file utilbyte.H + * + * @brief byte to integer utility + * + */ + +/*****************************************************************************/ +// Byte Utility class +/*****************************************************************************/ +/** + * @brief Byte Utility class + * + */ +class UtilByte +{ + public: + + /** + * @brief Default Constructor + * + */ + UtilByte(); + + /** + * @brief Destructor + * + */ + ~UtilByte(); + + /** + * @brief extract 2 bytes from buffer and convert to uint16 + * + * @param[in] i_buffer: pointer to buffer containing 2 bytes + * to be converted + * @retval: 16 bit integer value of the consecutive 2 bytes + * pointed in the buffer + */ + + static uint16_t bufferTo16uint(void * i_buffer); + + /** + * @brief extract 4 bytes from buffer and convert to uint32 + * + * @param[in] i_buffer: pointer to buffer containing 4 bytes + * to be converted + * @retval: 32 bit integer value of the consecutive 4 bytes + * pointed in the buffer + */ + + static uint32_t bufferTo32uint(void * i_buffer); + +}; + +/* + * Constructor + */ +UtilByte::UtilByte() +{ +} + +/* + * Destructor + */ +UtilByte::~UtilByte() +{ +} + +/* + * @brief converts 2 bytes into uint16 + */ + +inline uint16_t UtilByte::bufferTo16uint(void * i_buffer) +{ + return static_cast<uint16_t>( + ((uint8_t) *static_cast<char *>(i_buffer)) << 8 | + ((uint8_t) *(static_cast<char *>(i_buffer)+1))); +} + +/* + * @brief converts 4 bytes into uint16 + */ + +inline uint32_t UtilByte::bufferTo32uint(void * i_buffer) +{ + return static_cast<uint32_t>( + ((uint8_t) *static_cast<char *>(i_buffer)) << 24 | + ((uint8_t) *(static_cast<char *>(i_buffer)+1)) << 16 | + ((uint8_t) *(static_cast<char *>(i_buffer)+2)) << 8 | + ((uint8_t) *(static_cast<char *>(i_buffer)+3))); +} + +#endif //UTILBYTE_H diff --git a/src/makefile b/src/makefile index 55b4fdb78..4349f6d16 100644 --- a/src/makefile +++ b/src/makefile @@ -237,6 +237,7 @@ TESTCASE_MODULES += testfapi2 #TESTCASE_MODULES += testi2c TESTCASE_MODULES += testsbe +TESTCASE_MODULES += testsbeio #******************************************************* diff --git a/src/usr/sbeio/makefile b/src/usr/sbeio/makefile index 0f0fddd15..3fc386a3c 100644 --- a/src/usr/sbeio/makefile +++ b/src/usr/sbeio/makefile @@ -33,4 +33,6 @@ OBJS += sbe_fifodd.o OBJS += sbe_scomAccess.o OBJS += sbe_scomAccessdd.o +SUBDIRS = test.d + include ${ROOTPATH}/config.mk diff --git a/src/usr/sbeio/sbe_coreStateControl.C b/src/usr/sbeio/sbe_coreStateControl.C index 54f86d0a6..b449d6516 100644 --- a/src/usr/sbeio/sbe_coreStateControl.C +++ b/src/usr/sbeio/sbe_coreStateControl.C @@ -59,20 +59,21 @@ errlHndl_t startDeadmanLoop(const uint64_t i_waitTime ) SBE_TRACD(ENTER_MRK "startDeadmanLoop waitTime=0x%x",i_waitTime); - psuCommand l_psuCommand( - SBE_DMCONTROL_START | SBE_DMCONTROL_RESPONSE_REQUIRED, //control flags - SBE_PSU_CLASS_CORE_STATE, //command class - SBE_CMD_CONTROL_DEADMAN_LOOP); //command - psuResponse l_psuResponse; + SbePsu::psuCommand l_psuCommand( + SbePsu::SBE_DMCONTROL_START | + SbePsu::SBE_DMCONTROL_RESPONSE_REQUIRED, //control flags + SbePsu::SBE_PSU_CLASS_CORE_STATE, //command class + SbePsu::SBE_CMD_CONTROL_DEADMAN_LOOP); //command + SbePsu::psuResponse l_psuResponse; // set up PSU command message l_psuCommand.cd1_ControlDeadmanLoop_WaitTime = i_waitTime; - errl = performPsuChipOp(&l_psuCommand, + errl = SBEIO::SbePsu::getTheInstance().performPsuChipOp(&l_psuCommand, &l_psuResponse, - MAX_PSU_SHORT_TIMEOUT_NS, - SBE_DMCONTROL_START_REQ_USED_REGS, - SBE_DMCONTROL_START_RSP_USED_REGS); + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_DMCONTROL_START_REQ_USED_REGS, + SbePsu::SBE_DMCONTROL_START_RSP_USED_REGS); SBE_TRACD(EXIT_MRK "startDeadmanLoop"); @@ -93,17 +94,18 @@ errlHndl_t stopDeadmanLoop() SBE_TRACD(ENTER_MRK "stopDeadmanLoop"); - psuCommand l_psuCommand( - SBE_DMCONTROL_STOP + SBE_DMCONTROL_RESPONSE_REQUIRED, //control flags - SBE_PSU_CLASS_CORE_STATE, //command class - SBE_CMD_CONTROL_DEADMAN_LOOP); //comand - psuResponse l_psuResponse; + SbePsu::psuCommand l_psuCommand( + SbePsu::SBE_DMCONTROL_STOP + + SbePsu::SBE_DMCONTROL_RESPONSE_REQUIRED, //control flags + SbePsu::SBE_PSU_CLASS_CORE_STATE, //command class + SbePsu::SBE_CMD_CONTROL_DEADMAN_LOOP); //comand + SbePsu::psuResponse l_psuResponse; - errl = performPsuChipOp(&l_psuCommand, + errl = SBEIO::SbePsu::getTheInstance().performPsuChipOp(&l_psuCommand, &l_psuResponse, - MAX_PSU_SHORT_TIMEOUT_NS, - SBE_DMCONTROL_STOP_REQ_USED_REGS, - SBE_DMCONTROL_STOP_RSP_USED_REGS); + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_DMCONTROL_STOP_REQ_USED_REGS, + SbePsu::SBE_DMCONTROL_STOP_RSP_USED_REGS); SBE_TRACD(EXIT_MRK "stopDeadmanLoop"); diff --git a/src/usr/sbeio/sbe_psudd.C b/src/usr/sbeio/sbe_psudd.C index d5d9d4e7b..f1e200c34 100644 --- a/src/usr/sbeio/sbe_psudd.C +++ b/src/usr/sbeio/sbe_psudd.C @@ -36,10 +36,13 @@ #include <errl/errludtarget.H> #include <targeting/common/target.H> #include <targeting/common/targetservice.H> +#include <errl/errlreasoncodes.H> #include <sbeio/sbeioreasoncodes.H> #include <initservice/initserviceif.H> //@todo-RTC:149454-Remove #include <sbeio/sbe_psudd.H> #include <arch/ppc.H> +#include <util/utilbyte.H> +#include <kernel/pagemgr.H> trace_desc_t* g_trac_sbeio; TRAC_INIT(&g_trac_sbeio, SBEIO_COMP_NAME, 6*KILOBYTE, TRACE::BUFFER_SLOW); @@ -51,11 +54,57 @@ TRAC_INIT(&g_trac_sbeio, SBEIO_COMP_NAME, 6*KILOBYTE, TRACE::BUFFER_SLOW); using namespace ERRORLOG; -//TODO RTC 144313 implement error recovery and ffdc. - namespace SBEIO { +SbePsu & SbePsu::getTheInstance() +{ + return Singleton<SbePsu>::instance(); +} + +/** + * @brief Constructor + **/ +SbePsu::SbePsu() +{ + iv_ffdcPackageBuffer = PageManager::allocatePage(ffdcPackageSize, true); + initFFDCPackageBuffer(); + + /* + * TODO RTC 164405 + * + * call performPsuChipOp to tell SBE where to write when SBE is ready + * + * psuCommand l_psuCommand( + * SBE_REQUIRE_RESPONSE, + * SBE_PSU_GENERIC_MESSAGE, + * SBE_CMD_CONTROL_SYSTEM_CONFIG); + * + * psuResponse l_psuResponse; + * + * // Create FFDCPackage struct in psuCommand union + * uint64_t cd4_FFDCPackage_MbxReg2reserved = &iv_ffdcPackageBuffer; + * + * performPsuChipOp(&l_psuCommand, + * &l_psuResponse, + * MAX_PSU_SHORT_TIMEOUT_NS, + * SBE_SYSTEM_CONFIG_REQ_USED_REGS, + * SBE_SYSTEM_CONFIG_RSP_USED_REGS); + * + */ +} + +/** + * @brief Destructor + **/ +SbePsu::~SbePsu() +{ + if(iv_ffdcPackageBuffer != NULL) + { + PageManager::freePage(iv_ffdcPackageBuffer); + } +} + /** * @brief perform SBE PSU chip-op * @@ -65,7 +114,7 @@ namespace SBEIO * @param[in] i_reqMsgs 4 bit mask telling which regs to write * @param[in] i_rspMsgs 4 bit mask telling which regs to read */ -errlHndl_t performPsuChipOp(psuCommand * i_pPsuRequest, +errlHndl_t SbePsu::performPsuChipOp(psuCommand * i_pPsuRequest, psuResponse * o_pPsuResponse, const uint64_t i_timeout, uint8_t i_reqMsgs, @@ -155,9 +204,9 @@ errlHndl_t performPsuChipOp(psuCommand * i_pPsuRequest, /** * @brief write PSU Request message */ -errlHndl_t writeRequest(TARGETING::Target * i_target, - psuCommand * i_pPsuRequest, - uint8_t i_reqMsgs) +errlHndl_t SbePsu::writeRequest(TARGETING::Target * i_target, + psuCommand * i_pPsuRequest, + uint8_t i_reqMsgs) { errlHndl_t errl = NULL; static uint16_t l_seqID = 0; @@ -203,7 +252,8 @@ errlHndl_t writeRequest(TARGETING::Target * i_target, SBEIO_PSU_NOT_READY, i_pPsuRequest->mbxReg0, l_data); - //TODO RTC 144313 review callouts and ffdc + + handleFFDCError(errl); errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_HIGH); errl->collectTrace(SBEIO_COMP_NAME); @@ -246,11 +296,11 @@ errlHndl_t writeRequest(TARGETING::Target * i_target, /** * @brief Read PSU response messages */ -errlHndl_t readResponse(TARGETING::Target * i_target, - psuCommand * i_pPsuRequest, - psuResponse * o_pPsuResponse, - const uint64_t i_timeout, - uint8_t i_rspMsgs) +errlHndl_t SbePsu::readResponse(TARGETING::Target * i_target, + psuCommand * i_pPsuRequest, + psuResponse * o_pPsuResponse, + const uint64_t i_timeout, + uint8_t i_rspMsgs) { errlHndl_t errl = NULL; @@ -321,7 +371,8 @@ errlHndl_t readResponse(TARGETING::Target * i_target, SBEIO_PSU_RESPONSE_ERROR, i_pPsuRequest->mbxReg0, o_pPsuResponse->mbxReg4); - //TODO RTC 144313 review callouts and ffdc + + handleFFDCError(errl); errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_HIGH); errl->collectTrace(SBEIO_COMP_NAME); @@ -342,8 +393,8 @@ errlHndl_t readResponse(TARGETING::Target * i_target, /** * @brief poll for PSU to complete command */ -errlHndl_t pollForPsuComplete(TARGETING::Target * i_target, - const uint64_t i_timeout) +errlHndl_t SbePsu::pollForPsuComplete(TARGETING::Target * i_target, + const uint64_t i_timeout) { errlHndl_t errl = NULL; @@ -385,7 +436,8 @@ errlHndl_t pollForPsuComplete(TARGETING::Target * i_target, SBEIO_PSU_RESPONSE_TIMEOUT, i_timeout, 0); - //TODO RTC 144313 review callouts and ffdc + + handleFFDCError(errl); errl->addProcedureCallout(HWAS::EPUB_PRC_HB_CODE, HWAS::SRCI_PRIORITY_HIGH); errl->collectTrace(SBEIO_COMP_NAME); @@ -418,10 +470,10 @@ errlHndl_t pollForPsuComplete(TARGETING::Target * i_target, /** * @brief read Scom */ -errlHndl_t readScom(TARGETING::Target * i_target, - uint64_t i_addr, - uint64_t * o_pData, - bool i_trace) +errlHndl_t SbePsu::readScom(TARGETING::Target * i_target, + uint64_t i_addr, + uint64_t * o_pData, + bool i_trace) { errlHndl_t errl = NULL; @@ -444,9 +496,9 @@ errlHndl_t readScom(TARGETING::Target * i_target, /** * @brief write Scom */ -errlHndl_t writeScom(TARGETING::Target * i_target, - uint64_t i_addr, - uint64_t * i_pData) +errlHndl_t SbePsu::writeScom(TARGETING::Target * i_target, + uint64_t i_addr, + uint64_t * i_pData) { errlHndl_t errl = NULL; @@ -462,4 +514,131 @@ errlHndl_t writeScom(TARGETING::Target * i_target, return errl; } +/** + * @brief zero out FFDC Package Buffer + */ + +void SbePsu::initFFDCPackageBuffer() +{ + memset(iv_ffdcPackageBuffer, 0x00, PAGESIZE * ffdcPackageSize); +} + +/** + * @brief populate FFDC package buffer + * @param[in] i_data FFDC error data + * @param[in] i_len data buffer len to copy + */ +void SbePsu::writeFFDCBuffer( void * i_data, uint8_t i_len) { + if(i_len <= PAGESIZE * ffdcPackageSize) + { + initFFDCPackageBuffer(); + memcpy(iv_ffdcPackageBuffer, i_data, i_len); + } + else + { + SBE_TRACF(ERR_MRK"writeFFDCBuffer: Buffer size too large: %d", + i_len); + } +} + +/** + * @brief Read FFDC package(s) iv_ffdcPackageBuffer + * + * @param[in] io_errl Error entry object to inject FFDC errors + * + * FFDC package according to the SBE Interface Specification: + * Dword 0: + * byte 0,1: Magic Byte: 0xFFDC + * byte 2,3: Length in words (N + 6) + * byte 4,5: Sequence Id + * byte 6 : Command Class + * byte 7 : Command + * Dword 1: + * byte 0-3: Return Code + * byte 4-7: Word 0 + * Dword M: + * byte 0-3: Word N - 1 + * byte 4-7: Word N + */ + +bool SbePsu::handleFFDCError(ERRORLOG::ErrlEntry * io_errl) +{ + uint16_t l_magicByte = 0x00; + uint8_t i = 0; + bool rc = true; + + SBE_TRACD(ENTER_MRK "handleFFDCError"); + do { + // Magic Byte is 1st 2 bytes + l_magicByte = UtilByte::bufferTo16uint( + static_cast<char *>(iv_ffdcPackageBuffer) + i); + + if(l_magicByte == ffdcMagicByte) + { + // Length is next 2 bytes (in words, each word is 4 bytes) + uint16_t l_packageLen = UtilByte::bufferTo16uint( + static_cast<char *>(iv_ffdcPackageBuffer) + (i + 2)); + // In FFDC packet, byte 2 & byte 3 holds the length in words, + // which is 6 bytes less than the total package length. + uint8_t l_words = l_packageLen - ffdcPadLen; + uint8_t l_wordLen = ffdcWordLen * l_words; + SBE_TRACD(INFO_MRK"handleFFDCError: Package length: %d, Words: %d", l_packageLen, l_words); + + // Check to see if what we're copying is beyond the buffer size + if((uint8_t) (i + wordPadding + l_wordLen) > + PAGESIZE * ffdcPackageSize) + { + SBE_TRACF(ERR_MRK"handleFFDCError: FFDC Package buffer overflow detected."); + rc = false; + break; + } + else + { + // Extract the words and add to errl + void * l_wordBuffer = (void *) malloc(l_wordLen); + if(l_wordBuffer == NULL) + { + SBE_TRACF(ERR_MRK"handleFFDCError: Failure to allocate memory."); + rc = false; + break; + } + // Copy data from ffdcPackageBuffer to wordBuffer + // starting at 12th byte from current pointer + memcpy(static_cast<char *>(iv_ffdcPackageBuffer) + wordPadding, + l_wordBuffer, l_wordLen); + + ErrlUD *l_errlud = io_errl->addFFDC( SBE_COMP_ID, + l_wordBuffer, + sizeof(l_wordBuffer), + 0, // version + ERRL_UDT_NOFORMAT, // subversion + false ); + + if(l_errlud == NULL) + { + SBE_TRACF(ERR_MRK"handleFFDCError: Failure to add FFDC to error log."); + rc = false; + } + + free(l_wordBuffer); + } + // Skip length of whole package + i += l_wordLen + wordPadding; + } + else + { + SBE_TRACD(ERR_MRK"handleFFDCError: Invalid FFDC Magic Byte: 0x%04lx", + l_magicByte); + break; + } + } while (l_magicByte != 0x00); + + // zero out the whole thing + initFFDCPackageBuffer(); + + SBE_TRACD(EXIT_MRK "handleFFDCError"); + return rc; + +} + } //end of namespace SBEIO diff --git a/src/usr/sbeio/sbe_systemConfig.C b/src/usr/sbeio/sbe_systemConfig.C index 64774c64c..1e9a00a26 100644 --- a/src/usr/sbeio/sbe_systemConfig.C +++ b/src/usr/sbeio/sbe_systemConfig.C @@ -63,20 +63,20 @@ namespace SBEIO SBE_TRACD(ENTER_MRK "sending system configuration from HB -> SBE i_systemConfig=0x%x",i_systemConfig); - psuCommand l_psuCommand( - SBE_REQUIRE_RESPONSE, //control flags - SBE_PSU_GENERIC_MESSAGE, //command class - SBE_CMD_CONTROL_SYSTEM_CONFIG); //command - psuResponse l_psuResponse; + SbePsu::psuCommand l_psuCommand( + SbePsu::SBE_REQUIRE_RESPONSE, //control flags + SbePsu::SBE_PSU_GENERIC_MESSAGE, //command class + SbePsu::SBE_CMD_CONTROL_SYSTEM_CONFIG); //command + SbePsu::psuResponse l_psuResponse; // set up PSU command message l_psuCommand.cd2_SetSystemConfig_SystemFabricIdMap = i_systemConfig; - errl = performPsuChipOp(&l_psuCommand, + errl = SBEIO::SbePsu::getTheInstance().performPsuChipOp(&l_psuCommand, &l_psuResponse, - MAX_PSU_SHORT_TIMEOUT_NS, - SBE_SYSTEM_CONFIG_REQ_USED_REGS, - SBE_SYSTEM_CONFIG_RSP_USED_REGS); + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_SYSTEM_CONFIG_REQ_USED_REGS, + SbePsu::SBE_SYSTEM_CONFIG_RSP_USED_REGS); SBE_TRACD(EXIT_MRK "sendSystemConfig"); diff --git a/src/usr/sbeio/test/makefile b/src/usr/sbeio/test/makefile new file mode 100644 index 000000000..2017d8aab --- /dev/null +++ b/src/usr/sbeio/test/makefile @@ -0,0 +1,33 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/sbeio/test/makefile $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2011,2016 +# [+] International Business Machines Corp. +# +# +# 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 +ROOTPATH = ../../../.. + +EXTRAINCDIR += ${ROOTPATH}/src/usr/sbeio/ + +MODULE = testsbeio + +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/sbeio/test/sbe_ffdctest.H b/src/usr/sbeio/test/sbe_ffdctest.H new file mode 100644 index 000000000..51105f997 --- /dev/null +++ b/src/usr/sbeio/test/sbe_ffdctest.H @@ -0,0 +1,221 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/test/sbe_ffdctest.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* 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 */ +#ifndef __SBE_FFDCTEST_H +#define __SBE_FFDCTEST_H + +/** + * @file sbe_ffdctest.H + * + * @brief Test cases for sbe/hb ffdc package exchange +*/ + +#include <cxxtest/TestSuite.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <sbeio/sbe_psudd.H> + +extern trace_desc_t* g_trac_sbeio; + +class SbeFFDCTest : public CxxTest::TestSuite, public SBEIO::SbePsu +{ + public: + + /** + * @brief Test with zero data + */ + void testSBEFFDC1(void) + { + TS_TRACE(ENTER_MRK "sbeioTestFFDC test 1: no data"); + + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + 0, + 0, + 0, + 0); + + if(!SBEIO::SbePsu::handleFFDCError(l_errl)) + { + TS_FAIL(EXIT_MRK "sbeioTestFFDC test 1 failed."); + } + + delete l_errl; + TS_TRACE(EXIT_MRK "sbeioTestFFDC test 1: no data"); + } + + /** + * @brief Test with valid magic byte, 1 package, 1 word data + */ + void testSBEFFDC2(void) + { + uint8_t data[16] = { + 255, 220, // magic byte + 0, 7, // length of 1 word + 6 + 0, 1, // arbitrary sequence ID + 1, 1, // arbitrary command class and commamd + 0, 1, 0, 1, // arbitrary return code + 1, 1, 1, 1 // arbitrary data + }; + + TS_TRACE(ENTER_MRK "sbeioTestFFDC test 2: 1 package, 1 word data"); + + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + 0, + 0, + 0, + 0); + + SBEIO::SbePsu::writeFFDCBuffer(&data, 16); + if(!SBEIO::SbePsu::handleFFDCError(l_errl)) + { + TS_FAIL(EXIT_MRK "sbeioTestFFDC test 2 failed."); + } + + delete l_errl; + TS_TRACE(EXIT_MRK "sbeioTestFFDC test 2: 1 package, 1 word data"); + } + + /** + * @brief Test with valid magic byte, 1 package, 2 word data + */ + void testSBEFFDC3(void) + { + + uint8_t data[20] = { + 255, 220, // magic byte + 0, 8, // length of 2 word + 6 + 0, 2, // arbitrary sequence ID + 1, 1, // arbitrary command class and commamd + 0, 1, 0, 1, // arbitrary return code + 1, 1, 1, 1, // arbitrary data + 1, 1, 1, 1 // arbitrary data + }; + + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + 0, + 0, + 0, + 0); + TS_TRACE(ENTER_MRK "sbeioTestFFDC test 3: 1 package, 2 word data"); + + SBEIO::SbePsu::writeFFDCBuffer(&data, 20); + if(!SBEIO::SbePsu::handleFFDCError(l_errl)) + { + TS_FAIL(EXIT_MRK "sbeioTestFFDC test 3 failed."); + } + + delete l_errl; + TS_TRACE(EXIT_MRK "sbeioTestFFDC test 3: 1 package, 2 word data"); + + } + + /** + * @brief Test with valid magic byte, 2 package + */ + void testSBEFFDC4(void) + { + + uint8_t data[36] = { + 255, 220, // magic byte + 0, 8, // length of 1 word + 6 + 0, 2, // arbitrary sequence ID + 1, 1, // arbitrary command class and commamd + 0, 1, 0, 1, // arbitrary return code + 1, 1, 1, 1, // arbitrary data + 1, 1, 1, 1, + 255, 220, // package 2 + 0, 7, // length of 1 word + 6 + 0, 2, // arbitrary sequence ID + 1, 1, // arbitrary command class and commamd + 0, 1, 0, 1, // arbitrary return code + 2, 2, 2, 2 + }; + + TS_TRACE(ENTER_MRK "sbeioTestFFDC test 4: 2 packages, 2 word data"); + + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + 0, + 0, + 0, + 0); + SBEIO::SbePsu::writeFFDCBuffer(&data, 36); + if(!SBEIO::SbePsu::handleFFDCError(l_errl)) + { + TS_FAIL(EXIT_MRK "sbeioTestFFDC test 4 failed."); + } + + delete l_errl; + TS_TRACE(EXIT_MRK "sbeioTestFFDC test 4: 2 packages, 2 word data"); + + } + /** + * @brief Test with valid magic byte, 2 package, 2nd magic byte is bad + */ + void testSBEFFDC5(void) + { + + uint8_t data[40] = { + 255, 220, // magic byte + 0, 8, // length of 1 word + 6 + 0, 2, // arbitrary sequence ID + 1, 1, // arbitrary command class and commamd + 0, 1, 0, 1, // arbitrary return code + 1, 1, 1, 1, // arbitrary data + 1, 1, 1, 1, + 220, 220, // package 2 - bad magic byte + 0, 7, // length of 1 word + 6 + 0, 2, // arbitrary sequence ID + 1, 1, // arbitrary command class and commamd + 0, 1, 0, 1, // arbitrary return code + 1, 1, 1, 1, // arbitrary data + 2, 2, 2, 2 + }; + + TS_TRACE(ENTER_MRK"sbeioTestFFDC test 5:\ + 2 packages, bad 2nd magic byte"); + + errlHndl_t l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + 0, + 0, + 0, + 0); + SBEIO::SbePsu::writeFFDCBuffer(&data, 40); + if(!SBEIO::SbePsu::handleFFDCError(l_errl)) + { + TS_FAIL(EXIT_MRK "sbeioTestFFDC test 5 failed."); + } + + delete l_errl; + TS_TRACE(EXIT_MRK"sbeioTestFFDC test 5:\ + 2 packages, bad 2nd magic byte"); + + } +}; + +#endif diff --git a/src/usr/scan/scandd.C b/src/usr/scan/scandd.C index 1f3941a36..b12befb22 100644 --- a/src/usr/scan/scandd.C +++ b/src/usr/scan/scandd.C @@ -170,26 +170,26 @@ DEVICE_REGISTER_ROUTE( DeviceFW::WILDCARD, /// @brief translates HB target types to SBE target type groups /// @param[in] i_hbTarget includes the HB target type /// @return SBEIO::SBE_TARGET_TYPES returns SBE_TARGET_TYPE_UNKNOWN in error -SBE_TARGET_TYPES translateToSBETargetType(TARGETING::Target * i_hbTarget) +SbePsu::SBE_TARGET_TYPES translateToSBETargetType(TARGETING::Target *i_hbTarget) { TRACDCOMP( g_trac_scandd, ENTER_MRK "entering translateToSBETargetType()"); - SBE_TARGET_TYPES sbeType; - sbeType = SBE_TARGET_TYPE_UNKNOWN; + SbePsu::SBE_TARGET_TYPES sbeType; + sbeType = SbePsu::SBE_TARGET_TYPE_UNKNOWN; switch( i_hbTarget->getAttr<TARGETING::ATTR_TYPE>()){ case(TARGETING::TYPE_PROC): { - sbeType = SBE_TARGET_TYPE_PROC; + sbeType = SbePsu::SBE_TARGET_TYPE_PROC; break; } case(TARGETING::TYPE_EX): { - sbeType = SBE_TARGET_TYPE_EX; + sbeType = SbePsu::SBE_TARGET_TYPE_EX; break; } @@ -203,12 +203,12 @@ SBE_TARGET_TYPES translateToSBETargetType(TARGETING::Target * i_hbTarget) case(TARGETING::TYPE_L4): case(TARGETING::TYPE_CORE): { - sbeType = SBE_TARGET_TYPE_PERV; + sbeType = SbePsu::SBE_TARGET_TYPE_PERV; break; } case(TARGETING::TYPE_MCS): { - sbeType = SBE_TARGET_TYPE_MCS; + sbeType = SbePsu::SBE_TARGET_TYPE_MCS; break; } default: @@ -269,14 +269,14 @@ errlHndl_t sbeScanPerformOp(TARGETING::Target * i_target, va_list i_args) errlHndl_t l_errl = NULL; TRACFCOMP( g_trac_scandd, ENTER_MRK "sbeScanPerformOp()"); - psuCommand l_psuCommand( + SbePsu::psuCommand l_psuCommand( //control flags are hardcoded here, no need to pass them into sbe function - SBE_DMCONTROL_RESPONSE_REQUIRED, + SbePsu::SBE_DMCONTROL_RESPONSE_REQUIRED, //command class - SBE_PSU_PUT_RING_FROM_IMAGE_CMD, + SbePsu::SBE_PSU_PUT_RING_FROM_IMAGE_CMD, //command - SBE_CMD_CONTROL_PUTRING); - psuResponse l_psuResponse; + SbePsu::SBE_CMD_CONTROL_PUTRING); + SbePsu::psuResponse l_psuResponse; //Ring ID for this message RingID l_ringID = static_cast<RingID>(va_arg(i_args,uint64_t)); @@ -317,11 +317,11 @@ errlHndl_t sbeScanPerformOp(TARGETING::Target * i_target, va_list i_args) ":: sbeScanPerformOp() RingMode:%.8X ", l_psuCommand.cd3_PutRing_RingMode ); - l_errl = performPsuChipOp(&l_psuCommand, + l_errl = SBEIO::SbePsu::getTheInstance().performPsuChipOp(&l_psuCommand, &l_psuResponse, - MAX_PSU_SHORT_TIMEOUT_NS, - SBE_DMCONTROL_START_REQ_USED_REGS, - SBE_DMCONTROL_START_RSP_USED_REGS); + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_DMCONTROL_START_REQ_USED_REGS, + SbePsu::SBE_DMCONTROL_START_RSP_USED_REGS); TRACFCOMP( g_trac_scandd, EXIT_MRK "exiting :: sbeScanPerformOp()"); diff --git a/src/usr/scan/scandd.H b/src/usr/scan/scandd.H index e8b410c5b..9b8dfafc8 100644 --- a/src/usr/scan/scandd.H +++ b/src/usr/scan/scandd.H @@ -71,7 +71,7 @@ errlHndl_t scanDoScan( DeviceFW::OperationType i_opType, /// @brief translates HB target types to SBE target type groups /// @param[in] i_hbTarget includes the HB target type /// @return SBEIO::SBE_TARGET_TYPES returns SBE_TARGET_TYPE_UNKNOWN in error -SBEIO::SBE_TARGET_TYPES +SBEIO::SbePsu::SBE_TARGET_TYPES translateToSBETargetType(TARGETING::Target * i_hbTarget); /// @brief returns a ChipletID for a give target |