/*
* ipmi_mc_vendor.cpp
*
* Copyright (c) 2004 by FORCE Computers
* Copyright (c) 2005-2006 by ESO Technologies.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This
* file and program are licensed under a BSD style license. See
* the Copying file included with the OpenHPI distribution for
* full licensing terms.
*
* Authors:
* Thomas Kanngieser <thomas.kanngieser@fci.com>
* Pierre Sangouard <psangouard@eso-tech.com>
* Andy Cress <arcress@user.sourceforge.net>
*/
#include <assert.h>
extern "C" {
#include "SaHpiAtca.h"
}
#include "ipmi_mc_vendor.h"
#include "ipmi_mc_vendor_force.h"
#include "ipmi_mc_vendor_intel.h"
#include "ipmi_mc_vendor_sun.h"
#include "ipmi_mc_vendor_fix_sdr.h"
#include "ipmi_domain.h"
#include "ipmi_control_fan.h"
#include "ipmi_control_atca_led.h"
#include "ipmi_watchdog.h"
cIpmiMcVendorFactory *cIpmiMcVendorFactory::m_factory = 0;
static int use_count = 0;
static cThreadLock lock;
cIpmiMcVendorFactory::cIpmiMcVendorFactory()
: m_mc_vendors( 0 ), m_default( new cIpmiMcVendor( 0, 0, "default MC vendor" ) )
{
}
cIpmiMcVendorFactory::~cIpmiMcVendorFactory()
{
while( m_mc_vendors )
{
cIpmiMcVendor *mv = (cIpmiMcVendor *)m_mc_vendors->data;
m_mc_vendors = g_list_remove( m_mc_vendors, mv );
delete mv;
}
if ( m_default )
delete m_default;
}
void
cIpmiMcVendorFactory::InitFactory()
{
lock.Lock();
if ( m_factory == 0 )
{
m_factory = new cIpmiMcVendorFactory;
// Force ShMC specific stuff
m_factory->Register( new cIpmiMcVendorForceShMc( 0x1011 ) );
m_factory->Register( new cIpmiMcVendorForceShMc( 0x1080 ) );
// Intel BMC specific stuff
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x000C ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x001B ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0022 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0026 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0028 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0029 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0100 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x4311 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0811 ) );
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0900 ) ); /*HSC*/
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0911 ) ); /*HSC*/
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x0A0C ) ); /*HSC*/
m_factory->Register( new cIpmiMcVendorIntelBmc( 0x003E ) );
for (int i = 0x0048; i <= 0x005D; i++)
m_factory->Register( new cIpmiMcVendorIntelBmc( i ) ); /*Romley*/
// Sun BMC specific stuff
m_factory->Register( new cIpmiMcVendorSunBmc( 0x4701 ) );
// Enabling this code will fix badly formed SDR
// found on various boards tested with the plugin
// It would be much better if vendors fixed those
// This is why this code is not enabled by default
#ifdef FIX_BAD_SDR
for ( int i = 0; mc_patch[i].sdr_patch != NULL; i++ )
{
m_factory->Register( new cIpmiMcVendorFixSdr( mc_patch[i].manufacturer_id,
mc_patch[i].product_id ) );
}
#endif
}
use_count++;
lock.Unlock();
}
void
cIpmiMcVendorFactory::CleanupFactory()
{
lock.Lock();
use_count--;
assert( use_count >= 0 );
if ( use_count == 0 )
{
delete m_factory;
m_factory = 0;
}
lock.Unlock();
}
bool
cIpmiMcVendorFactory::Register( cIpmiMcVendor *mv )
{
if ( Find( mv->m_manufacturer_id, mv->m_product_id ) )
{
assert( 0 );
return false;
}
m_mc_vendors = g_list_append( m_mc_vendors, mv );
return true;
}
bool
cIpmiMcVendorFactory::Unregister( unsigned int manufacturer_id,
unsigned int product_id )
{
cIpmiMcVendor *mv = Find( manufacturer_id, product_id );
if ( !mv )
return false;
m_mc_vendors = g_list_remove( m_mc_vendors, mv );
return true;
}
cIpmiMcVendor *
cIpmiMcVendorFactory::Find( unsigned int manufacturer_id,
unsigned int product_id )
{
GList *list = m_mc_vendors;
while( list )
{
cIpmiMcVendor *mv = (cIpmiMcVendor *)list->data;
if ( mv->m_manufacturer_id == manufacturer_id
&& mv->m_product_id == product_id )
return mv;
list = g_list_next( list );
}
return 0;
}
cIpmiMcVendor *
cIpmiMcVendorFactory::Get( unsigned int manufacturer_id,
unsigned int product_id )
{
cIpmiMcVendor *mv = Find( manufacturer_id, product_id );
if ( mv )
return mv;
return m_default;
}
SaHpiEntityLocationT cIpmiMcVendor::m_unique_instance = 256;
cIpmiMcVendor::cIpmiMcVendor( unsigned int manufacturer_id,
unsigned int product_id,
const char *desc )
: m_manufacturer_id( manufacturer_id ),
m_product_id( product_id )
{
strncpy( m_description, desc, sizeof(m_description) - 1 );
m_description[sizeof(m_description) - 1] = 0;
}
cIpmiMcVendor::~cIpmiMcVendor()
{
}
bool
cIpmiMcVendor::InitMc( cIpmiMc * /*mc*/, const cIpmiMsg & /*devid*/ )
{
return true;
}
void
cIpmiMcVendor::CleanupMc( cIpmiMc * /*mc*/ )
{
}
bool
cIpmiMcVendor::ProcessSdr( cIpmiDomain * /*domain*/, cIpmiMc * /*mc*/, cIpmiSdrs * /*sdrs*/ )
{
return true;
}
bool
cIpmiMcVendor::ProcessFru( cIpmiInventory * /*inv*/, cIpmiMc * /*mc*/,
unsigned int /*sa*/, SaHpiEntityTypeT /*type*/)
{
return true;
}
bool
cIpmiMcVendor::CreateRdrs( cIpmiDomain *domain, cIpmiMc *source_mc, cIpmiSdrs *sdrs )
{
if ( CreateResources( domain, source_mc, sdrs ) == false )
return false;
if ( CreateSensors( domain, source_mc, sdrs ) == false )
return false;
if ( CreateControls( domain, source_mc, sdrs ) == false )
return false;
if ( CreateSels( domain, source_mc, sdrs ) == false )
return false;
if ( CreateInvs( domain, source_mc, sdrs ) == false )
return false;
if ( CreateWatchdogs( domain, source_mc ) == false )
return false;
return true;
}
bool
cIpmiMcVendor::CreateResources( cIpmiDomain *domain, cIpmiMc *source_mc, cIpmiSdrs *sdrs )
{
assert( source_mc );
bool found = false;
// Make sure that there is a mcdlr
for( unsigned int i = 0; i < sdrs->NumSdrs(); i++ )
{
cIpmiSdr *sdr = sdrs->Sdr( i );
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord )
{
found = true;
break;
}
}
// there must be a mcdlr !
if ( found == false )
{
stdlog << "WARNING : MC " << source_mc->GetAddress() << " NO MC Device Locator Record\n";
return false;
}
// create one resource per mcdlr and fdlr
for( unsigned int i = 0; i < sdrs->NumSdrs(); i++ )
{
cIpmiSdr *sdr = sdrs->Sdr( i );
cIpmiAddr addr;
unsigned int fru_id;
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord )
{
addr.m_slave_addr = sdr->m_data[5];
addr.m_channel = sdr->m_data[6] & 0xf;
fru_id = 0;
}
else if ( sdr->m_type == eSdrTypeFruDeviceLocatorRecord )
{
// We care only about logical FRUs
if ( (sdr->m_data[7] & 0x80) == 0 )
continue;
addr.m_slave_addr = sdr->m_data[5];
addr.m_channel = (sdr->m_data[8] >> 4) & 0xf;
fru_id = sdr->m_data[6];
}
else
continue;
stdlog << "CreateResources FRU " << fru_id << "\n";
if ( addr.m_slave_addr != source_mc->GetAddress() )
stdlog << "WARNING : SDR slave address " << addr.m_slave_addr << " NOT equal to MC slave address " << (unsigned char)source_mc->GetAddress() << "\n";
if ( addr.m_channel != source_mc->GetChannel() )
stdlog << "WARNING : SDR channel " << addr.m_channel << " NOT equal to MC channel " << source_mc->GetChannel() << "\n";
if ( FindOrCreateResource( domain, source_mc, fru_id, sdr, sdrs ) == NULL ) {
return false;
}
}
return true;
}
cIpmiResource *
cIpmiMcVendor::FindResource( cIpmiDomain *domain, cIpmiMc *mc,
unsigned int fru_id,
SaHpiEntityTypeT type,
SaHpiEntityLocationT instance,
cIpmiSdrs *sdrs )
{
assert( mc );
stdlog << "FindResource mc " << mc->GetAddress() << " FRU " << fru_id << " type " << type << " instance " << instance << "\n";
cIpmiEntityPath ep = CreateEntityPath( domain, mc->GetAddress(), fru_id,
type, instance, sdrs );
stdlog << "Looking for resource: " << ep << ".\n";
cIpmiResource *res = mc->FindResource( ep );
return res;
}
cIpmiResource *
cIpmiMcVendor::FindResource( cIpmiDomain *domain, cIpmiMc *mc,
unsigned int fru_id,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
assert( mc );
SaHpiEntityTypeT type = SAHPI_ENT_UNKNOWN;
SaHpiEntityLocationT instance = GetUniqueInstance();
unsigned char snum = 0;
if ( sdr )
{
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord
|| sdr->m_type == eSdrTypeFruDeviceLocatorRecord )
{
type = (SaHpiEntityTypeT)sdr->m_data[12];
instance = (SaHpiEntityLocationT)sdr->m_data[13];
snum = 0;
}
else if ( sdr->m_type == eSdrTypeFullSensorRecord )
{
type = (SaHpiEntityTypeT)sdr->m_data[8];
instance = (SaHpiEntityLocationT)sdr->m_data[9];
snum = sdr->m_data[7];
}
else
assert( 0 );
}
stdlog << "FindResource mc " << mc->GetAddress() << " FRU " << fru_id << " type " << type << " instance " << instance << " snum " << snum << "\n";
cIpmiEntityPath ep = CreateEntityPath( domain, mc->GetAddress(), fru_id,
type, instance, sdrs );
stdlog << "Looking for resource: " << ep << ".\n";
cIpmiResource *res = mc->FindResource( ep );
return res;
}
cIpmiResource *
cIpmiMcVendor::FindOrCreateResource( cIpmiDomain *domain, cIpmiMc *mc,
unsigned int fru_id,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
assert( mc );
SaHpiEntityTypeT type = SAHPI_ENT_UNKNOWN;
SaHpiEntityLocationT instance = GetUniqueInstance();
if ( sdr )
{
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord
|| sdr->m_type == eSdrTypeFruDeviceLocatorRecord )
{
type = (SaHpiEntityTypeT)sdr->m_data[12];
instance = (SaHpiEntityLocationT)sdr->m_data[13];
}
else if ( sdr->m_type == eSdrTypeFullSensorRecord )
{
type = (SaHpiEntityTypeT)sdr->m_data[8];
instance = (SaHpiEntityLocationT)sdr->m_data[9];
}
else
assert( 0 );
}
stdlog << "FindOrCreateResource mc " << mc->GetAddress() << " FRU " << fru_id << " type " << type << " instance " << instance << "\n";
cIpmiEntityPath ep = CreateEntityPath( domain, mc->GetAddress(), fru_id,
type, instance, sdrs );
stdlog << "Looking for resource: " << ep << ".\n";
cIpmiResource *res = mc->FindResource( ep );
if ( res )
return res;
return CreateResource( domain, mc, fru_id, sdr, sdrs );
}
cIpmiResource *
cIpmiMcVendor::CreateResource( cIpmiDomain *domain, cIpmiMc *mc,
unsigned int fru_id, cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
// create a new resource
cIpmiResource *res = new cIpmiResource( mc, fru_id );
SaHpiEntityTypeT type = SAHPI_ENT_UNKNOWN;
SaHpiEntityLocationT instance = GetUniqueInstance();
if ( sdr )
{
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord
|| sdr->m_type == eSdrTypeFruDeviceLocatorRecord )
{
type = (SaHpiEntityTypeT)sdr->m_data[12];
instance = (SaHpiEntityLocationT)sdr->m_data[13];
}
else if ( sdr->m_type == eSdrTypeFullSensorRecord )
{
type = (SaHpiEntityTypeT)sdr->m_data[8];
instance = (SaHpiEntityLocationT)sdr->m_data[9];
}
else
assert( 0 );
}
res->EntityPath() = CreateEntityPath( domain, mc->GetAddress(), fru_id,
type, instance, sdrs );
if ( sdr
&& ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord
|| sdr->m_type == eSdrTypeFruDeviceLocatorRecord ) )
{
stdlog << "Adding FRU " << fru_id << " ";
// set mc id string
res->ResourceTag().SetIpmi( sdr->m_data + 15 );
res->Oem() = sdr->m_data[14];
res->IsFru() = true;
}
// create rpt entry
stdlog << "adding resource: " << res->EntityPath() << ".\n";
// add res to mc
mc->AddResource( res );
return res;
}
// TODO:
// Handling of entity association records.
// This is the reason for the parameter sdrs.
cIpmiEntityPath
cIpmiMcVendor::CreateEntityPath( cIpmiDomain *domain, unsigned int mc_addr, unsigned int fru_id,
SaHpiEntityTypeT type,
SaHpiEntityLocationT instance, cIpmiSdrs * /*sdrs*/ )
{
// find fru info
cIpmiFruInfo *fi = domain->FindFruInfo( mc_addr, fru_id );
if ( ( fi == NULL ) && ( fru_id != 0) )
{
fi = domain->NewFruInfo( mc_addr, fru_id );
}
cIpmiEntityPath bottom;
// clear bit 7
instance &= 0x7f;
if ( instance >= 0x60 )
instance -= 0x60;
switch ((tIpmiEntityId)type)
{
default:
break;
case eIpmiEntityIdPicMgFrontBoard:
type = SaHpiEntityTypeT(ATCAHPI_ENT_PICMG_FRONT_BLADE);
break;
case eIpmiEntityIdPicMgRearTransitionModule:
type = SAHPI_ENT_BACK_PANEL_BOARD;
break;
case eIpmiEntityIdPicMgAdvancedMcModule:
type = SaHpiEntityTypeT(ATCAHPI_ENT_AMC);
break;
case eIpmiEntityIdPicMgMicroTcaCarrierHub:
type = SAHPI_ENT_SWITCH_BLADE;
break;
case eIpmiEntityIdPicmgShelfManager:
type = SAHPI_ENT_SHELF_MANAGER;
break;
case eIpmiEntityIdPicmgFiltrationUnit:
type = SaHpiEntityTypeT(ATCAHPI_ENT_FILTRATION_UNIT);
break;
case eIpmiEntityIdPicmgShelfFruInformation:
type = SaHpiEntityTypeT(ATCAHPI_ENT_SHELF_FRU_DEVICE);
break;
case eIpmiEntityIdPicmgAlarmPanel:
type = SAHPI_ENT_ALARM_MANAGER;
break;
}
bottom.SetEntry( 0, type, instance );
bottom.AppendRoot( 1 );
cIpmiEntityPath top = domain->EntityRoot();
if ( fi )
return fi->CreateEntityPath( top, bottom );
// fru info not found => use default entity path
cIpmiEntityPath ep = bottom;
ep += top;
return ep;
}
static cIpmiSensor *
FindSensor( GList *list, unsigned char sa, unsigned int num, unsigned char lun )
{
for( ; list; list = g_list_next( list ) )
{
cIpmiSensor *sensor = (cIpmiSensor *)list->data;
if ( sensor->Num() == num
&& sensor->Sa() == sa
&& sensor->Lun() == lun )
return sensor;
}
return 0;
}
bool
cIpmiMcVendor::CreateSensors( cIpmiDomain *domain, cIpmiMc *source_mc, cIpmiSdrs *sdrs )
{
GList *old_sensors = domain->GetSdrSensors( source_mc );
GList *new_sensors = 0;
GList *sensors = GetSensorsFromSdrs( domain, source_mc, sdrs );
unsigned int parent_fru_id;
SaHpiEntityTypeT type, parent_type;
SaHpiEntityLocationT instance, parent_instance;
while( sensors )
{
cIpmiSensor *sensor = (cIpmiSensor *)sensors->data;
sensors = g_list_remove( sensors, sensor );
cIpmiSensor *old_sensor = FindSensor( old_sensors, sensor->Sa(), sensor->Num(), sensor->Lun() );
if ( old_sensor && sensor->Cmp( *old_sensor ) )
{
// sensor already there, use old one
delete sensor;
old_sensor->HandleNew( domain );
old_sensors = g_list_remove( old_sensors, old_sensor );
new_sensors = g_list_append( new_sensors, old_sensor );
continue;
}
if ( old_sensor )
{
// remove the old sensor
old_sensors = g_list_remove( old_sensors, old_sensor );
old_sensor->Resource()->RemRdr( old_sensor );
delete old_sensor;
}
// check if the sensor is defined twice
if ( FindSensor( new_sensors, sensor->Sa(), sensor->Num(), sensor->Lun() ) )
{
stdlog << "sensor " << sensor->IdString() << " defined twice in SDR !\n";
delete sensor;
continue;
}
cIpmiSdr *sdr = sensor->GetSdr();
if ( sdr == 0 )
{
sdr = sdrs->FindSdr( sensor->Mc() );
if (!sdr)
{
delete sensor;
continue;
}
}
type = (SaHpiEntityTypeT)sdr->m_data[8];
instance = (SaHpiEntityLocationT)sdr->m_data[9];
parent_fru_id = sdrs->FindParentFru( type,
instance,
parent_type,
parent_instance
);
cIpmiResource *res = FindResource( domain, sensor->Mc(),
parent_fru_id, parent_type, parent_instance,
sdrs );
if (!res )
{
delete sensor;
continue;
}
new_sensors = g_list_append( new_sensors, sensor );
sensor->HandleNew( domain );
res->AddRdr( sensor );
}
// destry old sensors
while( old_sensors )
{
cIpmiSensor *sensor = (cIpmiSensor *)old_sensors->data;
old_sensors = g_list_remove( old_sensors, sensor );
sensor->Resource()->RemRdr( sensor );
delete sensor;
}
// set new sdr sensors
domain->SetSdrSensors( source_mc, new_sensors );
return true;
}
GList *
cIpmiMcVendor::GetSensorsFromSdrs( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdrs *sdrs )
{
GList *sensors = 0;
// create a list of full sensor records
for( unsigned int i = 0; i < sdrs->NumSdrs(); i++ )
{
cIpmiSdr *sdr = sdrs->Sdr( i );
if ( sdr->m_type != eSdrTypeFullSensorRecord )
continue;
GList *l = CreateSensorFromFullSensorRecord( domain, source_mc, sdr, sdrs );
if ( l )
sensors = g_list_concat( sensors, l );
}
return sensors;
}
GList *
cIpmiMcVendor::CreateSensorFromFullSensorRecord( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
GList *list = 0;
tIpmiSensorType sensor_type = (tIpmiSensorType)sdr->m_data[12];
if ( sensor_type == eIpmiSensorTypeAtcaHotSwap )
list = CreateSensorHotswap( domain, source_mc, sdr, sdrs );
else
{
tIpmiEventReadingType reading_type = (tIpmiEventReadingType)sdr->m_data[13];
if ( reading_type == eIpmiEventReadingTypeThreshold )
list = CreateSensorThreshold( domain, source_mc, sdr, sdrs );
else
list = CreateSensorDefault( domain, source_mc, sdr, sdrs );
}
for( GList *l = list; l; l = g_list_next( l ) )
{
cIpmiSensor *s = (cIpmiSensor *)l->data;
if ( s->GetSdr() == 0 )
s->SetSdr( sdr );
}
return list;
}
GList *
cIpmiMcVendor::CreateSensorHotswap( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
cIpmiMc *mc = source_mc; // FindMcBySdr( domain, sdr );
assert( mc );
cIpmiSensorHotswap *hs = new cIpmiSensorHotswap( mc );
hs->SourceMc() = source_mc;
if ( !hs->GetDataFromSdr( mc, sdr ) )
{
delete hs;
return 0;
}
CreateSensorEntityPath( domain, hs, source_mc, sdr, sdrs );
return g_list_append( 0, hs );
}
GList *
cIpmiMcVendor::CreateSensorThreshold( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
cIpmiMc *mc = source_mc; // FindMcBySdr( domain, sdr );
assert( mc );
cIpmiSensorThreshold *ts = new cIpmiSensorThreshold( mc );
ts->SourceMc() = source_mc;
if ( !ts->GetDataFromSdr( mc, sdr ) )
{
delete ts;
return 0;
}
CreateSensorEntityPath( domain, ts, source_mc, sdr, sdrs );
return g_list_append( 0, ts );
}
GList *
cIpmiMcVendor::CreateSensorDiscrete( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
cIpmiMc *mc = source_mc; //FindMcBySdr( domain, sdr );
assert( mc );
cIpmiSensorDiscrete *ds = new cIpmiSensorDiscrete( mc );
ds->SourceMc() = source_mc;
if ( !ds->GetDataFromSdr( mc, sdr ) )
{
delete ds;
return 0;
}
CreateSensorEntityPath( domain, ds, source_mc, sdr, sdrs );
return g_list_append( 0, ds );
}
GList *
cIpmiMcVendor::CreateSensorDefault( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
return CreateSensorDiscrete( domain, source_mc, sdr, sdrs );
}
void
cIpmiMcVendor::CreateSensorEntityPath( cIpmiDomain *domain, cIpmiSensor *s,
cIpmiMc *source_mc,
cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
SaHpiEntityTypeT type, parent_type;
SaHpiEntityLocationT instance, parent_instance;
unsigned int parent_fru_id;
if ( sdr )
{
type = (SaHpiEntityTypeT)sdr->m_data[8];
instance = (SaHpiEntityLocationT)sdr->m_data[9];
}
else
{
type = SAHPI_ENT_UNKNOWN;
instance = GetUniqueInstance();
}
parent_fru_id = sdrs->FindParentFru( type,
instance,
parent_type,
parent_instance
);
stdlog << "CreateSensorEntityPath mc " << source_mc->GetAddress() << " FRU " << parent_fru_id << " type " << type << " instance " << instance << "\n";
cIpmiEntityPath parent_ep = CreateEntityPath( domain, source_mc->GetAddress(), parent_fru_id,
parent_type, parent_instance, sdrs );
if ((type != parent_type)
|| (instance != parent_instance))
{
// clear bit 7
instance &= 0x7f;
if ( instance >= 0x60 )
instance -= 0x60;
cIpmiEntityPath child_ep;
child_ep.SetEntry( 0, type, instance );
child_ep.AppendRoot( 1 );
child_ep += parent_ep;
s->EntityPath() = child_ep;
}
else
{
s->EntityPath() = parent_ep;
}
}
cIpmiMc *
cIpmiMcVendor::FindMcBySdr( cIpmiDomain *domain, cIpmiSdr *sdr )
{
unsigned char chan = 0;
int findok = 0;
switch( sdr->m_type )
{
case eSdrTypeCompactSensorRecord:
findok = 1; break;
case eSdrTypeFullSensorRecord:
findok = 1; break;
case eSdrTypeMcDeviceLocatorRecord:
chan = sdr->m_data[6] & 0xf;
findok = 1; break;
case eSdrTypeFruDeviceLocatorRecord:
chan = (sdr->m_data[8] >> 4) & 0xf;
findok = 1; break;
default:
break;
}
if (findok)
{
cIpmiAddr addr( eIpmiAddrTypeIpmb, chan, 0, sdr->m_data[5] );
return domain->FindMcByAddr( addr );
}
return 0;
}
bool
cIpmiMcVendor::CreateControls( cIpmiDomain *domain, cIpmiMc *source_mc,
cIpmiSdrs *sdrs )
{
// controls only for device SDR
if ( source_mc == 0 )
return true;
if ( source_mc->IsTcaMc() )
{
return CreateControlsAtca( domain, source_mc, sdrs );
}
return true;
}
bool
cIpmiMcVendor::CreateWatchdogs( cIpmiDomain *domain, cIpmiMc *mc )
{
cIpmiResource *res;
for ( int i = 0; i < mc->NumResources(); i++ )
{
res = mc->GetResource ( i );
if ( res == 0 )
continue;
stdlog << "CreateWatchdogs: addr " << mc->GetAddress() << " FruId " <<
res->FruId() << "\n";
if (res->FruId() == 0)
{
cIpmiMsg msg( eIpmiNetfnApp, eIpmiCmdGetWatchdogTimer );
cIpmiMsg rsp;
if (mc->IsRmsBoard() &&
res->EntityPath().GetEntryType(0) != SAHPI_ENT_SYSTEM_BOARD)
continue;
/* Do an IPMI GetWatchdogTimer command to verify this feature. */
msg.m_data_len = 0;
SaErrorT rv = res->SendCommand( msg, rsp );
if (rv != 0 || rsp.m_data[0] != 0) {
stdlog << "CreateWatchdogs: IPMI error " << rv << " ccode " <<
rsp.m_data[0] << "\n";
continue;
}
/* Everything is valid, create the Watchdog RDR */
stdlog << "CreateWatchdogs Resource type " << res->EntityPath().GetEntryType(0) << " instance " << res->EntityPath().GetEntryInstance(0) << "\n";
cIpmiRdr *wd = new cIpmiWatchdog( mc, SAHPI_DEFAULT_WATCHDOG_NUM, 0 );
wd->EntityPath() = res->EntityPath();
wd->IdString().SetAscii( "Watchdog", SAHPI_TL_TYPE_TEXT, SAHPI_LANG_ENGLISH );
res->AddRdr( wd );
}
}
return true;
}
bool
cIpmiMcVendor::CreateControlsAtca( cIpmiDomain *domain, cIpmiMc *mc, cIpmiSdrs *sdrs )
{
cIpmiResource *res;
for ( int i = 0; i < mc->NumResources(); i++ )
{
res = mc->GetResource ( i );
if ( res == 0 )
continue;
if ( res->IsFru() )
{
stdlog << "CreateControlsAtca Resource type " << res->EntityPath().GetEntryType(0) << " instance " << res->EntityPath().GetEntryInstance(0) << " FRU " << res->FruId() << "\n";
CreateControlAtcaLed( domain, res, sdrs );
CreateControlAtcaFan( domain, res, sdrs );
}
}
return true;
}
bool
cIpmiMcVendor::CreateControlAtcaLed( cIpmiDomain *domain, cIpmiResource *res,
cIpmiSdrs *sdrs )
{
cIpmiMsg msg( eIpmiNetfnPicmg, eIpmiCmdGetFruLedProperties );
msg.m_data[0] = dIpmiPicMgId;
msg.m_data[1] = res->FruId();
msg.m_data_len = 2;
cIpmiMsg rsp;
SaErrorT rv = res->SendCommand( msg, rsp );
if ( rv != SA_OK
|| rsp.m_data_len < 4
|| rsp.m_data[0] != eIpmiCcOk
|| rsp.m_data[1] != dIpmiPicMgId )
{
stdlog << "cannot get FRU Led properties !\n";
return true;
}
unsigned char num_app_leds = rsp.m_data[3];
if ( num_app_leds > 0xFB )
num_app_leds = 0;
for (int i = 0; i <= (3+num_app_leds); i++)
{
if ( ( i <= 3 ) && ( rsp.m_data[2] & (1<<i) ) == 0 )
continue;
cIpmiMsg ledmsg( eIpmiNetfnPicmg, eIpmiCmdGetLedColorCapabilities );
ledmsg.m_data[0] = dIpmiPicMgId;
ledmsg.m_data[1] = res->FruId();
ledmsg.m_data[2] = i;
ledmsg.m_data_len = 3;
cIpmiMsg ledrsp;
rv = res->SendCommand( ledmsg, ledrsp );
if ( rv != SA_OK
|| ledrsp.m_data_len < 5
|| ledrsp.m_data[0] != eIpmiCcOk
|| ledrsp.m_data[1] != dIpmiPicMgId )
{
stdlog << "cannot get Led color capabilities !\n";
continue;
}
unsigned char led_color_capabilities = ledrsp.m_data[2] & 0x7E;
unsigned char led_default_local_color = ledrsp.m_data[3];
unsigned char led_default_override_color = ledrsp.m_data[4];
ledmsg.m_cmd = eIpmiCmdGetFruLedState;
rv = res->SendCommand( ledmsg, ledrsp );
if ( rv != SA_OK
|| ledrsp.m_data_len < 6
|| ledrsp.m_data[0] != eIpmiCcOk
|| ledrsp.m_data[1] != dIpmiPicMgId )
{
continue;
}
if ( (ledrsp.m_data[2] & 0x01) == 0 )
led_default_local_color = 0;
cIpmiControlAtcaLed *l = new cIpmiControlAtcaLed( res->Mc(), ATCAHPI_CTRL_NUM_BLUE_LED+i,
led_color_capabilities,
led_default_local_color,
led_default_override_color );
l->EntityPath() = res->EntityPath();
char ledname[32];
if (i == 0)
snprintf (ledname, sizeof(ledname), "Blue LED");
else
snprintf (ledname, sizeof(ledname), "LED %d", i);
l->IdString().SetAscii( ledname, SAHPI_TL_TYPE_TEXT, SAHPI_LANG_ENGLISH );
res->AddRdr( l );
}
return true;
}
bool
cIpmiMcVendor::CreateControlAtcaFan( cIpmiDomain *domain, cIpmiResource *res,
cIpmiSdrs *sdrs )
{
cIpmiMsg msg( eIpmiNetfnPicmg, eIpmiCmdGetFanSpeedProperties );
msg.m_data[0] = dIpmiPicMgId;
msg.m_data[1] = res->FruId();
msg.m_data_len = 2;
cIpmiMsg rsp;
SaErrorT rv = res->SendCommand( msg, rsp );
if ( rv != SA_OK
|| rsp.m_data_len < 6
|| rsp.m_data[0] != eIpmiCcOk
|| rsp.m_data[1] != dIpmiPicMgId )
{
stdlog << "cannot get fan speed properties !\n";
return true;
}
unsigned int min = rsp.m_data[2];
unsigned int max = rsp.m_data[3];
unsigned int def = rsp.m_data[4];
bool auto_adj = rsp.m_data[5] & 0x80;
cIpmiControlFan *f = new cIpmiControlFan( res->Mc(), ATCAHPI_CTRL_NUM_FAN_SPEED,
min, max, def,
auto_adj );
f->EntityPath() = res->EntityPath();
f->IdString().SetAscii( "Fan Control", SAHPI_TL_TYPE_TEXT, SAHPI_LANG_ENGLISH );
res->AddRdr( f );
return true;
}
bool
cIpmiMcVendor::CreateInvs( cIpmiDomain *domain, cIpmiMc *source_mc, cIpmiSdrs *sdrs )
{
for( unsigned int i = 0; i < sdrs->NumSdrs(); i++ )
{
cIpmiSdr *sdr = sdrs->Sdr( i );
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord )
{
if ( (sdr->m_data[8] & 8) == 0 )
continue;
}
else if ( sdr->m_type != eSdrTypeFruDeviceLocatorRecord )
continue;
if ( CreateInv( domain, source_mc, sdr, sdrs ) == false )
return false;
}
return true;
}
bool
cIpmiMcVendor::CreateInv( cIpmiDomain *domain, cIpmiMc *mc, cIpmiSdr *sdr, cIpmiSdrs *sdrs )
{
unsigned int fru_id;
// unsigned int lun;
unsigned int sa = mc->GetAddress();
SaHpiEntityTypeT type;
if ( sdr->m_type == eSdrTypeMcDeviceLocatorRecord ) /*0x12*/
{
fru_id = 0;
// lun = 0;
sa = sdr->m_data[5];
type = (SaHpiEntityTypeT)sdr->m_data[12];
/* chan = sdr->m_data[6]; */
}
else if ( sdr->m_type == eSdrTypeGenericDeviceLocatorRecord ) /*0x10*/
{
if ( sdr->m_data[5] != 0)
sa = (sdr->m_data[5] >> 1); /*access addr*/
fru_id = (sdr->m_data[6] >> 1) & 0x7f; /*sa*/
// lun = (sdr->m_data[7] >> 3) & 0x03; /*lun*/
type = (SaHpiEntityTypeT)sdr->m_data[12];
/* chan = (sdr->m_data[7] >> 5) & 0x07;; */
}
else if ( sdr->m_type == eSdrTypeFruDeviceLocatorRecord ) /*0x11*/
{
fru_id = sdr->m_data[6];
// lun = (sdr->m_data[7] >> 3) & 3;
sa = sdr->m_data[5];
type = (SaHpiEntityTypeT)sdr->m_data[12];
/* chan = sdr->m_data[8]; */
}
else /* other/unknown sdr type */
{
stdlog << "mc.CreateInv, unknown m_type=" << sdr->m_type <<
", sdr[3]=" << sdr->m_data[3] << ", sdr[5]=" << sdr->m_data[5] <<
", sdr[6]=" << sdr->m_data[6] << "\n";
fru_id = sdr->m_data[6];
// lun = (sdr->m_data[7] >> 3) & 3;
type = SAHPI_ENT_UNKNOWN;
}
cIpmiMc *m = mc;
assert( m );
cIpmiResource *res = FindResource( domain, m, fru_id, sdr, sdrs );
if ( !res )
return true;
cIpmiInventory *inv = (cIpmiInventory *)res->FindRdr( m, SAHPI_INVENTORY_RDR, fru_id );
bool need_add = false;
if ( inv == 0 )
{
inv = new cIpmiInventory( m, fru_id );
inv->IdString().SetIpmi( sdr->m_data + 15 );
inv->Oem() = sdr->m_data[14];
inv->Resource() = res;
ProcessFru(inv, m, sa, type);
need_add = true;
}
SaErrorT rv = inv->Fetch();
if ( rv != SA_OK )
{
if ( need_add )
delete inv;
// Ignore FRU errors
return true;
}
inv->EntityPath() = res->EntityPath();
if ( !need_add )
return true;
res->AddRdr( inv );
return true;
}
bool
cIpmiMcVendor::CreateSels( cIpmiDomain *domain, cIpmiMc *source_mc, cIpmiSdrs *sdrs )
{
if ( source_mc == 0 )
return false;
if ( !source_mc->SelDeviceSupport() )
return true;
cIpmiSdr *mcdlr = sdrs->FindSdr( source_mc );
if ( mcdlr == 0 )
return true;
cIpmiResource *res = FindResource( domain, source_mc, 0, mcdlr, sdrs );
if ( !res )
return true;
// create hpi sel
stdlog << "adding SEL " << res->EntityPath() << "\n";
// sel capabilities
res->m_sel = true;
return true;
}