summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/fsi/fsidd.C743
-rw-r--r--src/usr/fsi/fsidd.H315
-rw-r--r--src/usr/fsi/makefile30
-rw-r--r--src/usr/fsi/test/fsiddtest.H195
-rw-r--r--src/usr/fsi/test/makefile29
-rw-r--r--src/usr/makefile4
-rw-r--r--src/usr/xscom/xscom.C13
7 files changed, 1322 insertions, 7 deletions
diff --git a/src/usr/fsi/fsidd.C b/src/usr/fsi/fsidd.C
new file mode 100644
index 000000000..d909f85b7
--- /dev/null
+++ b/src/usr/fsi/fsidd.C
@@ -0,0 +1,743 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/fsi/fsidd.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/**
+ * @file fsidd.C
+ *
+ * @brief Implementation of the FSI Device Driver
+ */
+
+/*****************************************************************************/
+// I n c l u d e s
+/*****************************************************************************/
+#include <string.h>
+#include <devicefw/driverif.H>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <targeting/targetservice.H>
+#include <errl/errlmanager.H>
+#include <fsi/fsi_reasoncodes.H>
+#include "fsidd.H"
+#include <kernel/console.H>
+#include <sys/time.h>
+#include <algorithm>
+
+
+// Trace definition
+trace_desc_t* g_trac_fsi = NULL;
+TRAC_INIT(&g_trac_fsi, "FSI", 4096); //4K
+
+// Easy macro replace for unit testing
+//#define TRACUCOMP(args...) TRACFCOMP(args)
+#define TRACUCOMP(args...)
+
+
+//@todo - These should come from the target/attribute code somewhere
+uint64_t target_to_uint64(TARGETING::Target* i_target)
+{
+ uint64_t id = 0;
+ if( i_target == TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL )
+ {
+ id = 0xFFFFFFFFFFFFFFFF;
+ }
+ else
+ {
+ // class|type|model|number : 1 byte each
+ id = (uint64_t)(i_target->getAttr<TARGETING::ATTR_CLASS>() & 0xFF) << 56;
+ id |= (uint64_t)(i_target->getAttr<TARGETING::ATTR_TYPE>() & 0xFF) << 48;
+ id |= (uint64_t)(i_target->getAttr<TARGETING::ATTR_MODEL>() & 0xFF) << 40;
+ id |= 0ull << 32; //@todo-need a unit num
+ }
+ return id;
+}
+
+// Initialize static variables
+mutex_t FsiDD::cv_mux = MUTEX_INITIALIZER;
+std::vector<FsiDD*> FsiDD::cv_instances;
+
+/**
+ * @brief Select the instance for the given target
+ */
+FsiDD* FsiDD::getInstance( TARGETING::Target* i_target )
+{
+ FsiDD* inst = NULL;
+ TRACUCOMP( g_trac_fsi, "FsiDD::getInstance> Looking for target : %llX", target_to_uint64(i_target) );
+
+ mutex_lock(&cv_mux);
+
+ for( std::vector<FsiDD*>::iterator dd = FsiDD::cv_instances.begin();
+ dd != FsiDD::cv_instances.end();
+ ++dd )
+ {
+ if( (*dd)->iv_target == i_target )
+ {
+ inst = *dd;
+ break;
+ }
+ }
+
+ // need to instantiate an object
+ if( (inst == NULL)
+ && (TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL != i_target) )
+ {
+ // only support processor targets
+ //@todo - switch to PredicateCTM
+ if( i_target->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_PROC )
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::getInstance> Creating new instance for target : %llX", target_to_uint64(i_target) );
+ inst = new FsiDD(i_target);
+ FsiDD::cv_instances.push_back(inst);
+ }
+ }
+ mutex_unlock(&cv_mux);
+
+ return inst;
+}
+
+
+namespace FSI
+{
+
+/**
+ * @brief Performs a FSI Read Operation
+ * This function performs a FSI Read operation. It follows a pre-defined
+ * prototype functions in order to be registered with the device-driver
+ * framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target FSI target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output:
+ * Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * containing the FSI address
+ * @return errlHndl_t
+ */
+errlHndl_t ddRead(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t i_addr = va_arg(i_args,uint64_t);
+ TRACUCOMP( g_trac_fsi, "FSI::ddRead> i_addr=%llX, target=%llX", i_addr, target_to_uint64(i_target) );
+
+ do{
+ FsiDD* driver = FsiDD::getInstance(i_target);
+ if( driver )
+ {
+ // prefix the appropriate MFSI/cMFSI slave port
+ uint64_t l_addr = driver->genFullFsiAddr( i_target, i_addr );
+
+ // do the read
+ l_err = driver->read(l_addr,
+ io_buflen,
+ (uint32_t*)io_buffer);
+ if(l_err)
+ {
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP( g_trac_fsi, "FSI::ddRead> Invalid target : %llX", target_to_uint64(i_target) );
+ /*@
+ * @errortype
+ * @moduleid FSI::MOD_FSIDD_DDREAD
+ * @reasoncode FSI::RC_INVALID_TARGET
+ * @userdata1 Target Id
+ * @userdata2 FSI Address
+ * @devdesc FSI::ddRead> Invalid target
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ FSI::MOD_FSIDD_DDREAD,
+ FSI::RC_INVALID_TARGET,
+ target_to_uint64(i_target),
+ i_addr);
+ break;
+
+ }
+
+ }while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Performs a FSI Write Operation
+ * This function performs a FSI Write operation. It follows a pre-defined
+ * prototype functions in order to be registered with the device-driver
+ * framework.
+ *
+ * @param[in] i_opType Operation type, see DeviceFW::OperationType
+ * in driverif.H
+ * @param[in] i_target FSI target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output:
+ * Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessType DeviceFW::AccessType enum (usrif.H)
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * containing the FSI address
+ * @return errlHndl_t
+ */
+errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t i_addr = va_arg(i_args,uint64_t);
+ TRACUCOMP( g_trac_fsi, "FSI::ddWrite> i_addr=%llX, target=%llX", i_addr, target_to_uint64(i_target) );
+
+ do{
+ FsiDD* driver = FsiDD::getInstance(i_target);
+ if( driver )
+ {
+ // prefix the appropriate MFSI/cMFSI slave port
+ uint64_t l_addr = driver->genFullFsiAddr( i_target, i_addr );
+
+ // do the write
+ l_err = driver->write(l_addr,
+ io_buflen,
+ (uint32_t*)io_buffer);
+ if(l_err)
+ {
+ break;
+ }
+ }
+ else
+ {
+ TRACFCOMP( g_trac_fsi, "FSI::ddWrite> Invalid target : %llX", target_to_uint64(i_target) );
+ /*@
+ * @errortype
+ * @moduleid FSI::MOD_FSIDD_DDWRITE
+ * @reasoncode FSI::RC_INVALID_TARGET
+ * @userdata1 Target Id
+ * @userdata2 FSI Address
+ * @devdesc FSI::ddWrite> Invalid target
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ FSI::MOD_FSIDD_DDWRITE,
+ FSI::RC_INVALID_TARGET,
+ target_to_uint64(i_target),
+ i_addr);
+ break;
+
+ }
+
+ }while(0);
+
+ return l_err;
+}
+
+// Register fsidd access functions to DD framework
+DEVICE_REGISTER_ROUTE(DeviceFW::READ,
+ DeviceFW::FSI,
+ TARGETING::TYPE_PROC,
+ ddRead);
+
+// Register fsidd access functions to DD framework
+DEVICE_REGISTER_ROUTE(DeviceFW::WRITE,
+ DeviceFW::FSI,
+ TARGETING::TYPE_PROC,
+ ddWrite);
+
+
+}; //end FSI namespace
+
+
+
+
+
+/**
+ * @brief Read FSI Register
+ */
+errlHndl_t FsiDD::read(uint64_t i_address,
+ size_t& io_buflen,
+ uint32_t* o_buffer)
+{
+ TRACDCOMP(g_trac_fsi, "FsiDD::read(i_address=0x%llx)> ", i_address);
+ errlHndl_t l_err = NULL;
+ bool need_unlock = false;
+
+ do {
+ // make sure we got a valid FSI address
+ l_err = verifyAddressRange( i_address, io_buflen );
+ if(l_err)
+ {
+ break;
+ }
+
+ // setup the OPB command register
+ uint64_t fsicmd = i_address | 0x60000000; // 011=Read Full Word
+ fsicmd <<= 32; // Command is in the upper word
+
+ // generate the proper OPB SCOM address
+ uint64_t opbaddr = genOpbScomAddr(OPB_REG_CMD);
+
+ // atomic section >>
+ mutex_lock(&iv_fsiMutex);
+ need_unlock = true;
+
+ // always read/write 64 bits to SCOM
+ size_t scom_size = sizeof(uint64_t);
+
+ // write the OPB command register to trigger the read
+ TRACUCOMP(g_trac_fsi, "FsiDD::read> ScomWRITE : opbaddr=%.16llX, data=%.16llX", opbaddr, fsicmd );
+ l_err = deviceOp( DeviceFW::WRITE,
+ iv_target,
+ &fsicmd,
+ scom_size,
+ DEVICE_SCOM_ADDRESS(opbaddr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDD::read> Error from device 1 : RC=%X", l_err->reasonCode() );
+ break;
+ }
+
+ // poll for complete and get the data back
+ l_err = pollForComplete( i_address, o_buffer );
+ if( l_err )
+ {
+ break;
+ }
+
+ io_buflen = 4;
+
+ // atomic section <<
+ need_unlock = false;
+ mutex_unlock(&iv_fsiMutex);
+
+ } while(0);
+
+ if( need_unlock )
+ {
+ mutex_unlock(&iv_fsiMutex);
+ }
+
+ if( l_err )
+ {
+ io_buflen = 0;
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief Write FSI Register
+ */
+errlHndl_t FsiDD::write(uint64_t i_address,
+ size_t& io_buflen,
+ uint32_t* i_buffer)
+{
+ TRACDCOMP(g_trac_fsi, "FsiDD::write(i_address=0x%llx)> ", i_address);
+ errlHndl_t l_err = NULL;
+ bool need_unlock = false;
+
+ do {
+ // make sure we got an FSI address
+ l_err = verifyAddressRange( i_address, io_buflen );
+ if(l_err)
+ {
+ break;
+ }
+
+ // pull out the data to write (length has been verified)
+ uint32_t fsidata = *i_buffer;
+
+ // setup the OPB command register
+ uint64_t fsicmd = i_address | 0xE0000000; // 111=Write Full Word
+ fsicmd <<= 32; // Command is in the upper 32-bits
+ fsicmd |= fsidata; // Data is in the bottom 32-bits
+ size_t scom_size = sizeof(uint64_t);
+
+ // generate the proper OPB SCOM address
+ uint64_t opbaddr = genOpbScomAddr(OPB_REG_CMD);
+
+ // atomic section >>
+ mutex_lock(&iv_fsiMutex);
+ need_unlock = true;
+
+ // write the OPB command register
+ TRACUCOMP(g_trac_fsi, "FsiDD::write> ScomWRITE : opbaddr=%.16llX, data=%.16llX", opbaddr, fsicmd );
+ l_err = deviceOp( DeviceFW::WRITE,
+ iv_target,
+ &fsicmd,
+ scom_size,
+ DEVICE_SCOM_ADDRESS(opbaddr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDD::write> Error from device : RC=%X", l_err->reasonCode() );
+ break;
+ }
+
+ // poll for complete (no return data)
+ l_err = pollForComplete( i_address, NULL );
+ if( l_err )
+ {
+ break;
+ }
+
+ io_buflen = 4;
+
+ // atomic section <<
+ need_unlock = false;
+ mutex_unlock(&iv_fsiMutex);
+
+ } while(0);
+
+ if( need_unlock )
+ {
+ mutex_unlock(&iv_fsiMutex);
+ }
+
+ if( l_err )
+ {
+ io_buflen = 0;
+ }
+
+ TRACDCOMP(g_trac_fsi, "< FsiDD::write() ", i_address);
+
+ return l_err;
+}
+
+
+/**
+ * @brief Constructor
+ */
+FsiDD::FsiDD( TARGETING::Target* i_target )
+:iv_target(i_target)
+{
+ TRACFCOMP(g_trac_fsi, "FsiDD::FsiDD()> target=%llX", target_to_uint64(i_target) );
+
+ mutex_init(&iv_fsiMutex);
+}
+
+/**
+ * @brief Destructor
+ */
+FsiDD::~FsiDD()
+{
+ // remove this instance from the global list
+ FsiDD::cv_instances.erase(
+ std::find(cv_instances.begin(),
+ cv_instances.end(),
+ this)
+ );
+}
+
+/**
+ * @brief Verify Request is in appropriate address range
+ */
+errlHndl_t FsiDD::verifyAddressRange(uint64_t i_address,
+ size_t i_length)
+{
+ errlHndl_t l_err = NULL;
+
+ do{
+ //@todo - add more address checks
+
+ // no port specified
+ if( (i_address & (MFSI_PORT_MASK|CMFSI_PORT_MASK|CONTROL_REG_MASK)) == 0 )
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::verifyAddressRange> Invalid address : i_address=0x%X", i_address );
+ /*@
+ * @errortype
+ * @moduleid FSI::MOD_FSIDD_VERIFYADDRESSRANGE
+ * @reasoncode FSI::RC_INVALID_ADDRESS
+ * @userdata1 FSI Address
+ * @userdata2 Data Length
+ * @devdesc FsiDD::verifyAddressRange> Invalid address
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ FSI::MOD_FSIDD_VERIFYADDRESSRANGE,
+ FSI::RC_INVALID_ADDRESS,
+ i_address,
+ TO_UINT64(i_length));
+ break;
+ }
+
+ if( i_length != 4 )
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::verifyAddressRange> Invalid data length : i_length=%d", i_length );
+ /*@
+ * @errortype
+ * @moduleid FSI::MOD_FSIDD_VERIFYADDRESSRANGE
+ * @reasoncode FSI::RC_INVALID_LENGTH
+ * @userdata1 FSI Address
+ * @userdata2 Data Length
+ * @devdesc FsiDD::verifyAddressRange> Invalid data length
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ FSI::MOD_FSIDD_VERIFYADDRESSRANGE,
+ FSI::RC_INVALID_LENGTH,
+ i_address,
+ TO_UINT64(i_length));
+ break;
+ }
+
+
+ }while(0);
+
+ return l_err;
+}
+
+
+/**
+ * @brief Analyze error bits and recover hardware as needed
+ */
+errlHndl_t FsiDD::handleOpbErrors(TARGETING::Target* i_target,
+ uint64_t i_address,
+ uint32_t i_opbStatReg)
+{
+ errlHndl_t l_err = NULL;
+
+ if( (i_opbStatReg & OPB_STAT_ERR_ANY)
+ || (i_opbStatReg & OPB_STAT_BUSY) )
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::handleOpbErrors> Error during FSI access : i_address=0x%X, OPB Status=0x%.8X", i_address, i_opbStatReg );
+
+
+ /*@
+ * @errortype
+ * @moduleid FSI::MOD_FSIDD_HANDLEOPBERRORS
+ * @reasoncode FSI::RC_OPB_ERROR
+ * @userdata1 FSI Address
+ * @userdata2 OPB Status Register
+ * @devdesc FsiDD::handleOpbErrors> Error during FSI access
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ FSI::MOD_FSIDD_HANDLEOPBERRORS,
+ FSI::RC_OPB_ERROR,
+ i_address,
+ TWO_UINT32_TO_UINT64(i_opbStatReg,0));
+ //@todo - figure out best data to log
+
+ //@todo - implement recovery and callout code
+
+ }
+
+ return l_err;
+}
+
+/**
+ * @brief Poll for completion of a FSI operation, return data on read
+ */
+errlHndl_t FsiDD::pollForComplete(uint64_t i_address,
+ uint32_t* o_readData)
+{
+ errlHndl_t l_err = NULL;
+
+ do {
+ // poll for complete
+ uint32_t read_data[2];
+ size_t scom_size = sizeof(uint64_t);
+ uint64_t opbaddr = genOpbScomAddr(OPB_REG_STAT);
+ int attempts = 0;
+ do
+ {
+ TRACUCOMP(g_trac_fsi, "FsiDD::pollForComplete> ScomREAD : opbaddr=%.16llX", opbaddr );
+ l_err = deviceOp( DeviceFW::READ,
+ iv_target,
+ read_data,
+ scom_size,
+ DEVICE_SCOM_ADDRESS(opbaddr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDD::pollForComplete> Error from device 2 : RC=%X", l_err->reasonCode() );
+ break;
+ }
+
+ //@fixme - Simics model is broken on writes, just assume completion
+ if( !o_readData )
+ {
+ read_data[0] &= ~OPB_STAT_BUSY;
+ }
+
+ // check for completion or error
+ TRACUCOMP(g_trac_fsi, "FsiDD::pollForComplete> ScomREAD : read_data[0]=%.8llX", read_data[0] );
+ if( ((read_data[0] & OPB_STAT_BUSY) == 0) //not busy
+ || (read_data[0] & OPB_STAT_ERR_ANY) ) //error bits
+ {
+ break;
+ }
+
+ attempts++;
+ } while( attempts < MAX_OPB_ATTEMPTS );
+ if( l_err ) { break; }
+ //@todo - hw has a 1ms watchdog, do I need to have a limit or just
+ // loop until we hit an error
+
+ // check if we got an error
+ l_err = handleOpbErrors( iv_target, i_address, read_data[0] );
+ if( l_err )
+ {
+ break;
+ }
+
+ //@todo - is this possible? Ask hw team
+ // read valid isn't on
+ if( o_readData ) // only check if we're doing a read
+ {
+ if( !(read_data[0] & OPB_STAT_READ_VALID) )
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::read> Read valid never came on : i_address=0x%X, OPB Status=0x%.8X", i_address, read_data[0] );
+ //@todo - create error log
+ break;
+ }
+
+ *o_readData = read_data[1];
+ }
+
+ } while(0);
+
+ return l_err;
+}
+
+/**
+ * @brief Generate a complete FSI address based on the target and the
+ * FSI offset within that target
+ */
+uint64_t FsiDD::genFullFsiAddr(TARGETING::Target* i_target,
+ uint64_t i_address)
+{
+ //@todo - fill this in, for now just return the address as-is
+ return i_address;
+
+ //target matches my target so the address is correct as-is
+ if( i_target == iv_target )
+ {
+ return i_address;
+ }
+ //target is another proc so need to use the appropriate MFSI port
+ else if( i_target->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_PROC )
+ {
+ //@todo - use attribute to figure out which MFSI_PORT_x to use
+ TRACFCOMP( g_trac_fsi, "FsiDD::genFullFsiAddr> MFSI targets aren't supported yet : i_target=%llX", target_to_uint64(i_target) );
+ assert(0);
+ }
+ //target is a centaur so need to use the appropriate cMFSI port
+ else if( i_target->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_MEMBUF )
+ {
+ //@todo - use attribute to figure out which CMFSI_PORT_x to use
+ TRACFCOMP( g_trac_fsi, "FsiDD::genFullFsiAddr> CMFSI targets aren't supported yet : i_target=%llX", target_to_uint64(i_target) );
+ assert(0);
+ }
+ else
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::genFullFsiAddr> Unknown target type : i_target=%llX", target_to_uint64(i_target) );
+ assert(0);
+ }
+}
+
+/**
+ * @brief Generate a valid SCOM address to access the OPB, this will
+ * choosing the correct master
+ */
+uint64_t FsiDD::genOpbScomAddr(uint64_t i_opbOffset)
+{
+ //@todo: handle redundant FSI ports, always using zero for now
+ uint64_t opbaddr = FSI2OPB_OFFSET_0 | i_opbOffset;
+ return opbaddr;
+}
+
+//@todo - IGNORE THIS FOR NOW
+/**
+ * @brief Initializes the FSI bus for the given slave
+ */
+errlHndl_t FsiDD::initSlave(TARGETING::Target* i_target)
+{
+ errlHndl_t l_err = NULL;
+ size_t regsize = sizeof(uint32_t);
+
+ do {
+ uint64_t masteroffset = MFSI_CONTROL_REG; //call some function to get this
+
+
+ //figure out which port this target is on
+ uint64_t port = 0; //getAttr<TYPE_FSI_SLAVE_PORT>?
+ uint32_t portbit = 0x80000000 >> port;
+
+ //see if the slave is present
+ uint32_t readbuf = 0;
+ l_err = read( masteroffset|0x018, regsize, &readbuf );
+ if( l_err ) { break; }
+
+ if( !(readbuf & portbit) )
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDD::initSlave> Target %llX is not present : Reg 0x018=%lX", target_to_uint64(i_target), readbuf );
+ //@todo - create error log for non-present slave?
+ }
+
+ //choose clock ratio,delay selection
+ l_err = write( masteroffset|0x008, regsize, &portbit );
+ if( l_err ) { break; }
+
+ //enable the port
+ l_err = write( masteroffset|0x018, regsize, &portbit );
+ if( l_err ) { break; }
+
+ //reset the port
+ l_err = write( masteroffset|0x008, regsize, &portbit );
+ if( l_err ) { break; }
+
+ } while(0);
+
+ return l_err;
+}
+
+//@todo - IGNORE THIS FOR NOW
+/**
+ * @brief Initializes the FSI master control registers
+ *
+ * @return errlHndl_t NULL on success
+ */
+errlHndl_t FsiDD::initMaster()
+{
+ errlHndl_t l_err = NULL;
+
+ do {
+ //@todo - loop to hit MFSI_CONTROL_REG and CMFSI_CONTROL_REG range?
+
+ // Mode Register
+ // 1: Enable hardware error recovery
+ //uint32_t clock_ratio0 = 100; //iv_target->getAttr<TARGETING::>()
+ //uint32_t mode_reg = 0;
+
+ } while(0);
+
+ return l_err;
+}
diff --git a/src/usr/fsi/fsidd.H b/src/usr/fsi/fsidd.H
new file mode 100644
index 000000000..f577f6571
--- /dev/null
+++ b/src/usr/fsi/fsidd.H
@@ -0,0 +1,315 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/fsi/fsidd.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __FSI_FSIDD_H
+#define __FSI_FSIDD_H
+
+#include <sys/sync.h>
+#include <util/locked/list.H>
+#include <list>
+
+/** @file fsidd.H
+ * @brief Provides the interfaces to the FSI Device Driver
+ */
+
+class FsiDD;
+
+// Predeclare these so we can make them friends
+namespace FSI {
+errlHndl_t ddRead(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args);
+errlHndl_t ddWrite(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args);
+}
+
+/**
+ * Class to handle the FSI Master operations
+ * there will be one instance per master
+ */
+class FsiDD
+{
+ public:
+ /**
+ * @brief Performs an FSI Read Operation
+ *
+ * @param[in] i_address Address to read (relative to FSI Master chip)
+ * @param[in] io_buflen Number of bytes to access, returns
+ * number of bytes actually read
+ * @param[out] o_buffer Destination buffer for data
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t read(uint64_t i_address,
+ size_t& io_buflen,
+ uint32_t* o_buffer);
+
+ /**
+ * @brief Performs an FSI Write Operation
+ *
+ * @param[in] i_address Address to read (relative to FSI Master chip)
+ * @param[in] io_buflen Number of bytes to access, returns
+ * number of bytes actually written
+ * @param[out] o_buffer Source buffer for data
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t write(uint64_t i_address,
+ size_t& io_buflen,
+ uint32_t* i_buffer);
+
+ /**
+ * @brief Initializes the FSI bus for the given slave
+ *
+ * @param[in] Chip target of FSI-slave
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t initSlave(TARGETING::Target* i_target);
+
+ protected:
+ /**
+ * @brief Constructor
+ *
+ * @param[in] XSCOM target associated with this FSI Master instance
+ */
+ FsiDD( TARGETING::Target* i_target );
+
+
+ /**
+ * @brief Destructor
+ */
+ ~FsiDD();
+
+ /**
+ * @brief Verify Request is in appropriate address range
+ *
+ * @param[in] i_address Starting address (relative to FSI Device)
+ * @param[in] i_length Number of bytes being accessed
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t verifyAddressRange(uint64_t i_address,
+ size_t i_length);
+
+ /**
+ * @brief Analyze error bits and recover hardware as needed
+ *
+ * @param[in] i_target Target of SCOM operation
+ * @param[in] i_address Address of FSI register being accessed
+ * @param[in] i_opbStatReg OPB Status bits (OPB_REG_STAT[0:31])
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t handleOpbErrors(TARGETING::Target* i_target,
+ uint64_t i_address,
+ uint32_t i_opbStatReg);
+
+ /**
+ * @brief Poll for completion of a FSI operation, return data on read
+ *
+ * @param[in] i_address Address of FSI register being accessed
+ * @param[out] o_readData buffer to copy read data into, set to NULL
+ * for write operations
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t pollForComplete(uint64_t i_address,
+ uint32_t* o_readData);
+
+ /**
+ * @brief Generate a complete FSI address based on the target and the
+ * FSI offset within that target
+ *
+ * @param[in] i_target Target of FSI-slave, or master for control regs
+ * @param[in] i_address Address of FSI register relative to slave space
+ *
+ * @return uint64_t Fully qualified FSI address
+ */
+ uint64_t genFullFsiAddr(TARGETING::Target* i_target,
+ uint64_t i_address);
+
+ /**
+ * @brief Generate a valid SCOM address to access the OPB, this will
+ * choosing the correct master
+ *
+ * @param[in] i_address Address of OPB register relative to OPB space,
+ * e.g. OPB_REG_CMD
+ *
+ * @return uint64_t Fully qualified OPB SCOM address
+ */
+ uint64_t genOpbScomAddr(uint64_t i_opbOffset);
+
+ /**
+ * @brief Initializes the FSI master control registers
+ *
+ * @return errlHndl_t NULL on success
+ */
+ errlHndl_t initMaster();
+
+ /**
+ * FSI Address Space
+ */
+ enum {
+ // Local FSI Space
+ CFAM_CONFIG_TABLE = 0x000000, /**< Configuration Table of CFAM */
+ PEEK_TABLE = 0x000400, /**< Peek Table */
+ FSI_SLAVE_REG = 0x000800, /**< FSI Slave Register */
+ FSI_SHIFT_ENGINE = 0x000C00, /**< FSI Shift Engine (SCAN) */
+ FSI2PIB_ENGINE = 0x001000, /**< FSI2PIB Engine (SCOM) */
+ FSI_SCRATCHPAD = 0x001400, /**< FSI Scratchpad */
+ FSI_I2C_MASTER = 0x001800, /**< FSI I2C-Master */
+ FSI_GEMINI_MBOX = 0x002800, /**< FSI Gemini Mailbox with FSI GPx Registers */
+
+ // Master control registers
+ CMFSI_CONTROL_REG = 0x003000, /**< cMFSI Control Register */
+ MFSI_CONTROL_REG = 0x003400, /**< MFSI Control Register */
+ CONTROL_REG_MASK = 0x003400, /**< Mask to look for a valid control register */
+
+ // cMFSI Ports (32KB each)
+ CMFSI_PORT_0 = 0x040000, /**< cMFSI port 0 */
+ CMFSI_PORT_1 = 0x048000, /**< cMFSI port 1 */
+ CMFSI_PORT_2 = 0x050000, /**< cMFSI port 2 */
+ CMFSI_PORT_3 = 0x058000, /**< cMFSI port 3 */
+ CMFSI_PORT_4 = 0x060000, /**< cMFSI port 4 */
+ CMFSI_PORT_5 = 0x068000, /**< cMFSI port 5 */
+ CMFSI_PORT_6 = 0x070000, /**< cMFSI port 6 */
+ CMFSI_PORT_7 = 0x078000, /**< cMFSI port 7 */
+ CMFSI_PORT_MASK = 0x078000, /**< Mask to look for a valid cMFSI port */
+
+ // Offsets to cascaded slaves within a cMFSI port
+ CMFSI_SLAVE_0 = 0x000000, /**< cMFSI - Slave 0 */
+ CMFSI_SLAVE_1 = 0x002000, /**< cMFSI - Slave 1 */
+ CMFSI_SLAVE_2 = 0x004000, /**< cMFSI - Slave 2 */
+ CMFSI_SLAVE_3 = 0x006000, /**< cMFSI - Slave 3 */
+
+ // MFSI Ports (512KB each)
+ MFSI_PORT_0 = 0x080000, /**< MFSI port 0 */
+ MFSI_PORT_1 = 0x100000, /**< MFSI port 1 */
+ MFSI_PORT_2 = 0x180000, /**< MFSI port 2 */
+ MFSI_PORT_3 = 0x200000, /**< MFSI port 3 */
+ MFSI_PORT_4 = 0x280000, /**< MFSI port 4 */
+ MFSI_PORT_5 = 0x300000, /**< MFSI port 5 */
+ MFSI_PORT_6 = 0x380000, /**< MFSI port 6 */
+ MFSI_PORT_7 = 0x400000, /**< MFSI port 7 */
+ MFSI_PORT_MASK = 0x780000, /**< Mask to look for a valid MFSI port */
+ };
+
+
+ /**
+ * PIB2OPB Registers
+ */
+ enum {
+ OPB_REG_CMD = 0x0000, /**< Command Register */
+ OPB_REG_STAT = 0x0001, /**< Status Register */
+ OPB_REG_LSTAT = 0x0002, /**< Locked Status */
+ // no reg for 0x0003
+ OPB_REG_RES = 0x0004, /**< Reset */
+ OPB_REG_CRSIC = 0x0005, /**< cMFSI Remote Slave Interrupt Condition */
+ OPB_REG_CRSIM = 0x0006, /**< cMFSI Remote Slave Interrupt Mask */
+ OPB_REG_CRSIS = 0x0007, /**< cMFSI Remote Slave Interrupt Status */
+ OPB_REG_RSIC = 0x0008, /**< MFSI Remote Slave Interrupt Condition */
+ OPB_REG_RSIM = 0x0009, /**< MFSI Remote Slave Interrupt Mask */
+ OPB_REG_RSIS = 0x000A, /**< MFSI Remote Slave Interrupt Status */
+
+ // Offsets for cMFSI
+ FSI2OPB_OFFSET_0 = 0x00020010, /**< cMFSI 0 and MFSI */
+ FSI2OPB_OFFSET_1 = 0x00030000, /**< cMFSI 1 */
+
+ // Bit masks
+ OPB_STAT_BUSY = 0x00010000, /**< Bit 15 is the Busy bit */
+ OPB_STAT_READ_VALID = 0x00020000, /**< Bit 15 is the Busy bit */
+ OPB_STAT_ERR_OPB = 0x09F00000, /**< 4,7-11 are OPB errors */
+ OPB_STAT_ERR_CMFSI = 0x0000FC00, /**< 16-21 are cMFSI errors */
+ OPB_STAT_ERR_MFSI = 0x000000FC, /**< 24-29 are MFSI errors */
+ OPB_STAT_ERR_ANY = OPB_STAT_ERR_OPB|OPB_STAT_ERR_CMFSI|OPB_STAT_ERR_MFSI,
+
+ MAX_OPB_ATTEMPTS = 10, /**< Maximum number of attempts for OPB reg ops */
+ };
+
+
+ /**
+ * Global mutex @todo - make this per target for efficiency
+ */
+ mutex_t iv_fsiMutex;
+
+ /**
+ * Associated target of FSI Master, i.e. XSCOM target
+ */
+ TARGETING::Target* iv_target;
+
+ private:
+
+ // let my testcase poke around
+ friend class FsiDDTest;
+
+
+ friend errlHndl_t FSI::ddRead(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args);
+ friend errlHndl_t FSI::ddWrite(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args);
+
+ /**********
+ * STATIC
+ **********/
+
+ /**
+ * List of available instances
+ */
+ static std::vector<FsiDD*> cv_instances;
+
+ /**
+ * Global mutex to handle updates to gv_instances
+ */
+ static mutex_t cv_mux;
+
+
+ public:
+ /**
+ * @brief Select the instance for the given target
+ *
+ * @param[in] i_target TARGETING::Target* i_target
+ *
+ * @return FsiDD* Pointer to instance that matches the target
+ */
+ static FsiDD* getInstance( TARGETING::Target* i_target );
+
+
+};
+
+
+#endif
diff --git a/src/usr/fsi/makefile b/src/usr/fsi/makefile
new file mode 100644
index 000000000..94c02b826
--- /dev/null
+++ b/src/usr/fsi/makefile
@@ -0,0 +1,30 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/fsi/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../..
+MODULE = fsi
+
+OBJS = fsidd.o
+
+SUBDIRS = test.d
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/fsi/test/fsiddtest.H b/src/usr/fsi/test/fsiddtest.H
new file mode 100644
index 000000000..2b87c1dd0
--- /dev/null
+++ b/src/usr/fsi/test/fsiddtest.H
@@ -0,0 +1,195 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/fsi/test/fsiddtest.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __FSIDDTEST_H
+#define __FSIDDTEST_H
+
+/**
+ * @file fsiddtest.H
+ *
+ * @brief Test cases for FSI Device Driver
+*/
+
+#include <cxxtest/TestSuite.H>
+#include <errl/errlmanager.H>
+#include <errl/errlentry.H>
+#include <errl/errltypes.H>
+#include <limits.h>
+#include <devicefw/driverif.H>
+#include "../fsidd.H"
+
+extern trace_desc_t* g_trac_fsi;
+
+
+class FsiDDTest : public CxxTest::TestSuite
+{
+ public:
+
+ /**
+ * @brief FSI DD test - Read/Write
+ * Perform basic read/write operations
+ */
+ void test_readWrite(void)
+ {
+ return; //@fixme - enable when simics fixes are integrated
+ TRACFCOMP( g_trac_fsi, "FsiDDTest::test_readWrite> Start" );
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ errlHndl_t l_err = NULL;
+
+ // scratch data to use
+ struct {
+ uint64_t addr;
+ uint32_t data;
+ bool writeable;
+ } test_data[] = {
+ { FsiDD::MFSI_CONTROL_REG | 0x000000, 0x11111100, true }, //Mode Reg
+ //{ 0x000010, 0x22222222 },
+ //{ 0x000020, 0x33333333 },
+ { FsiDD::CMFSI_CONTROL_REG | 0x000074, 0x91010800, false }, //version
+ { FsiDD::MFSI_CONTROL_REG | 0x000074, 0x91010800, false }, //version
+ //{ FsiDD::MFSI_CONTROL_REG | 0x000018, 0x44444444, true },
+
+ { FsiDD::MFSI_PORT_0 | 0x000000, 0x91010800, false }, //Slave Config Table
+ };
+ const uint64_t NUM_ADDRS = sizeof(test_data)/sizeof(test_data[0]);
+
+ // allocate some space to play with
+ uint32_t read_data[NUM_ADDRS];
+ size_t op_size = sizeof(uint32_t);
+
+ // target the master processor
+ TARGETING::TargetService& targetService = TARGETING::targetService();
+ TARGETING::Target* fsi_target = NULL;
+ targetService.masterProcChipTargetHandle( fsi_target );
+
+ // read address X,Y,Z
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ total++;
+ TRACFCOMP( g_trac_fsi, "FsiDDTest::test_readWrite> Reading %llX", test_data[x].addr );
+ l_err = DeviceFW::deviceOp( DeviceFW::READ,
+ fsi_target,
+ &(read_data[x]),
+ op_size,
+ DEVICE_FSI_ADDRESS(test_data[x].addr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDDTest::test_readWrite> Error from device : addr=0x%X, RC=%X", test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "FsiDDTest::test_readWrite> ERROR : Unexpected error log from read1" );
+ fails++;
+ errlCommit(l_err);
+ delete l_err;
+ }
+
+ TRACFCOMP( g_trac_fsi, "0x%X = 0x%X", test_data[x].addr, read_data[x] );
+
+ //@todo - check op_size
+ }
+
+ // write X=A, Y=B, Z=C
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ total++;
+ l_err = DeviceFW::deviceOp( DeviceFW::WRITE,
+ fsi_target,
+ &(test_data[x].data),
+ op_size,
+ DEVICE_FSI_ADDRESS(test_data[x].addr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDDTest::test_readWrite> Error from device : addr=0x%X, RC=%X", test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "FsiDDTest::test_readWrite> ERROR : Unexpected error log from write1" );
+ fails++;
+ errlCommit(l_err);
+ delete l_err;
+ }
+
+ //@todo - check op_size
+ }
+
+ // read X,Y,Z
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ total++;
+ l_err = DeviceFW::deviceOp( DeviceFW::READ,
+ fsi_target,
+ &(read_data[x]),
+ op_size,
+ DEVICE_FSI_ADDRESS(test_data[x].addr) );
+ if( l_err )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDDTest::test_readWrite> Error from device : addr=0x%X, RC=%X", test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "FsiDDTest::test_readWrite> ERROR : Unexpected error log from read2" );
+ fails++;
+ errlCommit(l_err);
+ delete l_err;
+ }
+
+ //@todo - check op_size
+ }
+
+ // verify X==A, Y==B, Z==C
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ total++;
+ if( read_data[x] != test_data[x].data )
+ {
+ TRACFCOMP(g_trac_fsi, "FsiDDTest::test_readWrite> Data mismatch : addr=0x%X, exp=0x%X, act=0x%X", test_data[x].addr, test_data[x].data, read_data[x] );
+ TS_FAIL( "FsiDDTest::test_readWrite> ERROR : Data mismatch" );
+ fails++;
+ }
+ }
+
+ //@todo - repeat for each address space
+
+ TRACFCOMP( g_trac_fsi, "FsiDDTest::test_readWrite> %d/%d fails", fails, total );
+ };
+
+ /**
+ * @brief FSI DD test - verifyAddressRange
+ * Test output of verifyAddressRange
+ */
+ void test_verifyAddressRange(void)
+ {
+ TRACFCOMP( g_trac_fsi, "FsiDDTest::verifyAddressRange> Start" );
+ uint64_t fails = 0;
+ uint64_t total = 0;
+
+ //@todo
+ // values to try:
+ // -address 0
+ // -valid address at the beginning (if not 0)
+ // -valid address and size in the middle
+ // -valid address and size that hit the end of the range
+ // -valid address and size that exceeds range
+ // -address beyond range
+ // -address before beginning (if not 0)
+
+
+ TRACFCOMP( g_trac_fsi, "FsiDDTest::verifyAddressRange> %d/%d fails", fails, total );
+ };
+
+};
+
+
+#endif
diff --git a/src/usr/fsi/test/makefile b/src/usr/fsi/test/makefile
new file mode 100644
index 000000000..4c3fd7e8d
--- /dev/null
+++ b/src/usr/fsi/test/makefile
@@ -0,0 +1,29 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/fsi/test/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../../..
+
+MODULE = testfsi
+TESTS = *.H
+
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/makefile b/src/usr/makefile
index c1ba0e5e6..55dcb704c 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -25,7 +25,7 @@ ROOTPATH = ../..
OBJS = module_init.o
SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \
- scom.d xscom.d targeting.d initservice.d hwpf.d \
- ecmddatabuffer.d isteps.d pnor.d vfs.d i2c.d
+ scom.d xscom.d targeting.d initservice.d hwpf.d \
+ ecmddatabuffer.d isteps.d pnor.d i2c.d vfs.d fsi.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/xscom/xscom.C b/src/usr/xscom/xscom.C
index 179e8dc31..c893c5c09 100644
--- a/src/usr/xscom/xscom.C
+++ b/src/usr/xscom/xscom.C
@@ -426,6 +426,9 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
mutex_t* l_XSComMutex;
uint64_t l_addr = va_arg(i_args,uint64_t);
+ //@todo - Override the target to be the master sentinel
+ i_target = TARGETING::MASTER_PROCESSOR_CHIP_TARGET_SENTINEL;
+
// Retry loop
bool l_retry = false;
uint8_t l_retryCtr = 0;
@@ -542,28 +545,28 @@ errlHndl_t xscomPerformOp(DeviceFW::OperationType i_opType,
// Done, un-pin
task_affinity_unpin();
- TRACFCOMP(g_trac_xscom, "xscomPerformOp: OpType 0x%llX, Address 0x%llX, MMIO Address 0x%llX",
+ TRACFCOMP(g_trac_xscom, "xscomPerformOp: OpType 0x%.16llX, Address 0x%llX, MMIO Address 0x%llX",
static_cast<uint64_t>(i_opType),
l_addr,
static_cast<uint64_t>(l_mmioAddr));
- TRACFCOMP(g_trac_xscom, "xscomPerformOp: l_offset 0x%llX; VirtAddr %p; l_virtAddr+l_offset %p",
+ TRACFCOMP(g_trac_xscom, "xscomPerformOp: l_offset 0x%.16llX; VirtAddr %p; l_virtAddr+l_offset %p",
l_offset,
l_virtAddr,
l_virtAddr + l_offset);
if (i_opType == DeviceFW::READ)
{
- TRACFCOMP(g_trac_xscom, "xscomPerformOp: Read data: %llx", l_data); }
+ TRACFCOMP(g_trac_xscom, "xscomPerformOp: Read data: %.16llx", l_data); }
else
{
- TRACFCOMP(g_trac_xscom, "xscomPerformOp: Write data: %llx", l_data);
+ TRACFCOMP(g_trac_xscom, "xscomPerformOp: Write data: %.16llx", l_data);
}
// Handle error
if (l_hmer.mXSComStatus != HMER::XSCOM_GOOD)
{
uint64_t l_hmerVal = l_hmer;
- TRACFCOMP(g_trac_xscom, ERR_MRK "XSCOM status error HMER: %llx, XSComStatus %llx",
+ TRACFCOMP(g_trac_xscom, ERR_MRK "XSCOM status error HMER: %.16llx, XSComStatus %llx",
l_hmerVal, l_hmer.mXSComStatus);
/*@
* @errortype
OpenPOWER on IntegriCloud