summaryrefslogtreecommitdiffstats
path: root/src/usr/targeting/targplatutil.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/targeting/targplatutil.C')
-rw-r--r--src/usr/targeting/targplatutil.C184
1 files changed, 182 insertions, 2 deletions
diff --git a/src/usr/targeting/targplatutil.C b/src/usr/targeting/targplatutil.C
index 704e3deed..a1b483473 100644
--- a/src/usr/targeting/targplatutil.C
+++ b/src/usr/targeting/targplatutil.C
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2013,2014 */
+/* Contributors Listed Below - COPYRIGHT 2013,2015 */
+/* [+] 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. */
@@ -39,13 +41,20 @@
#include <targeting/targplatutil.H>
#include <targeting/common/predicates/predicates.H>
#include <errl/errlmanager.H>
-
+#include <config.h>
+#include <algorithm>
namespace TARGETING
{
namespace UTIL
{
+#ifdef CONFIG_BMC_IPMI
+ uint32_t getIPMISensorNumber( const TARGETING::Target*& i_targ,
+ TARGETING::SENSOR_NAME i_name );
+#endif
+
+
#define TARG_NAMESPACE "TARGETING::UTIL"
#define TARG_CLASS ""
@@ -101,6 +110,177 @@ void getMasterNodeTarget(Target*& o_masterNodeTarget)
o_masterNodeTarget = masterNodeTarget;
}
+// return the sensor number from the passed in target
+uint32_t getSensorNumber( const TARGETING::Target* i_pTarget,
+ TARGETING::SENSOR_NAME i_name )
+{
+
+#ifdef CONFIG_BMC_IPMI
+ // get the IPMI sensor number from the array, these are unique for each
+ // sensor + sensor owner in an IPMI system
+ return getIPMISensorNumber( i_pTarget, i_name );
+#else
+ // pass back the HUID - this will be the sensor number for non ipmi based
+ // systems
+ return get_huid( i_pTarget );
+
+#endif
+
+}
+
+// convert sensor number to a target
+TARGETING::Target * getSensorTarget(const uint32_t i_sensorNumber )
+{
+
+#ifdef CONFIG_BMC_IPMI
+ return TARGETING::UTIL::getTargetFromIPMISensor( i_sensorNumber );
+#else
+ // in non ipmi systems huid == sensor number
+ return Target::getTargetFromHuid( i_sensorNumber );
+#endif
+
+}
+
+// predicate for binary search of ipmi sensors array.
+// given an array[][2] compare the sensor name, located in the first column,
+// to the passed in key value
+static inline bool name_predicate( uint16_t (&a)[2], uint16_t key )
+{
+ return a[TARGETING::IPMI_SENSOR_ARRAY_NAME_OFFSET] < key;
+};
+
+#ifdef CONFIG_BMC_IPMI
+// given a target and sensor name, return the IPMI sensor number
+// from the IPMI_SENSORS attribute.
+uint32_t getIPMISensorNumber( const TARGETING::Target*& i_targ,
+ TARGETING::SENSOR_NAME i_name )
+{
+ // $TODO RTC:123035 investigate pre-populating some info if we end up
+ // doing this multiple times per sensor
+ //
+ // Helper function to search the sensor data for the correct sensor number
+ // based on the sensor name.
+ //
+ uint8_t l_sensor_number = INVALID_IPMI_SENSOR;
+
+ const TARGETING::Target * l_targ = i_targ;
+
+ if( i_targ == NULL )
+ {
+ TARGETING::Target * sys;
+ // use the system target
+ TARGETING::targetService().getTopLevelTarget(sys);
+
+ // die if there is no system target
+ assert(sys);
+
+ l_targ = sys;
+ }
+
+ TARGETING::AttributeTraits<TARGETING::ATTR_IPMI_SENSORS>::Type l_sensors;
+
+ // if there is no sensor attribute, we will return INVALID_IPMI_SENSOR(0xFF)
+ if( l_targ->tryGetAttr<TARGETING::ATTR_IPMI_SENSORS>(l_sensors) )
+ {
+ // get the number of rows by dividing the total size by the size of
+ // the first row
+ uint16_t array_rows = (sizeof(l_sensors)/sizeof(l_sensors[0]));
+
+ // create an iterator pointing to the first element of the array
+ uint16_t (*begin)[2] = &l_sensors[0];
+
+ // using the number entries as the index into the array will set the
+ // end iterator to the correct position or one entry past the last
+ // element of the array
+ uint16_t (*end)[2] = &l_sensors[array_rows];
+
+ uint16_t (*ptr)[2] =
+ std::lower_bound(begin, end, i_name, &name_predicate);
+
+ // we have not reached the end of the array and the iterator
+ // returned from lower_bound is pointing to an entry which equals
+ // the one we are searching for.
+ if( ( ptr != end ) &&
+ ( (*ptr)[TARGETING::IPMI_SENSOR_ARRAY_NAME_OFFSET] == i_name ) )
+ {
+ // found it
+ l_sensor_number =
+ (*ptr)[TARGETING::IPMI_SENSOR_ARRAY_NUMBER_OFFSET];
+
+ }
+ }
+ return l_sensor_number;
+}
+
+class number_predicate
+{
+ public:
+
+ number_predicate( const uint32_t number )
+ :iv_number(number)
+ {};
+
+ bool operator()( const uint16_t (&a)[2] ) const
+ {
+ return a[TARGETING::IPMI_SENSOR_ARRAY_NUMBER_OFFSET] == iv_number;
+ }
+
+ private:
+ uint32_t iv_number;
+};
+
+//******************************************************************************
+// getTargetFromIPMISensor()
+//******************************************************************************
+Target * getTargetFromIPMISensor( uint32_t i_sensorNumber )
+{
+
+ // if the size of HUID is made larger than a uint32_t the compile will fail
+ CPPASSERT((sizeof(TARGETING::ATTR_HUID_type) > sizeof(i_sensorNumber)));
+
+ // 1. find targets with IPMI_SENSOR attribute which has sensor numbers
+ // 2. search array for the sensor number (not sorted on this column)
+ // 3. return the target
+
+ TARGETING::Target * l_target = NULL;
+
+ TARGETING::AttributeTraits<TARGETING::ATTR_IPMI_SENSORS>::Type l_sensors;
+
+ for (TargetIterator itr = TARGETING::targetService().begin();
+ itr != TARGETING::targetService().end(); ++itr)
+ {
+ // if there is a sensors attribute, see if our number is in it
+ if( (*itr)->tryGetAttr<TARGETING::ATTR_IPMI_SENSORS>(l_sensors))
+ {
+ uint16_t array_rows = (sizeof(l_sensors)/sizeof(l_sensors[0]));
+
+ // create an iterator pointing to the first sensor number of the
+ // array.
+ uint16_t (*begin)[2] =
+ &l_sensors[TARGETING::IPMI_SENSOR_ARRAY_NAME_OFFSET];
+
+ // using the number entries as the index into the array will set the
+ // end iterator to the correct position or one entry past the last
+ // element of the array
+ uint16_t (*end)[2] = &l_sensors[array_rows];
+
+ uint16_t (*ptr)[2] = std::find_if(begin, end,
+ number_predicate(i_sensorNumber));
+
+ if ( ptr != end )
+ {
+ // found it
+ l_target = *itr;
+ break;
+ }
+ }
+ }
+ return l_target;
+}
+
+
+#endif
+
#undef TARG_NAMESPACE
#undef TARG_CLASS
OpenPOWER on IntegriCloud