/*
*
* Copyright (c) 2003,2004 by FORCE Computers
* Copyright (c) 2005 by ESO Technologies.
*
* Note that this file is based on parts of OpenIPMI
* written by Corey Minyard <minyard@mvista.com>
* of MontaVista Software. Corey's code was helpful
* and many thanks go to him. He gave the permission
* to use this code in OpenHPI under BSD license.
*
* 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>
*/
#include <errno.h>
#include "ipmi.h"
#include "ipmi_utils.h"
cIpmiDomain::cIpmiDomain()
: m_con( 0 ), m_is_tca( false ), m_main_sdrs( 0 ),
m_sensors_in_main_sdr( 0 ),
m_major_version( 0 ), m_minor_version( 0 ), m_sdr_repository_support( false ),
m_si_mc( 0 ),
m_initial_discover( 0 ),
m_mc_poll_interval( dIpmiMcPollInterval ),
m_sel_rescan_interval( dIpmiSelQueryInterval ),
m_bmc_discovered( false )
{
cIpmiMcVendorFactory::InitFactory();
m_did = 0;
m_own_domain = false;
for( int i = 0; i < 256; i++ )
{
m_mc_thread[i] = 0;
m_atca_site_property[i].m_property = 0;
m_atca_site_property[i].m_max_side_id = 0;
m_atca_site_property[i].m_mc_type = 0;
}
// scan at least at dIpmiBmcSlaveAddr
NewFruInfo( dIpmiBmcSlaveAddr, 0, SAHPI_ENT_SHELF_MANAGER, 0,
eIpmiAtcaSiteTypeDedicatedShMc,
dIpmiMcThreadInitialDiscover
| dIpmiMcThreadPollDeadMc
| dIpmiMcThreadPollAliveMc );
// default site type properties
unsigned int prop = dIpmiMcThreadInitialDiscover
| dIpmiMcThreadCreateM0;
// atca board
SetAtcaSiteProperty( eIpmiAtcaSiteTypeAtcaBoard, prop, 32 );
// power
SetAtcaSiteProperty( eIpmiAtcaSiteTypePowerEntryModule, prop, 8 );
// shelf fru information
SetAtcaSiteProperty( eIpmiAtcaSiteTypeShelfFruInformation, prop, 4 );
// dedicated ShMc
SetAtcaSiteProperty( eIpmiAtcaSiteTypeDedicatedShMc, prop, 2 );
// fan tray
SetAtcaSiteProperty( eIpmiAtcaSiteTypeFanTray, prop, 8 );
// fan filter tray
SetAtcaSiteProperty( eIpmiAtcaSiteTypeFanFilterTray, prop, 8 );
// alarm
SetAtcaSiteProperty( eIpmiAtcaSiteTypeAlarm, prop, 8 );
// AdvancedMC Module
SetAtcaSiteProperty( eIpmiAtcaSiteTypeAdvancedMcModule, prop, 32 );
// PMC
SetAtcaSiteProperty( eIpmiAtcaSiteTypePMC, prop, 32 );
// rear transition module
SetAtcaSiteProperty( eIpmiAtcaSiteTypeRearTransitionModule, prop, 32 );
// MicroTca Carrier Hub
SetAtcaSiteProperty( eIpmiAtcaSiteTypeMicroTcaCarrierHub, prop, 8 );
// Power Module
SetAtcaSiteProperty( eIpmiAtcaSiteTypePowerModule, prop, 8 );
}
cIpmiDomain::~cIpmiDomain()
{
cIpmiMcVendorFactory::CleanupFactory();
}
bool
cIpmiDomain::Init( cIpmiCon *con )
{
if ( m_con != 0 )
{
stdlog << "IPMI Domain already initialized !\n";
return false;
}
m_con = con;
// create system interface
cIpmiAddr si( eIpmiAddrTypeSystemInterface);
m_si_mc = new cIpmiMc( this, si );
if ( m_si_mc == 0 )
{
stdlog << "cannot create system interface !\n";
return false;
}
// create main sdr
m_main_sdrs = new cIpmiSdrs( m_si_mc, false );
// send get device id to system interface
cIpmiMsg msg( eIpmiNetfnApp, eIpmiCmdGetDeviceId );
cIpmiMsg rsp;
SaErrorT rv = m_si_mc->SendCommand( msg, rsp );
if ( rv != SA_OK )
{
stdlog << "cannot send IPMI get device id to system interface: " << rv << ", " << strerror( rv ) << " !\n";
return false;
}
if ( rsp.m_data[0] != 0
|| rsp.m_data_len < 12 )
{
// At least the get device id has to work.
stdlog << "get device id fails " << rsp.m_data[0] << " !\n";
return false;
}
m_major_version = rsp.m_data[5] & 0xf;
m_minor_version = (rsp.m_data[5] >> 4) & 0xf;
m_sdr_repository_support = (rsp.m_data[6] & 0x02) == 0x02;
m_si_mc->SdrRepositorySupport() = m_sdr_repository_support;
if ( m_major_version < 1 )
{
// We only support 1.0 and greater.
stdlog << "ipmi version " << m_major_version << "."
<< m_minor_version << " not supported !\n";
return false;
}
// set vendor
unsigned int mid = rsp.m_data[7]
| (rsp.m_data[8] << 8)
| (rsp.m_data[9] << 16);
unsigned int pid = IpmiGetUint16( rsp.m_data + 10 );
cIpmiMcVendor *mv = cIpmiMcVendorFactory::GetFactory()->Get( mid, pid );
m_si_mc->SetVendor( mv );
// initialize system interface MC
if ( mv->InitMc( m_si_mc, rsp ) == false )
{
stdlog << "cannot initialize system interface !\n";
return false;
}
int num = m_max_outstanding;
if ( m_max_outstanding == 0 )
{
// Check the number of outstanding requests.
// This is fine tuning if the BMC/ShMc has
// a block transfer interface.
// If not supported use the defaults
// given in openhpi.conf.
msg.m_netfn = eIpmiNetfnApp;
msg.m_cmd = eIpmiCmdGetBtInterfaceCapabilities;
msg.m_data_len = 0;
rv = m_si_mc->SendCommand( msg, rsp, 0, 1 );
// ignore on error
if ( rv == SA_OK && rsp.m_data[0] == 0 && rsp.m_data_len >= 6 )
{
num = rsp.m_data[1];
stdlog << "reading bt capabilities: max outstanding " << num
<< ", input " << (int)rsp.m_data[2]
<< ", output " << (int)rsp.m_data[3]
<< ", retries " << (int)rsp.m_data[5] << ".\n";
// check
if ( num < 1 )
num = 1;
if ( num > 32 )
num = 32;
}
}
if ( num == 0 )
{
num = 1;
}
stdlog << "max number of outstanding = " << num << ".\n";
m_con->SetMaxOutstanding( num );
/** Commenting this code block due to the multi-domain
** changes in the infrastructure.
** (Renier Morales 11/21/06)
if ( m_own_domain == true )
{
SaHpiTextBufferT buf = m_domain_tag;
m_did = oh_request_new_domain_aitimeout(m_handler_id, &buf,
0,
m_insert_timeout, 0, 0);
if ( m_did == 0 )
{
stdlog << "Failed to get a Domain ID - using default\n";
m_did = oh_get_default_domain_id();
}
}
else
{*/
m_insert_timeout = SAHPI_TIMEOUT_IMMEDIATE;
m_did = 0;
/*}*/
stdlog << "Domain ID " << m_did << "\n";
// check for TCA an modify m_mc_to_check
CheckTca();
// Non TCA system -> adjust BMC info
if ( !m_is_tca )
{
cIpmiFruInfo *fi = FindFruInfo( dIpmiBmcSlaveAddr, 0 );
if ( !fi )
return false;
fi->Entity() = SAHPI_ENT_SYS_MGMNT_MODULE;
fi->Site() = eIpmiAtcaSiteTypeUnknown;
fi->Slot() = GetFreeSlotForOther( dIpmiBmcSlaveAddr );
}
if ( m_sdr_repository_support )
{
stdlog << "reading repository SDR.\n";
rv = m_main_sdrs->Fetch();
if ( rv )
// Just report an error, it shouldn't be a big deal if this
// fails.
stdlog << "could not get main SDRs, error " << rv << " !\n";
else if ( !m_is_tca )
{
// for each mc device locator record in main repository
// create an entry in m_mc_to_check.
for( unsigned int i = 0; i < m_main_sdrs->NumSdrs(); i++ )
{
cIpmiSdr *sdr = m_main_sdrs->Sdr( i );
if ( sdr->m_type != eSdrTypeMcDeviceLocatorRecord )
continue;
unsigned char addr = sdr->m_data[5];
cIpmiFruInfo *fi = FindFruInfo( addr, 0 );
if ( fi == 0 )
NewFruInfo( addr, 0,
SAHPI_ENT_SYS_MGMNT_MODULE, GetFreeSlotForOther( addr ),
eIpmiAtcaSiteTypeUnknown,
dIpmiMcThreadInitialDiscover
| dIpmiMcThreadPollDeadMc
| dIpmiMcThreadPollAliveMc );
}
}
}
// Start all MC threads with the
// properties found in m_mc_to_check.
m_initial_discover = 0;
m_num_mc_threads = 0;
for( GList *list = GetFruInfoList(); list; list = g_list_next( list ) )
{
cIpmiFruInfo *fi = (cIpmiFruInfo *)list->data;
if ( fi->FruId() != 0 )
continue;
int addr = fi->Address();
if ( m_mc_thread[addr] != 0 )
{
stdlog << "Thread already started for " << addr << " !\n";
continue;
}
m_mc_thread[addr] = new cIpmiMcThread( this, addr, fi->Properties()
/*, m_mc_to_check[i],
m_mc_type[i], m_mc_slot[i] */ );
// Count MC thread with initial discover.
// This counter is used in cIpmi::IfDiscoverResources
// to wait until discover is done
if ( fi->Properties() & dIpmiMcThreadInitialDiscover )
{
m_initial_discover_lock.Lock();
m_initial_discover++;
m_initial_discover_lock.Unlock();
}
m_mc_thread[addr]->Start();
}
return true;
}
void
cIpmiDomain::Cleanup()
{
int i;
// stop MC threads
for( i = 0; i < 256; i++ )
if ( m_mc_thread[i] )
m_mc_thread[i]->m_exit = true;
// wait until all threads are finish
bool loop = true;
while( loop )
{
m_mc_thread_lock.Lock();
loop = (bool)m_num_mc_threads;
m_mc_thread_lock.Unlock();
usleep( 100000 );
}
// wait for threads exit
for( i = 0; i < 256; i++ )
if ( m_mc_thread[i] )
{
void *rv;
m_mc_thread[i]->Wait( rv );
delete m_mc_thread[i];
m_mc_thread[i] = 0;
}
// stop reader thread
if ( m_con && m_con->IsOpen() )
m_con->Close();
// Delete the sensors from the main SDR repository.
while( m_sensors_in_main_sdr )
{
cIpmiSensor *sensor = (cIpmiSensor *)m_sensors_in_main_sdr->data;
m_sensors_in_main_sdr = g_list_remove( m_sensors_in_main_sdr, sensor );
sensor->Resource()->RemRdr( sensor );
delete sensor;
}
// cleanup all MCs
for( i = m_mcs.Num() - 1; i >= 0; i-- )
{
cIpmiMc *mc = m_mcs[i];
CleanupMc( mc );
}
// now all mc's are ready to destroy
while( m_mcs.Num() )
{
cIpmiMc *mc = m_mcs[0];
CleanupMc( mc );
}
// destroy si
if ( m_si_mc )
{
m_si_mc->Cleanup();
delete m_si_mc;
m_si_mc = 0;
}
/* Destroy the main SDR repository, if it exists. */
if ( m_main_sdrs )
{
delete m_main_sdrs;
m_main_sdrs = 0;
}
}
void
cIpmiDomain::AddMc( cIpmiMc *mc )
{
m_mcs.Add( mc );
}
bool
cIpmiDomain::CleanupMc( cIpmiMc *mc )
{
if ( !mc->Cleanup() )
return false;
int idx = m_mcs.Find( mc );
if ( idx == -1 )
{
stdlog << "unable to find mc at " << (unsigned char)mc->GetAddress() << " in mc list !\n";
return false;
}
m_mcs.Rem( idx );
delete mc;
return true;
}
SaErrorT
cIpmiDomain::CheckTca()
{
cIpmiMsg msg( eIpmiNetfnPicmg, eIpmiCmdGetPicMgProperties );
msg.m_data_len = 1;
msg.m_data[0] = dIpmiPicMgId;
cIpmiMsg rsp;
SaErrorT rv;
int i;
m_is_tca = false;
if ( !m_si_mc )
return SA_ERR_HPI_INTERNAL_ERROR;
stdlog << "checking for TCA system.\n";
rv = m_si_mc->SendCommand( msg, rsp );
if ( rv != SA_OK || rsp.m_data[0] || rsp.m_data[1] != dIpmiPicMgId )
{
stdlog << "not a TCA system.\n";
return (rv != SA_OK) ? rv : SA_ERR_HPI_INVALID_DATA;
}
unsigned char minor = (rsp.m_data[2] >> 4) & 0x0f;
unsigned char major = rsp.m_data[2] & 0x0f;
stdlog << "found a PICMG system, Extension Version " << (unsigned int)major << "." << (unsigned int)minor << ".\n";
switch ( major )
{
default:
return SA_OK;
case 2:
stdlog << "found an ATCA system.\n";
break;
case 5:
stdlog << "found a MicroTCA system.\n";
break;
}
// use atca timeout
stdlog << "set timeout to " << m_con_atca_timeout << ".\n";
m_con->m_timeout = m_con_atca_timeout;
m_is_tca = true;
// MicroTCA systems have 1 to 16 Carriers
if ( major == 5 )
{
for ( int carrier_number = 1; carrier_number <= 16; carrier_number++ )
{
NewFruInfo( 0x80 + (carrier_number*2), 0, SAHPI_ENT_SUBBOARD_CARRIER_BLADE, carrier_number,
eIpmiAtcaSiteTypeAtcaBoard, dIpmiMcThreadInitialDiscover );
}
return SA_OK;
}
// read all fru addr
msg.m_netfn = eIpmiNetfnPicmg;
msg.m_cmd = eIpmiCmdGetAddressInfo;
msg.m_data[0] = dIpmiPicMgId;
msg.m_data[1] = 0; // fru id 0
msg.m_data[2] = 0x03; // physical addr
msg.m_data_len = 5;
static const char *map[] =
{
"ATCA Board",
"Power Entry Module",
"Shelf FRU Information",
"Dedicated ShMc",
"Fan Tray",
"Fan Filter Tray",
"Alarm",
"AdvancedMC Module",
"PMC",
"Rear Transition Module",
"MicroTCA Carrier Hub",
"Power Module"
};
static int map_num = sizeof( map ) / sizeof( char * );
for( i = 0; i < 256; i++ )
{
if ( !m_atca_site_property[i].m_property )
continue;
if ( m_atca_poll_alive_mcs == true )
m_atca_site_property[i].m_property |= dIpmiMcThreadPollAliveMc;
if ( i < map_num )
stdlog << "checking for " << map[i] << ".\n";
else
stdlog << "checking for " << (unsigned char)i << ".\n";
SaHpiEntityTypeT entity = MapAtcaSiteTypeToEntity( (tIpmiAtcaSiteType)i );
for( int j = 0; j < m_atca_site_property[i].m_max_side_id; j++ )
{
msg.m_data[3] = j + 1;
msg.m_data[4] = i;
rv = m_si_mc->SendCommand( msg, rsp );
if ( rv != SA_OK )
{
stdlog << "cannot send get address info: " << rv << " !\n";
break;
}
if ( rsp.m_data[0] )
break;
if ( i < map_num )
stdlog << "\tfound " << map[i] << " at " << rsp.m_data[3] << ".\n";
else
stdlog << "\tfound " << (unsigned char)i << " at " << rsp.m_data[3] << ".\n";
// add MC for initial scan (FRU 0)
if (rsp.m_data[5] == 0)
NewFruInfo( rsp.m_data[3], rsp.m_data[5], entity, j + 1,
(tIpmiAtcaSiteType)i, m_atca_site_property[i].m_property );
}
}
return SA_OK;
}
cIpmiMc *
cIpmiDomain::FindMcByAddr( const cIpmiAddr &addr )
{
if ( ( addr.m_type == eIpmiAddrTypeSystemInterface )
&& ( addr.m_channel == dIpmiBmcChannel ) )
return m_si_mc;
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( addr == mc->Addr() )
return mc;
}
return 0;
}
SaErrorT
cIpmiDomain::SendCommand( const cIpmiAddr &addr, const cIpmiMsg &msg,
cIpmiMsg &rsp_msg, int retries )
{
if ( m_con == 0 )
{
return SA_ERR_HPI_NOT_PRESENT;
}
return m_con->ExecuteCmd( addr, msg, rsp_msg, retries );
}
GList *
cIpmiDomain::GetSdrSensors( cIpmiMc *mc )
{
if ( mc )
return mc->GetSdrSensors();
return m_sensors_in_main_sdr;
}
void
cIpmiDomain::SetSdrSensors( cIpmiMc *mc,
GList *sensors )
{
if ( mc )
mc->SetSdrSensors( sensors );
else
m_sensors_in_main_sdr = sensors;
}
cIpmiMc *
cIpmiDomain::GetEventRcvr()
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
// Event receiver on TCA must be set to the active ShMc
if ( IsTca() )
{
if ( mc->GetAddress() == dIpmiBmcSlaveAddr )
return mc;
}
else if ( mc->SelDeviceSupport() )
{
return mc;
}
}
return 0;
}
void
cIpmiDomain::HandleEvents( GList *list )
{
while( list )
{
cIpmiEvent *event = (cIpmiEvent *)list->data;
list = g_list_remove( list, event );
HandleEvent( event );
}
}
void
cIpmiDomain::HandleAsyncEvent( const cIpmiAddr &addr, const cIpmiMsg &msg )
{
// It came from an MC, so find the MC.
cIpmiMc *mc = FindMcByAddr( addr );
if ( !mc )
{
stdlog << "cannot find mc for event !\n";
return;
}
cIpmiEvent *event = new cIpmiEvent;
event->m_mc = mc;
event->m_record_id = IpmiGetUint16( msg.m_data );
event->m_type = msg.m_data[2];
memcpy( event->m_data, msg.m_data + 3, dIpmiMaxSelData );
// Add it to the MCs event log.
mc->Sel()->AddAsyncEvent( event );
HandleEvent( event );
}
void
cIpmiDomain::HandleEvent( cIpmiEvent *event )
{
// find MC thread
unsigned char a = event->m_data[4];
bool hotswap = ( event->m_data[7] == eIpmiSensorTypeAtcaHotSwap ) ? true : false;
// if there is no MC thread => create MC thread
if ( m_mc_thread[a] == 0 )
{
int slot = GetFreeSlotForOther( a );
cIpmiFruInfo *fi = NewFruInfo( a, 0, SAHPI_ENT_SYS_MGMNT_MODULE, slot,
eIpmiAtcaSiteTypeUnknown,
dIpmiMcThreadInitialDiscover
| hotswap ? ( dIpmiMcThreadPollAliveMc
| dIpmiMcThreadCreateM0) : 0 );
m_mc_thread[a] = new cIpmiMcThread( this, a, fi->Properties() );
m_mc_thread[a]->Start();
}
m_mc_thread[a]->AddEvent( event );
}
cIpmiResource *
cIpmiDomain::VerifyResource( cIpmiResource *res )
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( mc->FindResource( res ) )
return res;
}
return 0;
}
cIpmiMc *
cIpmiDomain::VerifyMc( cIpmiMc *mc )
{
if ( m_si_mc == mc )
return mc;
int idx = m_mcs.Find( mc );
if ( idx == -1 )
return 0;
return mc;
}
cIpmiRdr *
cIpmiDomain::VerifyRdr( cIpmiRdr *rdr )
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( mc->FindRdr( rdr ) )
return rdr;
}
return 0;
}
cIpmiSensor *
cIpmiDomain::VerifySensor( cIpmiSensor *s )
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( mc->FindRdr( s ) )
return s;
}
return 0;
}
cIpmiControl *
cIpmiDomain::VerifyControl( cIpmiControl *c )
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( mc->FindRdr( c ) )
return c;
}
return 0;
}
cIpmiWatchdog *
cIpmiDomain::VerifyWatchdog ( cIpmiWatchdog *c )
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( mc->FindRdr( c ) )
return c;
}
return 0;
}
cIpmiInventory *
cIpmiDomain::VerifyInventory( cIpmiInventory *inv )
{
for( int i = 0; i < m_mcs.Num(); i++ )
{
cIpmiMc *mc = m_mcs[i];
if ( mc->FindRdr( inv ) )
return inv;
}
return 0;
}
void
cIpmiDomain::Dump( cIpmiLog &dump ) const
{
if ( dump.IsRecursive() )
{
dump << "#include \"Mc.sim\"\n";
dump << "#include \"Entity.sim\"\n";
dump << "#include \"Sensor.sim\"\n";
dump << "#include \"Sdr.sim\"\n";
dump << "#include \"Sel.sim\"\n";
dump << "#include \"Fru.sim\"\n\n\n";
// main sdr
if ( m_main_sdrs )
{
dump << "// repository SDR\n";
m_main_sdrs->Dump( dump, "MainSdr1" );
}
// dump all MCs
for( int i = 0; i < 256; i++ )
{
if ( m_mc_thread[i] == 0 || m_mc_thread[i]->Mc() == 0 )
continue;
cIpmiMc *mc = m_mc_thread[i]->Mc();
char str[80];
snprintf( str, sizeof(str), "Mc%02x", i );
mc->Dump( dump, str );
}
}
// sim
dump.Begin( "Sim", "Dump" );
for( GList *list = GetFruInfoList(); list; list = g_list_next( list ) )
{
cIpmiFruInfo *fi = (cIpmiFruInfo *)list->data;
const char *site = 0;
switch( fi->Site() )
{
case eIpmiAtcaSiteTypeAtcaBoard:
site = "AtcaBoard";
break;
case eIpmiAtcaSiteTypePowerEntryModule:
site = "PowerUnit";
break;
case eIpmiAtcaSiteTypeShelfFruInformation:
site = "ShelfFruInformation";
break;
case eIpmiAtcaSiteTypeDedicatedShMc:
site = "ShMc";
break;
case eIpmiAtcaSiteTypeFanTray:
site = "FanTray";
break;
case eIpmiAtcaSiteTypeFanFilterTray:
site = "FanFilterTray";
break;
case eIpmiAtcaSiteTypeAlarm:
site = "Alarm";
break;
case eIpmiAtcaSiteTypeAdvancedMcModule:
site = "AdvancedMcModule";
break;
case eIpmiAtcaSiteTypePMC:
site = "PMC";
break;
case eIpmiAtcaSiteTypeRearTransitionModule:
site = "RearTransitionModule";
break;
default:
site = "Unknown";
break;
}
dump.Entry( site ) << fi->Slot() << ", " << (unsigned char)fi->Address() << ";\n";
}
if ( dump.IsRecursive() )
{
dump << "\n";
if ( m_main_sdrs )
dump.Entry( "MainSdr" ) << "MainSdr1\n";
for( int i = 0; i < 256; i++ )
{
if ( m_mc_thread[i] == 0
|| m_mc_thread[i]->Mc() == 0 )
continue;
cIpmiFruInfo *fi = FindFruInfo( i, 0 );
if ( fi == 0 )
{
continue;
}
const char *type = 0;
switch( fi->Site() )
{
case eIpmiAtcaSiteTypeAtcaBoard:
type = "AtcaBoard";
break;
case eIpmiAtcaSiteTypePowerEntryModule:
type = "PowerUnit";
break;
case eIpmiAtcaSiteTypeShelfFruInformation:
type = "ShelfFruInformation";
break;
case eIpmiAtcaSiteTypeDedicatedShMc:
type = "ShMc";
break;
case eIpmiAtcaSiteTypeFanTray:
type = "FanTray";
break;
case eIpmiAtcaSiteTypeFanFilterTray:
type = "FanFilterTray";
break;
case eIpmiAtcaSiteTypeAlarm:
type = "Alarm";
break;
case eIpmiAtcaSiteTypeAdvancedMcModule:
type = "AdvancedMcModule";
break;
case eIpmiAtcaSiteTypePMC:
type = "PMC";
break;
case eIpmiAtcaSiteTypeRearTransitionModule:
type = "RearTransitionModule";
break;
default:
type = "Unknown";
break;
}
char str[30];
snprintf( str, sizeof(str), "Mc%02x", i );
dump.Entry( "Mc" ) << str << ", " << type << ", " << fi->Slot() << ";\n";
}
}
dump.End();
}