diff options
Diffstat (limited to 'src/usr/sbeio/sbe_getCapabilities.C')
-rw-r--r-- | src/usr/sbeio/sbe_getCapabilities.C | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/src/usr/sbeio/sbe_getCapabilities.C b/src/usr/sbeio/sbe_getCapabilities.C new file mode 100644 index 000000000..4a0d7d90a --- /dev/null +++ b/src/usr/sbeio/sbe_getCapabilities.C @@ -0,0 +1,366 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/sbeio/sbe_getCapabilities.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2018 */ +/* [+] 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 */ +/** +* @file sbe_getCapabilities.C +* @brief Get the capabilities from the SBE +*/ + +#include <errl/errlmanager.H> // errlHndl_t +#include <sbeio/sbe_psudd.H> // SbeFifo::psuCommand +#include "sbe_fifodd.H" // SbeFifo::fifoGetCapabilitiesRequest +#include <sbeio/sbe_utils.H> // sbeCapabilities_t +#include <sbeio/sbeioreasoncodes.H> // SBEIO_PSU, SBEIO_FIFO, +#include <targeting/common/commontargeting.H> // get_huid +#include <util/align.H> // ALIGN_X +#include <sys/mm.h> // mm_virt_to_phys + +extern trace_desc_t* g_trac_sbeio; + +namespace SBEIO +{ +using namespace TARGETING; +using namespace ERRORLOG; + + /** + * @brief Apply the SBE capabilities to the given target + * + * @param[in] i_target Target to apply the SBE capabilities on + * + * @param[in] i_capabilities The SBE capabilities themselves + * + */ +void applySbeCapabilities(TargetHandle_t i_target, + sbeCapabilities_t &i_capabilities) +{ + // Get the SBE Version from the SBE Capabilities and set the + // attribute associated with SBE Version + ATTR_SBE_VERSION_INFO_type l_sbeVersionInfo = + TWO_UINT16_TO_UINT32(i_capabilities.majorVersion, + i_capabilities.minorVersion); + i_target->setAttr<ATTR_SBE_VERSION_INFO>(l_sbeVersionInfo); + TRACFCOMP(g_trac_sbeio,"applySbeCapabilities: " + "Retrieved SBE Version: 0x%X", l_sbeVersionInfo); + + // Get the SBE Commit ID from the SBE Capabilities and set the + // attribute associated with SBE Commit ID + ATTR_SBE_COMMIT_ID_type l_sbeCommitId = i_capabilities.commitId; + i_target->setAttr<ATTR_SBE_COMMIT_ID>(l_sbeCommitId); + TRACFCOMP(g_trac_sbeio,"applySbeCapabilities: " + "Retrieved SBE Commit ID: 0x%X", l_sbeCommitId); + + // Get the SBE Release Tag from the SBE Capabilities and set the + // attribute associated with SBE Release Tag + ATTR_SBE_RELEASE_TAG_type l_sbeReleaseTagString = {0}; + + // Make sure the sizes are compatible. + static_assert(SBE_RELEASE_TAG_MAX_CHARS <= ATTR_SBE_RELEASE_TAG_max_chars, + "Copy error - size of source is greater than size of destination."); + + // Copy the release tags over into a more compatible type and set + // the SBE Release Tags attribute + strncpy(l_sbeReleaseTagString, + i_capabilities.releaseTag, + SBE_RELEASE_TAG_MAX_CHARS); + i_target->setAttr<ATTR_SBE_RELEASE_TAG>(l_sbeReleaseTagString); + TRACFCOMP(g_trac_sbeio,"applySbeCapabilities: " + "Retrieved SBE Release Tag: %s", l_sbeReleaseTagString); +} + +/** + * getPsuSbeCapabilities + */ +errlHndl_t getPsuSbeCapabilities(TargetHandle_t i_target) +{ + errlHndl_t l_errl(nullptr); + + TRACDCOMP(g_trac_sbeio, ENTER_MRK "getPsuSbeCapabilities"); + + // Cache the SBE Capabilities' size for future uses + size_t l_sbeCapabilitiesSize = sizeof(sbeCapabilities_t); + + // Set up the buffer which the SBE will copy the capabilities info to + // Create buffer with enough size to be properly aligned + uint8_t * l_sbeCapabilitiesReadBuffer = static_cast<uint8_t*>( + malloc(l_sbeCapabilitiesSize + + (SbePsu::SBE_CAPABILITIES_ALIGNMENT_SIZE_IN_BYTES - 1)) ); + + // Align the buffer + uint64_t l_sbeCapabilitiesReadBufferAligned = + ALIGN_X(reinterpret_cast<uint64_t>(l_sbeCapabilitiesReadBuffer), + SbePsu::SBE_CAPABILITIES_ALIGNMENT_SIZE_IN_BYTES); + + // Clear buffer up to the size of the capabilities + memset(reinterpret_cast<uint8_t*>(l_sbeCapabilitiesReadBufferAligned), + 0, l_sbeCapabilitiesSize ); + + // Create a PSU request message and initialize it + SbePsu::psuCommand l_psuCommand( + SbePsu::SBE_REQUIRE_RESPONSE | + SbePsu::SBE_REQUIRE_ACK, //control flags + SbePsu::SBE_PSU_GENERIC_MESSAGE, //command class + SbePsu::SBE_PSU_MSG_GET_CAPABILITIES); //command + l_psuCommand.cd7_getSbeCapabilities_CapabilitiesSize = + ALIGN_X(l_sbeCapabilitiesSize, + SbePsu::SBE_CAPABILITIES_ALIGNMENT_SIZE_IN_BYTES); + l_psuCommand.cd7_getSbeCapabilities_CapabilitiesAddr = + mm_virt_to_phys( + reinterpret_cast<void*>(l_sbeCapabilitiesReadBufferAligned)); + + // Create a PSU response message + SbePsu::psuResponse l_psuResponse; + + do + { + // Make the call to perform the PSU Chip Operation + l_errl = SbePsu::getTheInstance().performPsuChipOp( + i_target, + &l_psuCommand, + &l_psuResponse, + SbePsu::MAX_PSU_SHORT_TIMEOUT_NS, + SbePsu::SBE_GET_CAPABILITIES_REQ_USED_REGS, + SbePsu::SBE_GET_CAPABILITIES_RSP_USED_REGS); + + // Before continuing, make sure this request is honored + if (SBE_PRI_INVALID_COMMAND == l_psuResponse.primaryStatus && + SBE_SEC_COMMAND_NOT_SUPPORTED == l_psuResponse.secondaryStatus) + { + TRACFCOMP(g_trac_sbeio, "getPsuSbeCapabilities: SBE firmware does " + "not support PSU get capabilities request"); + + // Do not pass back any errors + delete l_errl; + l_errl = nullptr; + break; + } + + + if (l_errl) + { + TRACFCOMP(g_trac_sbeio, + "getPsuSbeCapabilities: " + "Call to performPsuChipOp failed, error returned"); + + TRACDBIN(g_trac_sbeio, + "getPsuSbeCapabilities: capabilities data", + reinterpret_cast<uint8_t*>(l_sbeCapabilitiesReadBufferAligned), + l_sbeCapabilitiesSize); + + break; + } + + // Sanity check - are HW and HB communications in sync? + if ((SbePsu::SBE_PSU_GENERIC_MESSAGE != + l_psuResponse.sbe_commandClass) || + (SbePsu::SBE_PSU_MSG_GET_CAPABILITIES != + l_psuResponse.sbe_command)) + { + TRACFCOMP(g_trac_sbeio, + "Call to performPsuChipOp returned an unexpected " + "message type; " + "command class returned:0x%X, " + "expected command class:0x%X, " + "command returned:0x%X, " + "expected command:0x%X", + l_psuResponse.sbe_commandClass, + SbePsu::SBE_PSU_GENERIC_MESSAGE, + l_psuResponse.sbe_command, + SbePsu::SBE_PSU_MSG_GET_CAPABILITIES); + + /*@ + * @errortype + * @moduleid SBEIO_PSU + * @reasoncode SBEIO_RECEIVED_UNEXPECTED_MSG + * @userdata1 Target HUID + * @userdata2[0:15] Requested command class + * @userdata2[16:31] Requested command + * @userdata2[32:47] Returned command class + * @userdata2[48:63] Returned command + * @devdesc Call to PSU Chip Op returned an + * unexpected message type. + */ + l_errl = new ErrlEntry( + ERRL_SEV_INFORMATIONAL, + SBEIO_PSU, + SBEIO_RECEIVED_UNEXPECTED_MSG, + get_huid(i_target), + TWO_UINT32_TO_UINT64( + TWO_UINT16_TO_UINT32(SbePsu::SBE_PSU_GENERIC_MESSAGE, + SbePsu::SBE_PSU_MSG_GET_CAPABILITIES), + TWO_UINT16_TO_UINT32(l_psuResponse.sbe_commandClass, + l_psuResponse.sbe_command) )); + + l_errl->collectTrace(SBEIO_COMP_NAME, 256); + + break; + } + + // Check for any difference in sizes (expected vs returned) + // This may happen but it is not a show stopper, just note it + if (l_psuResponse.sbe_capabilities_size != l_sbeCapabilitiesSize) + { + TRACFCOMP(g_trac_sbeio, "getPsuSbeCapabilities:" + "Call to performPsuChipOp returned an unexpected size: " + "capabilities size returned:%d, " + "expected capabilities size:%d, ", + l_psuResponse.sbe_capabilities_size, + l_sbeCapabilitiesSize); + } + + // Create an SBE Capabilities structure to make it easy to pull data; + // clear memory before use + sbeCapabilities_t l_sbeCapabilities; + memset(&l_sbeCapabilities, 0, sizeof(sbeCapabilities_t)); + + // If the returned size is greater than or equal to the needed size, + // then copy all of the SBE capabilities + if (l_psuResponse.sbe_capabilities_size >= l_sbeCapabilitiesSize) + { + memcpy (&l_sbeCapabilities, + reinterpret_cast<void*>(l_sbeCapabilitiesReadBufferAligned), + l_sbeCapabilitiesSize); + } + // If the returned size is less than the needed size and is not zero + // then copy what was given + else if (l_psuResponse.sbe_capabilities_size) + { + memcpy (&l_sbeCapabilities, + reinterpret_cast<void*>(l_sbeCapabilitiesReadBufferAligned), + l_psuResponse.sbe_capabilities_size); + } + + // If data returned, retrieve it + if (l_psuResponse.sbe_capabilities_size) + { + applySbeCapabilities(i_target, l_sbeCapabilities); + } + } while (0); + + // Free the buffer + if (l_sbeCapabilitiesReadBuffer) + { + free(l_sbeCapabilitiesReadBuffer); + l_sbeCapabilitiesReadBuffer = nullptr; + } + + TRACFCOMP(g_trac_sbeio, EXIT_MRK "getPsuSbeCapabilities"); + + return l_errl; +}; + + +/** + * getFifoSbeCapabilities + */ +errlHndl_t getFifoSbeCapabilities(TargetHandle_t i_target) +{ + errlHndl_t l_errl(nullptr); + + TRACDCOMP(g_trac_sbeio, ENTER_MRK "getFifoSbeCapabilities"); + + do + { + // Get the needed structures to make the FIFO call + // Create a FIFO request message. Default ctor initializes correctly + SbeFifo::fifoGetCapabilitiesRequest l_fifoRequest; + + // Create a FIFO response message. No need to iniitilaize + SbeFifo::fifoGetCapabilitiesResponse l_fifoResponse; + + // Make the call to perform the FIFO Chip Operation + l_errl = SbeFifo::getTheInstance().performFifoChipOp( + i_target, + reinterpret_cast<uint32_t *>(&l_fifoRequest), + reinterpret_cast<uint32_t *>(&l_fifoResponse), + sizeof(l_fifoResponse)); + + if (l_errl) + { + TRACFCOMP(g_trac_sbeio, + "Call to performFifoChipOp failed, error returned"); + break; + } + + // Sanity check - are HW and HB communications in sync? + if ((SbeFifo::FIFO_STATUS_MAGIC != l_fifoResponse.status.magic) || + (SbeFifo::SBE_FIFO_CLASS_GENERIC_MESSAGE != + l_fifoResponse.status.commandClass) || + (SbeFifo::SBE_FIFO_CMD_GET_CAPABILITIES != + l_fifoResponse.status.command)) + { + TRACFCOMP(g_trac_sbeio, + "Call to performFifoChipOp returned an unexpected " + "message type; " + "magic code returned:0x%X, " + "expected magic code:0x%X, " + "command class returned:0x%X, " + "expected command class:0x%X, " + "command returned:0x%X, " + "expected command:0x%X", + l_fifoResponse.status.magic, + SbeFifo::FIFO_STATUS_MAGIC, + l_fifoResponse.status.commandClass, + SbeFifo::SBE_FIFO_CLASS_GENERIC_MESSAGE, + l_fifoResponse.status.command, + SbeFifo::SBE_FIFO_CMD_GET_CAPABILITIES); + + /*@ + * @errortype + * @moduleid SBEIO_FIFO + * @reasoncode SBEIO_RECEIVED_UNEXPECTED_MSG + * @userdata1 Target HUID + * @userdata2[0:15] Requested command class + * @userdata2[16:31] Requested command + * @userdata2[32:47] Returned command class + * @userdata2[48:63] Returned command + * @devdesc Call to FIFO Chip Op returned an + * unexpected message type. + */ + l_errl = new ErrlEntry( + ERRL_SEV_INFORMATIONAL, + SBEIO_FIFO, + SBEIO_RECEIVED_UNEXPECTED_MSG, + get_huid(i_target), + TWO_UINT32_TO_UINT64( + TWO_UINT16_TO_UINT32(SbeFifo::SBE_FIFO_CLASS_GENERIC_MESSAGE, + SbeFifo::SBE_FIFO_CMD_GET_CAPABILITIES), + TWO_UINT16_TO_UINT32(l_fifoResponse.status.commandClass, + l_fifoResponse.status.command) )); + + l_errl->collectTrace(SBEIO_COMP_NAME, 256); + + break; + } + + applySbeCapabilities(i_target, l_fifoResponse.capabilities); + } + while(0); + + TRACDCOMP(g_trac_sbeio, EXIT_MRK "getFifoSbeCapabilities"); + + return l_errl; +}; + +} //end namespace SBEIO + |