diff options
author | Nick Bofferding <bofferdn@us.ibm.com> | 2011-06-08 08:11:59 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2011-06-17 16:02:44 -0500 |
commit | 36d3996114b47cac0f12f16bf5a5c51a2f5f2ecf (patch) | |
tree | 8a8175b9d1bb5f6ef76a1d32eb2226fc6067eb98 /src/usr/targeting/targetservice.C | |
parent | cdaabfdbec148d9ce85f422507c596a8ae6ced08 (diff) | |
download | talos-hostboot-36d3996114b47cac0f12f16bf5a5c51a2f5f2ecf.tar.gz talos-hostboot-36d3996114b47cac0f12f16bf5a5c51a2f5f2ecf.zip |
Added support for base targeting infrastructure
Change-Id: Ie32d18b421b63f067eaf49a3592368f4adc444aa
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/139
Tested-by: Jenkins Server
Reviewed-by: MIKE J. JONES <mjjones@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/targeting/targetservice.C')
-rw-r--r-- | src/usr/targeting/targetservice.C | 567 |
1 files changed, 567 insertions, 0 deletions
diff --git a/src/usr/targeting/targetservice.C b/src/usr/targeting/targetservice.C new file mode 100644 index 000000000..e90449d23 --- /dev/null +++ b/src/usr/targeting/targetservice.C @@ -0,0 +1,567 @@ + +/** + * @file targetservice.C + * + * @brief Implementation of the TargetService class + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +// STD +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +// Other components +#include <trace/interface.H> + +// This component +#include <targeting/targetservice.H> +#include "trace.H" +#include "fakepnordata.H" + +//****************************************************************************** +// targetService +//****************************************************************************** + +namespace TARGETING +{ + +#define TARG_NAMESPACE "TARGETING::" + +//****************************************************************************** +// targetService +//****************************************************************************** + +TARGETING::TargetService& targetService() +{ + #define TARG_FN "targetService()" + + return TARGETING::theTargetService::instance(); + + #undef TARG_FN +} + +//****************************************************************************** +// Component trace buffer +//****************************************************************************** + +trace_desc_t* g_trac_targeting = NULL; +TRAC_INIT(&g_trac_targeting, "TARG", 4096); + +#define TARG_CLASS "TargetService::" + +//****************************************************************************** +// TargetService::TargetService +//****************************************************************************** + +TargetService::TargetService() : + iv_initialized(false), iv_maxTargets(0), iv_pPnor(NULL) +{ + #define TARG_FN "TargetService()" + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::~TargetService +//****************************************************************************** + +TargetService::~TargetService() +{ + #define TARG_FN "~TargetService()" + + // Nothing to do; Target[] memory not owned by this object + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::init +//****************************************************************************** + +void TargetService::init() +{ + #define TARG_FN "init()" + + TARG_ENTER(); + + // Build the association mappings + AssociationAttrMap a1 = {PARENT, INWARDS, ATTR_PHYS_PATH}; + AssociationAttrMap a2 = {CHILD, OUTWARDS, ATTR_PHYS_PATH}; + AssociationAttrMap a3 = {PARENT_BY_AFFINITY, INWARDS, ATTR_AFFINITY_PATH}; + AssociationAttrMap a4 = {CHILD_BY_AFFINITY, OUTWARDS, ATTR_AFFINITY_PATH}; + AssociationAttrMap a5 = {VOLTAGE_SUPPLIER, INWARDS, ATTR_POWER_PATH}; + AssociationAttrMap a6 = {VOLTAGE_CONSUMER, OUTWARDS, ATTR_POWER_PATH}; + iv_associationMappings.push_back(a1); + iv_associationMappings.push_back(a2); + iv_associationMappings.push_back(a3); + iv_associationMappings.push_back(a4); + iv_associationMappings.push_back(a5); + iv_associationMappings.push_back(a6); + + // Get+save pointer to beginning of targeting's swappable config in + // PNOR. Note that this will change once PNOR is accessible + (void)thePnorBuilderService::instance() + .getTargetingImageBaseAddress(iv_pPnor); + + (void)_configureTargetPool(); + + iv_initialized = true; + + TARG_EXIT(); + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::getTopLevelTarget +//****************************************************************************** + +void TargetService::getTopLevelTarget( + Target*& o_targetHandle) const +{ + #define TARG_FN "getTopLevelTarget(...)" + + if (iv_initialized) + { + EntityPath l_topLevelPhysicalPath(EntityPath::PATH_PHYSICAL); + l_topLevelPhysicalPath.addLast(TYPE_SYS, 0); + o_targetHandle = toTarget(l_topLevelPhysicalPath); + } + else + { + o_targetHandle = NULL; + assert(iv_initialized); + } + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::exists +//****************************************************************************** + +void TargetService::exists( + const EntityPath& i_entityPath, + bool& o_exists) const +{ + #define TARG_FN "exists(...)" + + bool l_found = false; + if (iv_initialized) + { + for (uint32_t i = 0; i < iv_maxTargets; ++i) + { + if (i_entityPath == (*iv_targets)[i].getAttr<ATTR_PHYS_PATH> ()) + { + l_found = true; + } + } + } + else + { + assert(iv_initialized); + } + + o_exists = l_found; + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::toTarget +//****************************************************************************** + +Target* TargetService::toTarget( + const EntityPath& i_entityPath) const +{ + #define TARG_FN "toTarget(...)" + + // Used by -> operator on EntityPath for convenience (can be dangerous + // though!) + Target* l_pTarget = NULL; + if (iv_initialized) + { + for (uint32_t i = 0; i < iv_maxTargets; ++i) + { + if (i_entityPath == (*iv_targets)[i].getAttr<ATTR_PHYS_PATH> ()) + { + l_pTarget = &(*iv_targets)[i]; + break; + } + } + } + else + { + assert(iv_initialized); + } + + return l_pTarget; + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::masterProcChipTarget +//****************************************************************************** + +void TargetService::masterProcChipTargetHandle( + Target*& o_masterProcChipTargetHandle) const +{ + #define TARG_FN "masterProcChipTargetHandle(...)" + + Target* l_pTarget = NULL; + if (iv_initialized) + { + //@TODO Need to query the actual hardware and cross check it with + // PNOR to determine the master chip + // target; for now, just always report sys0.n0.proc0 + EntityPath l_masterProcChipEntityPath(EntityPath::PATH_PHYSICAL); + l_masterProcChipEntityPath.addLast(TYPE_SYS, 0).addLast(TYPE_NODE, 0) + .addLast(TYPE_PROC, 0); + + l_pTarget = l_masterProcChipEntityPath.operator->(); + } + else + { + assert(iv_initialized); + } + + o_masterProcChipTargetHandle = l_pTarget; + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::tryGetPath +//****************************************************************************** + +bool TargetService::tryGetPath( + const ATTRIBUTE_ID i_attr, + const Target* const i_pTarget, + EntityPath& o_entityPath) const +{ + #define TARG_FN "tryGetPath(...)" + + bool l_exist = false; + if (iv_initialized) + { + switch (i_attr) + { + case ATTR_PHYS_PATH: + l_exist = i_pTarget->tryGetAttr<ATTR_PHYS_PATH> (o_entityPath); + break; + case ATTR_AFFINITY_PATH: + l_exist = i_pTarget->tryGetAttr<ATTR_AFFINITY_PATH> ( + o_entityPath); + break; + case ATTR_POWER_PATH: + l_exist = i_pTarget->tryGetAttr<ATTR_POWER_PATH> (o_entityPath); + break; + default: + TARG_ERR("BUG; i_attr = 0x%08X does not map to an entity " + "path"); + assert(0); + break; + } + } + else + { + assert(iv_initialized); + } + + return l_exist; + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::getAssociated +//****************************************************************************** + +void TargetService::getAssociated( + const Target* const i_pTarget, + const ASSOCIATION_TYPE i_type, + const RECURSION_LEVEL i_recursionLevel, + TargetHandleList& o_list) const +{ + #define TARG_FN "getAssociated(...)" + + do { + + assert(iv_initialized); + + if( (i_pTarget == NULL) + || (i_pTarget == MASTER_PROCESSOR_CHIP_TARGET_SENTINEL) ) + { + TARG_ERR("BUG; caller tried to get association using a NULL target " + "handle or the master processor chip target handle sentinel. " + "i_pTarget = %p",i_pTarget); + assert(0); + } + + // Start with no elements + o_list.clear(); + + // Figure out which attribute to look up + for (uint32_t i = 0; i < iv_associationMappings.size(); ++i) + { + if (i_type == iv_associationMappings[i].associationType) + { + EntityPath l_entityPath; + + bool l_exist = tryGetPath(iv_associationMappings[i].attr, + i_pTarget, l_entityPath); + + if (l_exist) + { + if (iv_associationMappings[i].associationDir == INWARDS) + { + (void) _getInwards(iv_associationMappings[i].attr, + i_recursionLevel, l_entityPath, o_list); + } + else if (iv_associationMappings[i].associationDir + == OUTWARDS) + { + (void) _getOutwards(iv_associationMappings[i].attr, + i_recursionLevel, l_entityPath, o_list); + } + else + { + TARG_ERR("BUG; iv_associationMappings[i].associationDir " + "= 0x%X not supported", + iv_associationMappings[i].associationDir); + assert(0); + } + } + break; + } + } + + } while (0); + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::dump() +//****************************************************************************** + +void TargetService::dump() const +{ + #define TARG_FN "dump(...)" + + if (iv_initialized) + { + TARG_INF("Targets (size=%d):", + sizeof(Target)*iv_maxTargets); + + for (uint32_t i = 0; i < iv_maxTargets; ++i) + { + TARG_INF( + "[Target %d] " + "Class = 0x%X, " + "Type = 0x%X, " + "Model = 0x%X", + i, + (*iv_targets)[i].getAttr<ATTR_CLASS>(), + (*iv_targets)[i].getAttr<ATTR_TYPE>(), + (*iv_targets)[i].getAttr<ATTR_MODEL>()); + TARG_INF("Physical"); + (*iv_targets)[i].getAttr<ATTR_PHYS_PATH>().dump(); + + EntityPath l_entityPath; + if( (*iv_targets)[i].tryGetAttr<ATTR_AFFINITY_PATH>(l_entityPath) ) + { + TARG_INF("Affinity"); + l_entityPath.dump(); + } + + if( (*iv_targets)[i].tryGetAttr<ATTR_POWER_PATH>(l_entityPath) ) + { + TARG_INF("Power"); + l_entityPath.dump(); + } + + uint8_t l_dummyRw = 0; + if ((*iv_targets)[i].tryGetAttr<ATTR_DUMMY_RW> (l_dummyRw)) + { + TARG_INF("Dummy = 0x%X", + l_dummyRw); + } + + TARG_INF("Supports FSI SCOM = %d", + (*iv_targets)[i].getAttr<ATTR_PRIMARY_CAPABILITIES>() + .supportsFsiScom); + TARG_INF("Supports XSCOM SCOM = %d", + (*iv_targets)[i].getAttr<ATTR_PRIMARY_CAPABILITIES>() + .supportsXscom); + TARG_INF("Supports Inband SCOM = %d", + (*iv_targets)[i].getAttr<ATTR_PRIMARY_CAPABILITIES>() + .supportsInbandScom); + + ScomSwitches l_switches = {0}; + if ( (*iv_targets)[i].tryGetAttr<ATTR_SCOM_SWITCHES>(l_switches) ) + { + TARG_INF("Use FSI SCOM = %d",l_switches.useFsiScom); + TARG_INF("Use XSCOM = %d",l_switches.useXscom); + TARG_INF("Use inband SCOM = %d",l_switches.useInbandScom); + } + + uint64_t l_xscomBaseAddr = 0; + if ( (*iv_targets)[i].tryGetAttr<ATTR_XSCOM_BASE_ADDRESS>( + l_xscomBaseAddr) ) + { + TARG_INF("XSCOM Base Address = 0x%X",l_xscomBaseAddr); + } + + XscomChipInfo l_xscomChipInfo = {0}; + if ( (*iv_targets)[i].tryGetAttr<ATTR_XSCOM_CHIP_INFO>( + l_xscomChipInfo) ) + { + TARG_INF("XSCOM Node ID = 0x%X",l_xscomChipInfo.nodeId); + TARG_INF("XSCOM Chip ID = 0x%X",l_xscomChipInfo.chipId); + } + + } + } + else + { + assert(iv_initialized); + } + + return; + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::_configureTargetPool +//****************************************************************************** + +void TargetService::_configureTargetPool() +{ + #define TARG_FN "_configureTargetPool(...)" + + TARG_ENTER(); + + _maxTargets(); + + // iv_pPnor--> points to uint32_t* --> points to --> uint32_t, targets[] + // (uint32_t*)+1 --> points to ------------> targets[] + + iv_targets = + reinterpret_cast< Target(*)[] > ( + *(reinterpret_cast<uint32_t**>( + const_cast<void*>(iv_pPnor))) + 1); + TARG_EXIT(); + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::_maxTargets +//****************************************************************************** + +uint32_t TargetService::_maxTargets() +{ + #define TARG_FN "_maxTargets(...)" + + // Target count found by following the pointer pointed to by the iv_pPnor + // pointer. + iv_maxTargets = *(*(reinterpret_cast<const uint32_t * const *>(iv_pPnor))); + return iv_maxTargets; + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::_getInwards +//****************************************************************************** + +void TargetService::_getInwards( + const ATTRIBUTE_ID i_attr, + const RECURSION_LEVEL i_recursionLevel, + EntityPath i_entityPath, + TargetHandleList& o_list) const +{ + #define TARG_FN "_getInwards(...)" + + while (i_entityPath.size() > 1) + { + i_entityPath.removeLast(); + for (uint32_t i = 0; i < iv_maxTargets; ++i) + { + EntityPath l_candidatePath; + bool l_candidateFound = tryGetPath(i_attr, &(*iv_targets)[i], + l_candidatePath); + if (l_candidateFound && (l_candidatePath == i_entityPath)) + { + o_list.push_back(&(*iv_targets)[i]); + break; + } + } + + if (i_recursionLevel == IMMEDIATE) + { + break; + } + } + + #undef TARG_FN +} + +//****************************************************************************** +// TargetService::_getOutwards +//****************************************************************************** + +void TargetService::_getOutwards( + const ATTRIBUTE_ID i_attr, + const RECURSION_LEVEL i_recursionLevel, + EntityPath i_entityPath, + TargetHandleList& o_list) const +{ + #define TARG_FN "_getOutwards()...)" + + do { + + // If at max depth (a leaf path element), no children possible + if (i_entityPath.size() >= EntityPath::MAX_PATH_ELEMENTS) + { + break; + } + + // Find the children (immediate, or all), depending on recursion level + for (uint32_t i = 0; i < iv_maxTargets; ++i) + { + EntityPath l_candidatePath; + bool l_candidateFound = tryGetPath(i_attr, &(*iv_targets)[i], + l_candidatePath); + if (l_candidateFound) + { + if ( ( (i_recursionLevel == IMMEDIATE) + && (l_candidatePath.size() == i_entityPath.size() + 1)) + || ( (i_recursionLevel == ALL) + && (l_candidatePath.size() > i_entityPath.size()))) + { + if (i_entityPath.equals(l_candidatePath,i_entityPath.size())) + { + o_list.push_back(&(*iv_targets)[i]); + } + } + } + } + + } while (0); + + #undef TARG_FN +} + +#undef TARG_CLASS + +#undef TARG_NAMESPACE + +} // End namespace TARGETING |