summaryrefslogtreecommitdiffstats
path: root/src/usr/pore/poreve/porevesrc
diff options
context:
space:
mode:
authorThi Tran <thi@us.ibm.com>2012-01-13 10:29:25 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-02-07 13:49:45 -0600
commit859335d953a59c25de64a414c344d0a22d0911cb (patch)
treec606dbbbe0cbbfa3275ca0d644ac417e258b84b9 /src/usr/pore/poreve/porevesrc
parent0f454c096f27c06cb93ad442c0e14fc734464867 (diff)
downloadtalos-hostboot-859335d953a59c25de64a414c344d0a22d0911cb.tar.gz
talos-hostboot-859335d953a59c25de64a414c344d0a22d0911cb.zip
Initial VSBE Supports
Fixed test case failure Change-Id: Ie388aebddacba99dfc6cc04e5fe98f0e8ca8b4bd Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/520 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/pore/poreve/porevesrc')
-rw-r--r--src/usr/pore/poreve/porevesrc/bus.C900
-rw-r--r--src/usr/pore/poreve/porevesrc/bus.H661
-rw-r--r--src/usr/pore/poreve/porevesrc/create.C46
-rw-r--r--src/usr/pore/poreve/porevesrc/fasti2c.C604
-rw-r--r--src/usr/pore/poreve/porevesrc/fasti2c.H564
-rw-r--r--src/usr/pore/poreve/porevesrc/hookmanager.C575
-rw-r--r--src/usr/pore/poreve/porevesrc/hookmanager.H859
-rw-r--r--src/usr/pore/poreve/porevesrc/pib2cfam.C167
-rw-r--r--src/usr/pore/poreve/porevesrc/pib2cfam.H94
-rw-r--r--src/usr/pore/poreve/porevesrc/pore.C269
-rw-r--r--src/usr/pore/poreve/porevesrc/pore.H259
-rw-r--r--src/usr/pore/poreve/porevesrc/poreve.C480
-rw-r--r--src/usr/pore/poreve/porevesrc/poreve.H535
-rw-r--r--src/usr/pore/poreve/porevesrc/sbevital.C82
-rw-r--r--src/usr/pore/poreve/porevesrc/sbevital.H85
15 files changed, 6180 insertions, 0 deletions
diff --git a/src/usr/pore/poreve/porevesrc/bus.C b/src/usr/pore/poreve/porevesrc/bus.C
new file mode 100644
index 000000000..fdf3e90a5
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/bus.C
@@ -0,0 +1,900 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/bus.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// $Id: bus.C,v 1.22 2012/01/05 23:15:54 bcbrock Exp $
+
+/// \file bus.C
+/// \brief PoreVe bus and base device models
+
+#include "bus.H"
+#include <fapi.H>
+#include <transaction.H>
+
+
+
+using namespace vsbe;
+
+//-----------------------------------------------------------------------------
+Bus::Bus() :
+ iv_primarySlaves(NULL),
+ iv_secondarySlaves(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+Bus::~Bus()
+{
+}
+
+//-----------------------------------------------------------------------------
+void
+Bus::attachPrimarySlave(Slave* i_slave)
+{
+ if( iv_primarySlaves == 0 )
+ {
+ i_slave->iv_next = 0;
+ }else{
+ i_slave->iv_next = iv_primarySlaves;
+ }
+ iv_primarySlaves = i_slave;
+}
+
+//-----------------------------------------------------------------------------
+void
+Bus::attachSecondarySlave(Slave* i_slave)
+{
+ if( iv_secondarySlaves == 0 )
+ {
+ i_slave->iv_next = 0;
+ }else{
+ i_slave->iv_next = iv_secondarySlaves;
+ }
+ iv_secondarySlaves = i_slave;
+}
+
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+Bus::operation(Transaction& trans)
+{
+ fapi::ReturnCode rc;
+ Slave* slave= 0;
+
+ do
+ {
+ for( slave = iv_primarySlaves; slave; slave = slave->iv_next )
+ {
+ if( (trans.iv_address >= slave->iv_base) && (trans.iv_address < (slave->iv_base + slave->iv_size) ) )
+ {
+ break; // found a primary slave
+ }
+ }
+
+ if( slave == 0 )
+ { // primary slaves did not hold the transaction address. Try using the secondary slaves.
+ for( slave = iv_secondarySlaves; slave; slave = slave->iv_next )
+ {
+ if( (trans.iv_address >= slave->iv_base) && (trans.iv_address < (slave->iv_base + slave->iv_size) ) )
+ {
+ break; // found a secondary slave
+ }
+ }
+ }
+
+ break;
+
+ }while(0);
+
+ do
+ {
+ if( slave == 0 ) // neither primary nor secondary slaves held the address
+ {
+ trans.busError(ME_NOT_MAPPED_ON_BUS);
+ rc= 1;
+ break;
+ }
+
+ if( (trans.iv_mode & slave->iv_permissions) == 0 ){
+ trans.busError(ME_BUS_SLAVE_PERMISSION_DENIED);
+ rc= 1;
+ break;
+ }
+
+ trans.iv_offset = trans.iv_address - slave->iv_base;
+ rc = slave->operation( trans );
+ break;
+ }while(1);
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+Slave::Slave()
+:iv_base(0), iv_size(0), iv_permissions(0),
+iv_next(NULL), iv_target(NULL), iv_dataBuffer(NULL)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+Slave::~Slave()
+{
+}
+
+//-----------------------------------------------------------------------------
+PibSlave::PibSlave()
+{
+}
+
+//-----------------------------------------------------------------------------
+PibSlave::~PibSlave()
+{
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+PibSlave::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ PibTransaction* pt = (PibTransaction*)&io_transaction;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ rc = getScom( io_transaction.iv_address, io_transaction.iv_data );
+ }
+ else
+ {
+ rc = putScom( io_transaction.iv_address, io_transaction.iv_data );
+ }
+
+ if( rc.ok() )
+ {
+ pt->iv_pcbReturnCode = PCB_SUCCESS;
+ }
+ else
+ {
+ if( rc & fapi_PCB_RESOURCE_BUSY ){
+ pt->iv_pcbReturnCode = PCB_RESOURCE_OCCUPIED;
+ }else if( rc & fapi_PCB_OFFLINE_ERROR ){
+ pt->iv_pcbReturnCode = PCB_CHIPLET_OFFLINE;
+ }else if( rc & fapi_PCB_PARTIAL_ERROR ){
+ pt->iv_pcbReturnCode = PCB_PARTIAL_GOOD;
+ }else if( rc & fapi_PCB_ADDRESS_ERROR ){
+ pt->iv_pcbReturnCode = PCB_ADDRESS_ERROR;
+ }else if( rc & fapi_PCB_CLOCK_ERROR ){
+ pt->iv_pcbReturnCode = PCB_CLOCK_ERROR;
+ }else if( rc & fapi_PCB_PARITY_ERROR ){
+ pt->iv_pcbReturnCode = PCB_PACKET_ERROR;
+ }else if( rc & fapi_PCB_TIMEOUT_ERROR ){
+ pt->iv_pcbReturnCode = PCB_TIMEOUT;
+ }else{
+ pt->iv_pcbReturnCode = PCB_TIMEOUT;
+ }
+ rc = 0;
+ }
+
+ io_transaction.iv_modelError = ME_SUCCESS;
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+void
+Slave::configure(
+ fapi::Target* i_target,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions
+ )
+{
+ iv_target = i_target;
+ iv_dataBuffer = i_dataBuffer;
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_next = NULL;
+}
+
+
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+PibSlave::getScom(const uint32_t i_offset, uint64_t& o_data)
+{
+ fapi::ReturnCode rc;
+ rc = fapiGetScom( *iv_target, i_offset, *iv_dataBuffer );
+ o_data = iv_dataBuffer->getDoubleWord( 0 );
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+PibSlave::putScom(const uint32_t i_offset, const uint64_t i_data)
+{
+ fapi::ReturnCode rc;
+ iv_dataBuffer->setDoubleWordLength( 1 );
+ iv_dataBuffer->setDoubleWord( 0, i_data );
+ rc = fapiPutScom( *iv_target, i_offset, *iv_dataBuffer );
+
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+PibMemory::PibMemory() :
+iv_passThrough(false),iv_memory(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+PibMemory::~PibMemory()
+{
+}
+
+//-----------------------------------------------------------------------------
+void
+PibMemory::setPassThrough(const bool i_enable)
+{
+ iv_passThrough = i_enable;
+}
+
+//-----------------------------------------------------------------------------
+void
+PibMemory::configure(
+ fapi::Target* i_target,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory
+ )
+{
+ iv_target = i_target;
+ iv_dataBuffer = i_dataBuffer;
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_memory = i_memory;
+ iv_next = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+fapi::ReturnCode
+PibMemory::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ me = iv_memory->read( (uint32_t)(io_transaction.iv_offset * TRANSACTION_SIZE_IN_BYTES), io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = getScom( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+ else if( io_transaction.iv_mode & ACCESS_MODE_WRITE )
+ {
+ me = iv_memory->write( (uint32_t)(io_transaction.iv_offset * TRANSACTION_SIZE_IN_BYTES), io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = putScom( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ me = iv_memory->fetch( (uint32_t)(io_transaction.iv_offset * TRANSACTION_SIZE_IN_BYTES), io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = getScom( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+
+ io_transaction.busError( me );
+
+ if( me == ME_SUCCESS )
+ {
+ rc = (uint32_t)0; // if read/write or getScom/putScom succeeded then set rc = 0
+ }
+
+ // if read/write failed then rc == 1 by default
+ // if read/write returned ME_NOT_MAPPED_IN_MEMORY && pass through true then rc == value returned from putScom or getScom
+
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+Memory::Memory() :
+ iv_images(0)
+{
+#if POREVE_STATISTICS
+ resetStatistics();
+#endif
+}
+
+//-----------------------------------------------------------------------------
+Memory::~Memory()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool
+Memory::checkCrc()
+{
+ MemoryImage* mi = iv_images;
+ bool rc = true;
+
+ do{
+
+ if( mi->checkCrc() == false )
+ {
+ rc = false;
+ break;
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::read(
+ uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ )
+{
+ char* from_ptr;
+ char* to_ptr;
+ size_t cnt;
+ MemoryImage* mi;
+ ModelError me;
+ int mi_found;
+
+ o_data = 0; // Assure all bytes are cleared
+
+ me = ME_SUCCESS;
+ do{
+ if( iv_images == 0 )
+ {
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+ mi = iv_images;
+ mi_found = 0;
+ do{
+
+ if( (i_offset >= mi->iv_base) && ((i_offset + i_size) <= (mi->iv_base + mi->iv_size) ) )
+ {
+ mi_found= 1;
+ iv_images = mi; // have the Memory always point to the last MemoryImage that was used
+ break; // we found a chunk of memory containing the transaction address
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ if( ! mi_found )
+ { // There was no MemoryImage that contained the transaction address
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+
+ if( (mi->iv_permissions & ACCESS_MODE_READ ) == 0 )
+ { // The permissions over the memory block do not allow the mode being used by the transaction
+ me = ME_MEMORY_IMAGE_PERMISSION_DENIED;
+ break;
+ }
+
+ // Init the character pointer into the eprom image we are using.
+ from_ptr = (char*)mi->iv_image + (i_offset - mi->iv_base);
+
+ // Init the character pointer into the o_data buffer.
+ // Take care of Endianess by moving to one or the other end of the buffer as appropriate.
+#ifdef _BIG_ENDIAN
+ to_ptr = (char*)&o_data + (TRANSACTION_SIZE_IN_BYTES - i_size);
+#else
+ to_ptr = ((char*)&o_data + i_size -1);
+#endif
+
+ for( cnt = 0; cnt < i_size; cnt++ )
+ {
+ *to_ptr = *from_ptr++;
+
+ // Move the to pointer either forward or backward as appropriate for Endianess
+#ifdef _BIG_ENDIAN
+ to_ptr++;
+#else
+ to_ptr--;
+#endif
+ }
+
+ me = ME_SUCCESS;
+ break;
+ }while(1);
+
+#if POREVE_STATISTICS
+ iv_reads++;
+#endif
+
+ return me;
+}
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::fetch(
+ uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ )
+{
+ char* from_ptr;
+ char* to_ptr;
+ size_t cnt;
+ MemoryImage* mi;
+ ModelError me;
+ int mi_found;
+
+ o_data = 0; // Assure all bytes are cleared
+
+ me = ME_SUCCESS;
+ do{
+ if( iv_images == 0 )
+ {
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+ mi = iv_images;
+ mi_found = 0;
+ do{
+
+ if( (i_offset >= mi->iv_base) && ((i_offset + i_size) <= (mi->iv_base + mi->iv_size) ) )
+ {
+ mi_found= 1;
+ iv_images = mi; // have the Memory always point to the last MemoryImage that was used
+ break; // we found a chunk of memory containing the transaction address
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ if( ! mi_found )
+ { // There was no MemoryImage that contained the transaction address
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+
+ if( (mi->iv_permissions & ACCESS_MODE_EXECUTE ) == 0 )
+ { // The permissions over the memory block do not allow the mode being used by the transaction
+ me = ME_MEMORY_IMAGE_PERMISSION_DENIED;
+ break;
+ }
+
+ // Init the character pointer into the eprom image we are using.
+ from_ptr = (char*)mi->iv_image + i_offset;
+
+ // Init the character pointer into the o_data buffer.
+ // Take care of Endianess by moving to one or the other end of the buffer as appropriate.
+#ifdef _BIG_ENDIAN
+ to_ptr = (char*)&o_data + (TRANSACTION_SIZE_IN_BYTES - i_size);
+#else
+ to_ptr = ((char*)&o_data + i_size -1);
+#endif
+
+ for( cnt = 0; cnt < i_size; cnt++ )
+ {
+ *to_ptr = *from_ptr++;
+
+ // Move the to pointer either forward or backward as appropriate for Endianess
+#ifdef _BIG_ENDIAN
+ to_ptr++;
+#else
+ to_ptr--;
+#endif
+ }
+
+ me = ME_SUCCESS;
+ break;
+ }while(1);
+
+#if POREVE_STATISTICS
+ iv_fetches++;
+#endif
+
+ return me;
+}
+
+
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::write(
+ uint32_t i_offset, // the address in the eprom image
+ uint64_t i_data, // data to write into the eprom image
+ size_t i_size // number of bytes to write (pretty much going to be TRANSACTION_SIZE_IN_BYTES)
+ )
+{
+ char* to_ptr;
+ char* from_ptr;
+ size_t cnt;
+ MemoryImage* mi;
+ ModelError me;
+ int mi_found;
+
+ me = ME_SUCCESS;
+ do{
+ if( iv_images == 0 )
+ {
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+ mi = iv_images;
+ mi_found = 0;
+ do{
+
+ if( (i_offset >= mi->iv_base) && ((i_offset + i_size) <= (mi->iv_base + mi->iv_size) ) )
+ {
+ mi_found= 1;
+ iv_images = mi; // have the Memory always point to the last MemoryImage that was used
+ break; // we found a chunk of memory containing the transaction address
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ if( ! mi_found )
+ { // There was no MemoryImage that contained the transaction address
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+
+ if( (mi->iv_permissions & ACCESS_MODE_WRITE ) == 0 )
+ { // The permissions over the memory block do not allow the mode being used by the transaction
+ me = ME_MEMORY_IMAGE_PERMISSION_DENIED;
+ break;
+ }
+
+ // Init the character pointer into the eprom image we are using.
+ to_ptr = (char*)mi->iv_image + i_offset;
+
+ // Init the character pointer into the o_data buffer.
+ // Take care of Endianess by moving to one or the other end of the buffer as appropriate.
+#ifdef _BIG_ENDIAN
+ from_ptr = (char*)&i_data + (TRANSACTION_SIZE_IN_BYTES - i_size);
+#else
+ from_ptr = ((char*)&i_data + i_size -1);
+#endif
+
+ for( cnt = 0; cnt < i_size; cnt++ )
+ {
+ *to_ptr++ = *from_ptr;
+
+ // Move the to pointer either forward or backward as appropriate for Endianess
+#ifdef _BIG_ENDIAN
+ from_ptr++;
+#else
+ from_ptr--;
+#endif
+ }
+
+ me = ME_SUCCESS;
+ break;
+
+ }while(1);
+
+#if POREVE_STATISTICS
+ iv_writes++;
+#endif
+
+ return me;
+}
+
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::map(
+ uint32_t i_base, // For direct memory this is the 0 based offset from the Slave iv_base
+ size_t i_size, // Size of this chunk of memory
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable
+ )
+{
+ ModelError me = ME_SUCCESS;
+ MemoryImage* n;
+ MemoryImage* mi = new MemoryImage( i_base, i_size, i_permissions, i_image, i_crcEnable );
+
+ if( iv_images == 0 )
+ {
+ iv_images = mi;
+ mi->iv_next = mi;
+ }else{
+ n = iv_images->iv_next;
+ while( n->iv_next != iv_images )
+ {
+ n = n->iv_next;
+ }
+ n->iv_next = mi;
+ mi->iv_next = iv_images;
+ }
+
+ return me;
+}
+
+
+//-----------------------------------------------------------------------------
+#if POREVE_STATISTICS
+void
+Memory::resetStatistics()
+{
+ iv_reads = 0;
+ iv_writes = 0;
+ iv_fetches = 0;
+}
+#endif // POREVE_STATISTICS
+
+
+//-----------------------------------------------------------------------------
+MemoryImage::MemoryImage(
+ uint32_t i_base,
+ size_t i_size,
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable
+ )
+{
+
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_image = i_image;
+ iv_crcEnable = i_crcEnable;
+ iv_originalCrc = 0;
+ iv_next = NULL;
+
+ if( i_crcEnable )
+ {
+ iv_originalCrc = computeCrc();
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+MemoryImage::~MemoryImage()
+{
+}
+
+//-----------------------------------------------------------------------------
+uint64_t
+MemoryImage::computeCrc()
+{
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+bool
+MemoryImage::checkCrc()
+{
+ bool result = true;
+
+ if( iv_crcEnable == true )
+ {
+ uint64_t current_crc = computeCrc();
+ if( current_crc != iv_originalCrc )
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+OciMemory::OciMemory() :
+iv_memory(NULL), iv_passThrough(false)
+{
+}
+
+//-----------------------------------------------------------------------------
+OciMemory::~OciMemory()
+{
+}
+
+//-----------------------------------------------------------------------------
+void
+OciMemory::setPassThrough(const bool i_enable)
+{
+ iv_passThrough = i_enable;
+}
+
+//-----------------------------------------------------------------------------
+void
+OciMemory::configure(
+ fapi::Target* i_target,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory
+ )
+{
+ iv_target = i_target;
+ iv_dataBuffer = i_dataBuffer;
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_memory = i_memory;
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+fapi::ReturnCode
+OciMemory::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+
+ ModelError me;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ me = iv_memory->read( (uint32_t)io_transaction.iv_offset, io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = read( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ me = iv_memory->write( (uint32_t)io_transaction.iv_offset, io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = write( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+
+ io_transaction.busError( me );
+
+ if( me == ME_SUCCESS )
+ {
+ rc = (uint32_t)0;
+ }
+
+ // if read/write failed then rc == 1 by default
+ // if read/write returned ME_NOT_MAPPED_IN_MEMORY && pass through true then
+ // rc == value returned from putScom or getScom
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlave::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ rc = read( io_transaction.iv_address, io_transaction.iv_data );
+ }
+ else
+ {
+ rc = write( io_transaction.iv_address, io_transaction.iv_data );
+ }
+
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+
+ io_transaction.busError( me );
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+OciSlave::~OciSlave()
+{
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlave::read(const uint32_t i_address, uint64_t& o_data)
+{
+ fapi::ReturnCode rc;
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlave::write(const uint32_t i_address, const uint64_t i_data)
+{
+ fapi::ReturnCode rc;
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlaveWritable::write(const uint32_t i_address, const uint64_t i_data)
+{
+
+ // For this model, print out a message to confirm a write has been written is all it needs.
+ FAPI_INF("OciSlaveWritable::write(0x%08x, 0x%016llx)",
+ i_address, i_data);
+ fapi::ReturnCode rc;
+ return rc;
+}
+
diff --git a/src/usr/pore/poreve/porevesrc/bus.H b/src/usr/pore/poreve/porevesrc/bus.H
new file mode 100644
index 000000000..6370bae84
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/bus.H
@@ -0,0 +1,661 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/bus.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_BUS_H
+#define __VSBE_BUS_H
+
+// $Id: bus.H,v 1.14 2011/12/16 21:47:59 bcbrock Exp $
+
+/// \file bus.H
+/// \brief PoreVe bus and base device models
+
+#include <fapi.H>
+#include "transaction.H"
+
+
+namespace vsbe
+{
+
+class Slave;
+class Memory;
+
+// Temporary FAPI return codes from getscom/putscom errors
+#define fapi_PCB_RESOURCE_BUSY 0x02014003
+#define fapi_PCB_OFFLINE_ERROR 0x02014005
+#define fapi_PCB_PARTIAL_ERROR 0x02014007
+#define fapi_PCB_ADDRESS_ERROR 0x02014009
+#define fapi_PCB_CLOCK_ERROR 0x0201400B
+#define fapi_PCB_PARITY_ERROR 0x0201400D
+#define fapi_PCB_TIMEOUT_ERROR 0x0201400F
+
+//-----------------------------------------------------------------------------
+/*!
+The Pore hardware engine is connected via PIB bus and OCI bus. The Bus object
+functions to group all entities on the bus. For example, the PIB has the ability
+to run put/getscom via the PibSlave, as well as access OTPROM memory via the
+PibMemory object and PNOR and SEEPROM via FastI2cMemory objects.
+*/
+/// All pore hardware bus transactions are submitted through a Bus object.
+class Bus
+{
+
+public:
+
+ Bus();
+ virtual ~Bus();
+
+ /*! Primary Slaves are searched first for a given Transaction Address */
+ /// Primary Slaves are a linked list of Slave based objects
+ void attachPrimarySlave(Slave* i_slave);
+
+ /*! If a Secondary slave cannot service the Transaction then the Transaction address
+ is not mapped on the bus at all. */
+ /// Secondary Slaves are searched only if a Primary Slave did not support the Transaction Address
+ void attachSecondarySlave(Slave* i_slave);
+
+ /*!
+ The PrimarySlaves attached to the bus are checked to find one that handles the
+ Transaction address. If no match, then the SecondarySlaves are checked. When a
+ Slave is found containing the address the Transaction::iv_offset is set to the
+ Transaction::iv_address - Slave::iv_base. The Slave operation method is then
+ executed.
+
+ The return code from the Slave is passed back and becomes the return code of the
+ Bus operation. The Transaction ModelError is set by the Slave and is passed back
+ as well.
+
+ @returns If any error occurs then the fapi::ReturnCode is not ok, and the
+ transaction ModelError indicates the kind of problem found.
+
+ @returns rc=1 and Transaction ModelError=ME_NOT_MAPPED_ON_BUS if neither Primary
+ nor Secondary Slaves have mapped the transaction address.
+
+ @returns rc=1 and Transaction ModelError=ME_BUS_SLAVE_PERMISSION_DENIED if the
+ transaction address is found on a Slave but the Slave permissions deny the
+ transaction mode.
+
+ @returns rc=1 and Transaction ModelError= some other Model Error codes if the
+ Slave operation fails.
+
+ @returns rc=0 and Transaction ModelError=ME_SUCCESS if the transaction was
+ successful.
+ */
+ /// The basic method called to get a bus transaction done.
+ fapi::ReturnCode operation(Transaction& io_transaction);
+
+
+protected:
+
+ /// Primary list of "attached" bus elements like PibMemory, OciMemory and so forth
+ Slave* iv_primarySlaves;
+
+ /// The Secondary list is used when the Primary list fails to contain a Transaction address
+ Slave* iv_secondarySlaves;
+
+};
+
+//-----------------------------------------------------------------------------
+/*!
+Any kind of object attached to a Bus must be based upon the Slave class.
+Each of the Bus devices must specify their base address, size, and permissions
+as well as target and dataBuffer to be used for bus transactions. All these attributes
+are defined by the base Slave class.
+*/
+/// The Slave object contains the common attributes of all bus devices.
+class Slave
+{
+public:
+
+ Slave();
+ virtual ~Slave();
+
+ /// Slave based objects must be configured before use.
+ virtual void configure(fapi::Target* i_target,
+ ecmdDataBufferBase *i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions);
+
+ /*!
+ Notice that the operation is pure virtual in the Slave class. All derived bus attached
+ devices must define their own operation methods since they vary from one to the other.
+ */
+ /// The Slave class also defines the fundamental operation that a Bus can call.
+ virtual fapi::ReturnCode operation(Transaction& io_transaction) = 0; // the slave instance will implement
+
+ /*!
+ The iv_base address is specified in terms of the system, so for example it might be the first address
+ in a range beginning at 0x08000000 in the system memory, or it might be the first address in a range of
+ scom addresses in the system.
+ */
+ /// The Bus devices base address. A System memory address or scom address, not an offset.
+ uint32_t iv_base;
+
+ /// This specifies the number of bytes from the iv_base that this Bus device responds to.
+ uint64_t iv_size;
+
+ /*!
+ For example: ACCESS_MODE_READ | ACCESS_MODE_WRITE | ACCESS_MODE_EXECUTE
+ */
+ /// Establish the read/write/execute mode allowed upon this Bus device.
+ int iv_permissions;
+
+ /// Points to the next Slave in a linked list that the Bus::operation will search
+ Slave* iv_next;
+
+ /// A pointer to the fapi Target to be used when accessing this Bus device.
+ fapi::Target* iv_target;
+
+ /// A pointer to the fapi DataBuffer to be used when accessing this Bus device.
+ ecmdDataBufferBase* iv_dataBuffer;
+
+
+};
+
+
+//-----------------------------------------------------------------------------
+/*!
+The SCOM addresses of a system are defined by a call to configure to the PIB
+slave for the system. There is no mapping done since there is no memory manager
+involved. When the PIB bus manager is asked to perform an operation and if the
+Transaction iv_address falls into the address range of the SCOM's then the
+operation method for the Slave will be called, which will call the
+PibSlave::getScom/putScom implemnted with fapiGet/Putscom.
+*/
+/// Implements SCOM access to the system.
+class PibSlave : public Slave
+{
+public:
+
+ PibSlave();
+ virtual ~PibSlave();
+
+ /// Overriding Slave::operation
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+protected:
+
+ /*!
+ The i_offset is an actual scom address that has not been changed to implement
+ "core reduction" as an eCMD address might for certain chiplets. The address is
+ the raw native SCOM address used by the hardware.
+
+ The calling Slave class object iv_target and iv_dataBuffer are used to perform
+ the operation.
+
+ @returns rc= the value returned by fapi::GetScom
+ */
+ /// PibSlave read calls fapi::GetScom
+ fapi::ReturnCode getScom(const uint32_t i_offset, uint64_t& o_data);
+
+ /*!
+ The i_offset is an actual scom address that has not been changed to implement
+ "core reduction" as an eCMD address might for certain chiplets. The address is
+ the raw native SCOM address used by the hardware.
+
+ The calling Slave class object iv_target and iv_dataBuffer are used to perform
+ the operation.
+
+ @returns rc= the value returned by fapi::PutScom
+ */
+ /// PibSlave write calls fapi::PutScom
+ fapi::ReturnCode putScom(const uint32_t i_offset, const uint64_t i_data);
+};
+
+//-----------------------------------------------------------------------------
+/*!
+This object has (virtual) methods to handle directly access memory.
+*/
+/// Methods Used to access OTPROM.
+class PibMemory : public PibSlave
+{
+public:
+
+ PibMemory();
+ virtual ~PibMemory();
+
+
+ /// Slave based objects must be configured before use.
+ virtual void configure(fapi::Target* i_target,
+ ecmdDataBufferBase *i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory);
+
+ /*!
+ Pass-through mode is established with a true value. This mode means that if a
+ PibMemory address is NOT_MAPPED_IN_MEMORY then the address of a transaction is
+ passed-through to the PibSlave::getScom or PibSlave::putScom method for resolution.
+ */
+ /// Control the pass-through mode. True means pass-through mode is enabled.
+ void setPassThrough(const bool i_enable);
+
+ /*!
+ Bus::operation already made sure the Transaction address is within our chunk of
+ memory and has set the Transaction::iv_offset.
+
+ This operation accesses direct memory, like OTPROM.
+
+ Transactions give us addresses on 64bit , or 8 byte, boundries. The address
+ passed into Memory::read or write is calculated as the Transaction::iv_offset *
+ 8. So, as example, if the Transaction::_iv_address was 0x08000000 and the
+ PibMemory Slave::iv_base were configured to 0x08000000 then the
+ Transaction::iv_offset would be 0x00000000. That multiplied by 8 remains
+ 0x00000000. If the Transaction address were 0x08000001, then the Transaction
+ offset would be 0x00000001, and that multiplied by 8 would be 0x00000008, the
+ reall offset into the eprom image we will read or write from.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::read method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::read
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ PibSlave::getScom is called passing the Transaction iv_address.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::write method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::write
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ PibSlave::putScom is called passing the Transaction iv_address.
+
+ @returns rc=0 if transaction succeeded
+ @returns rc=1 if transaction failed and passThrough mode was not active
+ @returns rc!=0 if read/write failed and passThrough call to getScom/putScom also
+ failed. In this case the rc value is whatever getScom or putScom returns from
+ fapi.
+
+ */
+ /// Implement a PibMemory transaction. Called by the Bus::operation()
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+protected:
+
+ /// Remember the pass-through mode setting
+ bool iv_passThrough;
+
+ /// Pointer to Memory manager storing a linked list of MemoryImage (s) "containing" mapped memory areas
+ Memory* iv_memory;
+
+};
+
+//-----------------------------------------------------------------------------
+/// Not sure what a OciSlave does yet
+class OciSlave : public Slave
+{
+public:
+
+ virtual ~OciSlave();
+
+ /*!
+ Bus::operation already made sure the Transaction address is within our chunk of
+ memory and has set the Transaction::iv_offset.
+
+ If a ACCESS_MODE_READ transaction is called for then the OciSlave::read method is
+ called passing the Transaction iv_address to complete the operation.
+
+ If a ACCESS_MODE_WRITE transaction is called for then the OciSlave::write method is
+ called passing the Transaction iv_address to complete the operation.
+
+ @returns rc=0 if transaction succeeded
+ @returns rc=1 if transaction failed
+
+ */
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+protected:
+
+ /*!
+ Called by OciSlave::operation.
+ */
+ virtual fapi::ReturnCode read(const uint32_t i_address, uint64_t& o_data);
+
+ /*!
+ Called by OciSlave::operation.
+ */
+ virtual fapi::ReturnCode write(const uint32_t i_address, const uint64_t i_data);
+
+};
+
+//-----------------------------------------------------------------------------
+/// An OciSlave that accepts and simply swallows write transactions
+class OciSlaveWritable : public OciSlave
+{
+public:
+ virtual fapi::ReturnCode write(const uint32_t i_address, const uint64_t i_data);
+};
+
+//-----------------------------------------------------------------------------
+/// Methods Used to access Mainstore/SRAM
+class OciMemory : public OciSlave
+{
+public:
+
+ OciMemory();
+ virtual ~OciMemory();
+
+ /// Slave based objects must be configured before use.
+ virtual void configure(fapi::Target* i_target,
+ ecmdDataBufferBase *i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory);
+
+ /*!
+ Bus::operation already made sure the Transaction address is within our chunk of
+ memory and has set the Transaction::iv_offset.
+
+ This operation accesses memory like Mainstore or SRAM memory.
+
+ Transactions to the OCI bus give us addresses on byte boundries. The offset
+ passed into Memory::read or write is therefore simply the
+ Transaction::iv_offset without modification.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::read method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::read
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ OciSlave::read is called passing the Transaction iv_address.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::write method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::write
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ OciSlave::write is called passing the Transaction iv_address.
+
+ @returns rc=0 if transaction succeeded
+ @returns rc=1 if transaction failed and passThrough mode was not active
+ @returns rc!=0 if read/write failed and passThrough call to OciSlave::read/write also
+ failed. In this case the rc value is whatever OciSlave::read or OciSlave::write returns.
+ */
+ /// Implement a OciMemory transaction. Called by the Bus::operation()
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+ /*!
+ Pass-through mode is established with a true value. This mode means that if a
+ OciMemory address is NOT_MAPPED_IN_MEMORY then the address of a transaction is
+ passed-through to the OciSlave::read or OciSlave::write method for resolution.
+ */
+ /// Control the pass-through mode. True means pass-through mode is enabled.
+ void setPassThrough(const bool i_enable);
+
+ /// Pointer to Memory manager storing a linked list of MemoryImage (s) "containing" mapped memory areas
+ Memory *iv_memory;
+
+protected:
+
+ /// Remember the pass-through mode setting
+ bool iv_passThrough;
+};
+
+
+//-----------------------------------------------------------------------------
+/// Store details of a block of memory being managed by a Memory manager
+class MemoryImage
+{
+public:
+
+ /*!
+ A MemoryImage is used to store information about a portion of Memory that has been mapped.
+ It is created by the Memory::map method.
+
+ @param i_base A zero based offset from the Slave iv_base address
+ @param i_size Size of i_image in bytes
+ @param i_permissions The read/write/execute permissions over this block of memory
+ @param i_image A pointer to an allocated block of memory storing the content of the block of memory
+ @param i_crcEnable true or false indicating whether crc is to be calculated over the block of memory
+ */
+ MemoryImage(uint32_t i_base,
+ size_t i_size,
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable );
+
+ virtual ~MemoryImage();
+
+ /*!
+ When this method is called the crc of the associated MemoryImage is calculated
+ and compared to iv_originalCrc which was the crc value at the time that the
+ MemoryImage was mapped into the Memory.
+
+ @returns true if iv_originalCrc == the current crc of the MemoryImage or if crc
+ checking is not enabled for the MemoryImage.
+ @returns false if crc checking is enabled and the crc values do not match.
+ */
+ /// true if iv_originalCrc == current crc, or if iv_crcEnable == false
+ virtual bool checkCrc();
+
+ /// base address associated with iv_image in the system (not real address of iv_image)
+ uint32_t iv_base;
+
+ /// byte size of the block of memory pointed to by iv_image
+ size_t iv_size;
+
+ /// Access permissions over this block of memory (ACCESS_MODE_READ | ACCESS_MODE_WRITE | ACCESS_MODE_EXECUTE)
+ int iv_permissions;
+
+ /// Pointer to the chunk of memory a user has allocated and stored eprom image into
+ void* iv_image;
+
+ /// Remember if told to compute crc or not via i_crcEnable
+ bool iv_crcEnable;
+
+ /// Link to next MemoryImage in the Memory managers circular linked list
+ MemoryImage* iv_next;
+
+protected:
+
+ /// Method to calculate crc over iv_image
+ virtual uint64_t computeCrc();
+
+ /// If iv_crcEnable is true this is the calculated crc over iv_image at the time it was mapped into Memory
+ uint64_t iv_originalCrc;
+};
+
+//-----------------------------------------------------------------------------
+/// Contains one or many MemoryImages for a certain type of memory
+class Memory
+{
+public:
+
+ Memory();
+ virtual ~Memory();
+
+ /*!
+ The map method is used to register a pointer to a contiguous block of memory
+ that contains some part of an eeprom image, as well as to declare the offset
+ from the system base address, the size, and access permissions of that block of
+ memory.
+
+ The iv_images pointer of the Memory manager points to one or many MemoryImages.
+ Each time this map method is called a new MemoryImage object is created to
+ remember all the details about the i_image being passed in. The new MemoryImage
+ is placed into a circular linked list owned by the Memory manager.
+
+ The Memory manager is always associated with a particuliar kind of memory, like
+ PibMemory or OciMemory, so the i_image is some portion of PibMemory or
+ OciMemory. As an example, suppose OTPROM is 0x01000000 bytes in the system,
+ starting at address 0x80000000. Also suppose you have parts of the OTPROM from
+ 0x80000000 to 0x80000100 and from 0x80010000 to 0x80010500 in two image files
+ that you have read into program memory and you want to map into the OTPROM
+ Memory manager. When calling the configure method on the PibMemory you declare
+ OTPROM memory starts at 0x80000000 and has 0x01000000 bytes. Then you call map
+ on the PibMemory manager twice, first declaring an offset 0x00000000 for
+ 0x00000100 bytes, then again with offset 0x00010000 for 0x00000500 bytes.
+
+ @param i_base A zero based offset from the Slave iv_base address
+ @param i_size Size of i_image in bytes
+ @param i_permissions The read/write/execute permissions over this block of memory
+ @param i_image A pointer to an allocated block of memory storing the content of the block of memory
+ @param i_crcEnable true or false indicating whether crc is to be calculated over the block of memory
+ @returns ME_SUCCESS if all's well (currently that's all it can return)
+ */
+ /// Register a "chunk" of memory to the Memory manager
+ virtual ModelError map(uint32_t i_base,
+ size_t i_size,
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable);
+
+ /*!
+ This method runs through every MemoryImage checking its crc.
+
+ @returns true if all MemoryImage have the same crc as when they were originally mapped into Memory
+ @returns false if any MemoryImage has a crc that is different
+ */
+ /// Check if crc of all MemoryImages is still the same as when it was originally mapped into Memory
+ virtual bool checkCrc();
+
+ /*!
+ This method is used to read Direct Memory out of an eprom image. An offset from
+ the base of the eprom memory image is passed in for the access, along with the
+ number of bytes to read.
+
+ The memory storage may be split into more than one MemoryImage's that have been
+ mapped. This method runs through the circuliarly linked list of MemoryImage objects
+ looking for one that contains the block of memory being accessed.
+
+ Upon successfully finding a containing MemoryImage the Memory::iv_images is set
+ to point to the MemoryImage just found. This should speed up operation assuming
+ a large number of transactions might occur on contiguous blocks of memory.
+
+ The data are copied out of the MemoryImage::iv_image into the o_data buffer for
+ return. The Endianess of the host platform being used is considered as this
+ operation occurs. (It is assumed the MemoryImage::iv_image is stored in
+ BigEndian order.)
+
+ @returns If there is no MemoryImage that contains the block of memory requested
+ then ME_NOT_MAPPED_IN_MEMORY is returned.
+
+ @returns If the memory block is found within a MemoryImage but the
+ MemoryImage::iv_permissions do not permit ACCESS_MODE_READ then
+ ME_MEMORY_IMAGE_PERMISSION_DENIED is returned.
+
+ @returns ME_SUCCESS if all bytes of the memory requested are contained in the
+ MemoryImage and the permissions of the MemoryImage allow ACCESS_MODE_READ.
+
+ */
+ /// Used to find a MemoryImage from which to read data
+ virtual ModelError read(uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ );
+
+ /*!
+ This method is used to fetch instructions from Direct Memory out of an eprom
+ image. An offset from the base of the eprom memory image is passed in for the
+ access, along with the number of bytes to read.
+
+ The memory storage may be split into more than one MemoryImage's that have been
+ mapped. This method runs through the circuliarly linked list of MemoryImage objects
+ looking for one that contains the block of memory being accessed.
+
+ Upon successfully finding a containing MemoryImage the Memory::iv_images is set
+ to point to the MemoryImage just found. This should speed up operation assuming
+ a large number of transactions might occur on contiguous blocks of memory.
+
+ The data are copied out of the MemoryImage::iv_image into the o_data buffer for
+ return. The Endianess of the host platform being used is considered as this
+ operation occurs. (It is assumed the MemoryImage::iv_image is stored in
+ BigEndian order.)
+
+ @returns If there is no MemoryImage that contains the block of memory requested
+ then ME_NOT_MAPPED_IN_MEMORY is returned.
+
+ @returns If the memory block is found within a MemoryImage but the
+ MemoryImage::iv_permissions do not permit ACCESS_MODE_EXECUTE then
+ ME_MEMORY_IMAGE_PERMISSION_DENIED is returned.
+
+ @returns ME_SUCCESS if all bytes of the memory requested are contained in the
+ MemoryImage and the permissions of the MemoryImage allow ACCESS_MODE_EXECUTE.
+
+ */
+ /// Used to find a MemoryImage from which to fetch instructions
+ virtual ModelError fetch(uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ );
+
+ /*!
+ This method is used to write Direct Memory out of an eprom image. An offset from
+ the base of the eprom memory image is passed in for the access, along with the
+ number of bytes to write.
+
+ The memory storage may be split into more than one MemoryImage's that have been
+ mapped. This method runs through the circuliarly linked list of MemoryImage objects
+ looking for one that contains the block of memory being accessed.
+
+ Upon successfully finding a containing MemoryImage the Memory::iv_images is set
+ to point to the MemoryImage just found. This should speed up operation assuming
+ a large number of transactions might occur on contiguous blocks of memory.
+
+ The data are copied out of the i_data buffer into the MemoryImage::iv_image. The
+ Endianess of the host platform being used is considered as this operation
+ occurs. (It is assumed the MemoryImage::iv_image is stored in BigEndian order.)
+
+ @returns If there is no MemoryImage that contains the block of memory requested
+ then ME_NOT_MAPPED_IN_MEMORY is returned.
+
+ @returns If the memory block is found within a MemoryImage but the
+ MemoryImage::iv_permissions do not permit ACCESS_MODE_WRITE then
+ ME_MEMORY_IMAGE_PERMISSION_DENIED is returned.
+
+ @returns ME_SUCCESS if all bytes of the memory requested are contained in the
+ MemoryImage and the permissions of the MemoryImage allow ACCESS_MODE_WRITE.
+
+ */
+ /// Used to find a MemoryImage to change
+ virtual ModelError write(uint32_t i_offset,
+ uint64_t i_data,
+ size_t i_size);
+
+ /// Pointer to first MemoryImage in a circularly linked list
+ MemoryImage* iv_images;
+
+#if POREVE_STATISTICS
+
+ /// Reset Memory usage statistics
+ ///
+ /// This API clears the instance variables iv_reads, iv_writes and
+ /// iv_fetches.
+ void
+ resetStatistics();
+
+ /// Number of read() calls for this memory
+ uint64_t iv_reads;
+
+ /// Number of write() calls for this memory
+ uint64_t iv_writes;
+
+ /// Number of fetch() calls for this memory
+ uint64_t iv_fetches;
+
+#endif // POREVE_STATISTICS
+
+};
+
+
+
+
+
+
+
+
+
+} // end of namespace vsbe
+#endif
diff --git a/src/usr/pore/poreve/porevesrc/create.C b/src/usr/pore/poreve/porevesrc/create.C
new file mode 100644
index 000000000..8e0d8d636
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/create.C
@@ -0,0 +1,46 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/create.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// $ID$
+
+/// \file create.C
+/// \brief The create method for PoreVe
+///
+/// The PoreVe class declares a static create() method that allows link-time
+/// selection of a normal vs. debug version of PoreVe. This is similar to the
+/// same idea used to make a link-time selection of the Pore hardware model
+/// (PMX vs. BOE). This create() method is linked into the poreve.so. The
+/// create() method for PoreVeDbg is defined in dbg.C
+
+#include "poreve.H"
+
+using namespace vsbe;
+
+PoreVe*
+PoreVe::create(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget,
+ const void* i_arg)
+{
+ // i_arg is needed for subclass to instantiate and the (debug) subclass.
+ return new PoreVe(i_id, i_masterTarget);
+}
+
diff --git a/src/usr/pore/poreve/porevesrc/fasti2c.C b/src/usr/pore/poreve/porevesrc/fasti2c.C
new file mode 100644
index 000000000..676fdccda
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/fasti2c.C
@@ -0,0 +1,604 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/fasti2c.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// $Id: fasti2c.C,v 1.5 2012/01/10 00:27:41 bcbrock Exp $
+
+/// \file fasti2c.C
+/// \brief The "fast-mode" I2C controllers and I2C memory models used
+/// to implement the OTPROM, PNOR and SEEPROM interfaces.
+
+#include "fasti2c.H"
+
+/// Diagnostic aid for debugging fasti2c.C
+#ifdef DEBUG_FASTI2C
+#define BUG() \
+ FAPI_ERR("\n>>> fasti2c:Bug trapped at %s:%d\n\n", \
+ __FILE__, __LINE__)
+#else
+#define BUG()
+#endif // DEBUG_FASTI2C
+
+using namespace vsbe;
+
+////////////////////////////////////////////////////////////////////////////
+// I2cMemory
+////////////////////////////////////////////////////////////////////////////
+
+I2cMemory::I2cMemory(const size_t i_addressBytes) :
+iv_addressBytes(i_addressBytes), iv_address(0)
+{
+}
+
+
+I2cMemory::~I2cMemory()
+{
+}
+
+
+ModelError
+I2cMemory::addressWrite(const size_t i_bytes, const uint32_t i_address)
+{
+ ModelError me;
+
+ if (i_bytes != iv_addressBytes) {
+ BUG();
+ me = ME_I2CMEMORY_ILLEGAL_ADDRESS;
+ } else {
+ me = ME_SUCCESS;
+ iv_address = i_address;
+ }
+ return me;
+}
+
+
+ModelError
+I2cMemory::dataRead(const size_t i_bytes, uint64_t& o_data)
+{
+ ModelError me;
+
+ me = read(iv_address, o_data, i_bytes);
+ if (me == 0) {
+ iv_address += i_bytes;
+ }
+ return me;
+}
+
+
+ModelError
+I2cMemory::dataWrite(const size_t i_bytes, const uint64_t i_data)
+{
+ ModelError me;
+
+ me = write(iv_address, i_data, i_bytes);
+ if (me == 0) {
+ iv_address += i_bytes;
+ }
+ return me;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// FastI2cController
+////////////////////////////////////////////////////////////////////////////
+
+FastI2cController::FastI2cController() :
+ iv_devices(0),
+ iv_state(IDLE), iv_fifo(0)
+
+{
+ iv_status.value = 0;
+ iv_control.value = 0;
+}
+
+
+// The destructor deletes the circular list of devices.
+
+FastI2cController::~FastI2cController()
+{
+ I2cDevice *p, *next;
+
+ if (iv_devices != 0) {
+ for (p = iv_devices->next; p != iv_devices; p = next) {
+ next = p->next;
+ delete p;
+ }
+ delete iv_devices;
+ }
+}
+
+
+ModelError
+FastI2cController::attachMemory(I2cMemory* i_memory,
+ const unsigned i_port,
+ const unsigned i_deviceAddress)
+{
+ ModelError me = ME_SUCCESS;
+ FastI2cControlRegister control; // Used to validate i_Port and i_deviceId
+ I2cDevice* device = new I2cDevice;
+
+ control.fields.port_number = i_port;
+ control.fields.device_address = i_deviceAddress;
+ // Make sure input variables fits into control fields
+ if ((control.fields.port_number != i_port) ||
+ (control.fields.device_address != i_deviceAddress)) {
+ BUG();
+ me = ME_INVALID_ARGUMENT;
+
+ } else {
+
+ device->iv_port = i_port;
+ device->iv_deviceAddress = i_deviceAddress;
+ device->iv_memory = i_memory;
+
+ if (iv_devices == 0) {
+ iv_devices = device;
+ device->next = device;
+ } else {
+
+ if (findDevice(i_port, i_deviceAddress) != 0) {
+ BUG();
+ me = ME_DUPLICATE_CONFIGURATION;
+ } else {
+ device->next = iv_devices->next;
+ iv_devices->next = device;
+ }
+ }
+ }
+ if (me != 0) {
+ delete device;
+ }
+ return me;
+}
+
+
+// Modeling notes:
+//
+// o The RESET register is not modeled here
+//
+// o Our models ignore the I2C Speed
+//
+// o Transactions complete in 0 time and polling always succeeds on the first
+// read of the status register. This is done to simplify the PORE
+// engine model.
+//
+// o Only the following types of control register actions are modeled:
+// * Address write : with_start; with_address; !with_continue; with_stop;
+// data_length == 0
+// * Data read : with_start; with_address; !with_continue; with_stop;
+// data_length == [4,8]
+// * Data write : with_start; with_address; !with_continue; with_stop;
+// data_length == 8
+//
+// o The memory models hold the last address written
+//
+// o Redundant reads of the STATUS register are allowed
+//
+// o PORE only does 4/8 byte reads and 8 byte writes, so any other data
+// access is considered an error (although the models could easily be
+// extended to allow them).
+
+fapi::ReturnCode
+FastI2cController::operation(Transaction& io_transaction)
+{
+ ModelError me;
+ fapi::ReturnCode rc;
+
+ if (0) {
+ if (io_transaction.iv_mode == ACCESS_MODE_WRITE) {
+ FAPI_DBG("FASTI2C : write : offset = %u, data = 0x%016llx\n",
+ io_transaction.iv_offset,
+ io_transaction.iv_data);
+ } else {
+ FAPI_DBG("FASTI2C : read : offset = %u\n",
+ io_transaction.iv_offset);
+ }
+ }
+
+ switch (io_transaction.iv_offset) {
+
+ case FASTI2C_CONTROL_OFFSET:
+
+ if (io_transaction.iv_mode != ACCESS_MODE_WRITE) {
+ BUG();
+ me = ME_WRITE_ONLY_REGISTER;
+
+ } else if (iv_state != IDLE) {
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+
+ } else {
+
+ iv_control.value = io_transaction.iv_data;
+
+ if (!iv_control.fields.with_start ||
+ !iv_control.fields.with_address ||
+ iv_control.fields.read_continue ||
+ !iv_control.fields.with_stop) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+
+ } else if (iv_control.fields.read_not_write == 0) {
+
+ if (iv_control.fields.address_range == 0) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+
+ } else {
+ if (iv_control.fields.data_length == 0) {
+ me = addressWrite();
+
+ } else if (iv_control.fields.data_length != 8) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+
+ } else {
+ me = initialDataWrite();
+ }
+ }
+ } else {
+ if ((iv_control.fields.data_length != 4) &&
+ (iv_control.fields.data_length != 8)) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+ } else {
+ me = dataRead();
+ }
+ }
+ }
+ break;
+
+
+ case FASTI2C_STATUS_OFFSET:
+
+ if (io_transaction.iv_mode != ACCESS_MODE_READ) {
+ BUG();
+ me = ME_READ_ONLY_REGISTER;
+
+ } else {
+
+ switch (iv_state) {
+
+ case ADDRESS_WRITE_ONGOING:
+ case DATA_WRITE_ONGOING:
+ iv_status.value = 0;
+ iv_status.fields.i2c_command_complete = 1;
+ io_transaction.iv_data = iv_status.value;
+ iv_state = IDLE;
+ me = ME_SUCCESS;
+ break;
+
+ case DATA_READ_ONGOING:
+ iv_status.value = 0;
+ iv_status.fields.i2c_command_complete = 1;
+ iv_status.fields.i2c_fifo_entry_count =
+ iv_control.fields.data_length;
+ io_transaction.iv_data = iv_status.value;
+ iv_state = DATA_AVAILABLE;
+ me = ME_SUCCESS;
+ break;
+
+ case IDLE:
+ io_transaction.iv_data = iv_status.value;
+ me = ME_SUCCESS;
+ break;
+
+ default:
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ }
+ break;
+
+
+ case FASTI2C_DATA_OFFSET:
+
+ if ((io_transaction.iv_mode == ACCESS_MODE_READ) ||
+ (io_transaction.iv_mode == ACCESS_MODE_EXECUTE)) {
+
+ switch (iv_state) {
+
+ case DATA_AVAILABLE:
+ io_transaction.iv_data = iv_fifo;
+ iv_state = IDLE;
+ me = ME_SUCCESS;
+ break;
+
+ default:
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ } else {
+
+ switch (iv_state) {
+
+ case WRITE_DATA_EXPECTED:
+ me = finalDataWrite(io_transaction.iv_data);
+ iv_state = DATA_WRITE_ONGOING;
+
+ default:
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ }
+ break;
+
+
+ default:
+ BUG();
+ me = ME_ILLEGAL_REGISTER_OFFSET;
+ break;
+ }
+
+ if (me != 0) {
+ iv_state = ERROR;
+ rc = 1; // \bug Fix this
+ }
+ io_transaction.busError(me);
+ return rc;
+}
+
+
+// Find the device in the circular device list and spin the device to the
+// front of the list if found.
+
+I2cDevice*
+FastI2cController::findDevice(const unsigned i_port,
+ const unsigned i_deviceAddress)
+{
+ I2cDevice* p;
+
+ p = iv_devices;
+ if (p != 0) {
+ do {
+ if ((p->iv_port == i_port) &&
+ (p->iv_deviceAddress == i_deviceAddress)) {
+ iv_devices = p;
+ break;
+ }
+ if (p == iv_devices) {
+ p = 0;
+ break;
+ }
+ } while(1);
+ }
+ return p;
+}
+
+
+uint32_t
+FastI2cController::getI2cAddress(const FastI2cControlRegister i_control)
+{
+ size_t addressBytes = i_control.fields.address_range;
+
+ return i_control.words.low_order >> ((4 - addressBytes) * 8);
+}
+
+
+// The address is left-justified in the low-order 32 bits of the control
+// register.
+
+ModelError
+FastI2cController::addressWrite()
+{
+ ModelError me;
+ unsigned port = iv_control.fields.port_number;
+ unsigned deviceAddress = iv_control.fields.device_address;
+ size_t addressBytes = iv_control.fields.address_range;
+ I2cDevice* p;
+
+ p = findDevice(port, deviceAddress);
+ if (p == 0) {
+ BUG();
+ me = ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER;
+ } else {
+ me = p->iv_memory->addressWrite(addressBytes,
+ getI2cAddress(iv_control));
+ iv_state = ADDRESS_WRITE_ONGOING;
+ }
+ return me;
+}
+
+
+ModelError
+FastI2cController::dataRead()
+{
+ ModelError me;
+ unsigned port = iv_control.fields.port_number;
+ unsigned deviceAddress = iv_control.fields.device_address;
+ size_t dataBytes = iv_control.fields.data_length;
+ uint64_t data;
+ I2cDevice* p;
+
+ p = findDevice(port, deviceAddress);
+ if (p == 0) {
+ BUG();
+ me = ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER;
+ } else {
+ me = p->iv_memory->dataRead(dataBytes, data);
+ iv_fifo = data << (64 - (dataBytes * 8));
+ iv_state = DATA_READ_ONGOING;
+ }
+ return me;
+}
+
+
+// For addresses < 4 bytes, the first slug of data occupies the remainder of
+// the low-order word of the control register. Any remaining bytes come in on
+// the next transaction targeting the data register. This code assumes 8-byte
+// only data writes.
+
+ModelError
+FastI2cController::initialDataWrite()
+{
+ unsigned addressBytes = iv_control.fields.address_range;
+
+ if (addressBytes < 4) {
+ iv_fifo =
+ BE64_GET_FIELD(iv_control.words.low_order,
+ 32 + (addressBytes * 8),
+ 63) <<
+ ((4 - addressBytes) * 8);
+ }
+ iv_state = WRITE_DATA_EXPECTED;
+ return ME_SUCCESS;
+}
+
+
+// Assume 8-byte only write transactions
+
+ModelError
+FastI2cController::finalDataWrite(const uint64_t i_data)
+{
+ ModelError me;
+ unsigned port = iv_control.fields.port_number;
+ unsigned deviceAddress = iv_control.fields.device_address;
+ size_t addressBytes = iv_control.fields.address_range;
+ I2cDevice* p;
+
+ iv_fifo =
+ BE64_SET_FIELD(iv_fifo, addressBytes * 8, 63,
+ BE64_GET_FIELD(i_data, 0,
+ ((8 - addressBytes) * 8)) - 1);
+
+ p = findDevice(port, deviceAddress);
+ if (p == 0) {
+ BUG();
+ me = ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER;
+ } else {
+ me = p->iv_memory->dataWrite(8, iv_fifo);
+ iv_state = DATA_WRITE_ONGOING;
+ }
+ return me;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// LpcController
+////////////////////////////////////////////////////////////////////////////
+
+LpcController::LpcController() :
+ iv_eccStart(0),
+ iv_eccStop(LPC_MEMORY_MAX_SIZE)
+{
+}
+
+
+LpcController::~LpcController()
+{
+}
+
+
+fapi::ReturnCode
+LpcController::operation(Transaction& io_transaction)
+{
+ ModelError me = ME_SUCCESS;
+ fapi::ReturnCode rc;
+ bool handledBySuperclass = false;
+ FastI2cControlRegister control;
+ uint32_t address;
+
+ switch (io_transaction.iv_offset) {
+
+ case LPCM_ECC_START_OFFSET:
+
+ if (iv_state != IDLE) {
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_READ) {
+ io_transaction.iv_data = iv_eccStart;
+ me = ME_SUCCESS;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_WRITE) {
+ iv_eccStart = io_transaction.iv_data;
+ me = ME_SUCCESS;
+
+ } else {
+ BUG();
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ }
+ break;
+
+ case LPCM_ECC_STOP_OFFSET:
+
+ if (iv_state != IDLE) {
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_READ) {
+ io_transaction.iv_data = iv_eccStop;
+ me = ME_SUCCESS;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_WRITE) {
+ iv_eccStop = io_transaction.iv_data;
+ me = ME_SUCCESS;
+
+ } else {
+ BUG();
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ }
+ break;
+
+ default:
+
+ if ((io_transaction.iv_offset == FASTI2C_CONTROL_OFFSET) &&
+ (io_transaction.iv_mode == ACCESS_MODE_WRITE)) {
+
+ control.value = io_transaction.iv_data;
+ address = getI2cAddress(control);
+ if ((address < iv_eccStart) || (address >= iv_eccStop)) {
+ BUG();
+ me = ME_LPC_ILLEGAL_ADDRESS;
+
+ } else {
+
+ handledBySuperclass = true;
+ rc = FastI2cController::operation(io_transaction);
+ }
+ } else {
+
+ handledBySuperclass = true;
+ rc = FastI2cController::operation(io_transaction);
+ }
+ break;
+ }
+ if (!handledBySuperclass) {
+ if (me != 0) {
+ rc = 1; // \bug Fix this;
+ }
+ io_transaction.busError(me);
+ }
+ return rc;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/usr/pore/poreve/porevesrc/fasti2c.H b/src/usr/pore/poreve/porevesrc/fasti2c.H
new file mode 100644
index 000000000..a21288e94
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/fasti2c.H
@@ -0,0 +1,564 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/fasti2c.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_FASTI2C_H
+#define __VSBE_FASTI2C_H
+
+// $Id: fasti2c.H,v 1.5 2011/12/16 20:27:26 bcbrock Exp $
+
+/// \file fasti2c.H
+/// \brief The "fast-mode" I2C controllers and memory models used
+/// to implement the OTPROM, PNOR and SEEPROM interfaces.
+
+#include <fapi.H>
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bebits.H"
+#include "bus.H"
+
+namespace vsbe {
+
+ class FastI2cController;
+ class LpcController;
+ class I2cMemory;
+
+ /// \defgroup fasti2c_speeds Fast-Mode I2C Controller Speeds
+ ///
+ /// Note that all speeds are considered "legal", and the model does not
+ /// interpret the speed setting.
+ ///
+ /// @{
+
+ const int FASTI2C_SPEED_100K = 0;
+ const int FASTI2C_SPEED_400K = 1;
+ const int FASTI2C_SPEED_3400K = 2;
+ const int FASTI2C_SPEED_50K = 3;
+
+ /// @}
+
+ /// \defgroup fasti2c_offsets Fast-Mode I2C Controller Register Offsets (PIB) and limits
+ ///
+ /// The last two offsets are only valid on the LpcController model.
+ /// @{
+
+ const uint32_t FASTI2C_CONTROL_OFFSET = 0x0;
+ const uint32_t FASTI2C_RESET_OFFSET = 0x1;
+ const uint32_t FASTI2C_STATUS_OFFSET = 0x2;
+ const uint32_t FASTI2C_DATA_OFFSET = 0x3;
+ const size_t FASTI2C_REGISTERS = 0x4;
+
+ const uint32_t LPCM_ECC_START_OFFSET = 0x4;
+ const uint32_t LPCM_ECC_STOP_OFFSET = 0x5;
+ const size_t LPCM_REGISTERS = 0x6;
+
+ /// @}
+
+ /// The maximum memory size supported by the LPC controller (64MB)
+ const uint32_t LPC_MEMORY_MAX_SIZE = (1 << 26);
+
+
+ // These register layouts are copied/modified from the PMX model. If they
+ // need to be modified here then they will also need to be modified in the
+ // PMX model.
+
+ /// Fast-Mode I2C Controller Control Register Layout
+ typedef union {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t with_start : 1;
+ uint64_t with_address : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_stop : 1;
+ uint64_t data_length : 4;
+ uint64_t device_address : 7;
+ uint64_t read_not_write : 1;
+ uint64_t speed : 2;
+ uint64_t port_number : 5;
+ uint64_t address_range : 3;
+ uint64_t _reserved0 : 6;
+ uint64_t data0 : 8;
+ uint64_t data1 : 8;
+ uint64_t data2 : 8;
+ uint64_t data3 : 8;
+#else
+ uint64_t data3 : 8;
+ uint64_t data2 : 8;
+ uint64_t data1 : 8;
+ uint64_t data0 : 8;
+ uint64_t _reserved0 : 6;
+ uint64_t address_range : 3;
+ uint64_t port_number : 5;
+ uint64_t speed : 2;
+ uint64_t read_not_write : 1;
+ uint64_t device_address : 7;
+ uint64_t data_length : 4;
+ uint64_t with_stop : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_address : 1;
+ uint64_t with_start : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+ } FastI2cControlRegister;
+
+
+ /// Fast-Mode I2C Controller Reset Register Layout
+ typedef union {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+ } FastI2cResetRegister;
+
+
+ /// Fast-Mode I2C Controller Status Register Layout
+ typedef union {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pib_address_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t lb_parity_error : 1;
+ uint64_t read_data : 32;
+ uint64_t _reserved0 : 6;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_fifo_entry_count : 8;
+#else
+ uint64_t i2c_fifo_entry_count : 8;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t _reserved0 : 6;
+ uint64_t read_data : 32;
+ uint64_t lb_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_address_invalid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+ } FastI2cStatusRegister;
+
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// I2cMemory
+////////////////////////////////////////////////////////////////////////////
+
+
+/// An I2C memory model
+///
+/// The I2cMemory is a subclass of the Memory. It adds a device address for
+/// mapping onto an I2c bus, and also supports I2C memory operations such as
+/// addressWrite() and dataRead().
+
+class
+vsbe::I2cMemory : public Memory
+{
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create an I2c Memory
+ ///
+ /// \param[in] i_addressBytes The number of bytes (1-4) in a memory
+ /// address for this memory.
+ I2cMemory(const size_t i_addressBytes);
+
+ virtual ~I2cMemory();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Perform an I2C address write to an attached device.
+ ///
+ /// \param[in] i_bytes The number of address bytes, which must match the
+ /// configuration.
+ ///
+ /// \param[in] i_address The memory address.
+ ///
+ /// \retval me ModelError return code
+ ModelError
+ addressWrite(const size_t i_bytes, const uint32_t i_address);
+
+ /// Perform an I2C data read from an attached device.
+ ///
+ /// \param[in] i_bytes The number of data bytes to read
+ ///
+ /// \param[out] o_data The data, right justified
+ ///
+ /// The read has a side effect of incrementing the address held in the
+ /// device by \a i_bytes.
+ ///
+ /// \retval me ModelError return code
+ ModelError
+ dataRead(const size_t i_bytes, uint64_t& o_data);
+
+ /// Perform an I2C data write to an attached device.
+ ///
+ /// \param[in] i_bytes The number of data bytes to write
+ ///
+ /// \param[in] i_data The data, right justified
+ ///
+ /// The write has a side effect of incrementing the address held in the
+ /// device by \a i_bytes.
+ ///
+ /// \retval me ModelError return code
+ ModelError
+ dataWrite(const size_t i_bytes, const uint64_t i_data);
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The number of address bytes (1-4)
+ const size_t iv_addressBytes;
+
+ /// The address register, auto-incremented on data reads and writes
+ uint32_t iv_address;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ I2cMemory(const I2cMemory& i_rhs);
+ I2cMemory& operator=(const I2cMemory& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// I2cDevice
+////////////////////////////////////////////////////////////////////////////
+
+namespace vsbe {
+
+/// A simple I2C device/bus model
+///
+/// This simple device/bus model is used by the FastI2cController to model the
+/// atachment of multiple I2cMemory to the physical busses (ports) controlled
+/// by each controller. Normally only 1 or two devices are attached to each
+/// controller so it's easiest to model all devices under control of a
+/// controller as a single list.
+
+typedef struct I2cDevice {
+
+ /// The controller port number - associated with a physical I2C bus
+ unsigned iv_port;
+
+ /// The device address of the device on the bus
+ unsigned iv_deviceAddress;
+
+ /// The I2cMemory
+ I2cMemory* iv_memory;
+
+ /// The next I2cdevice in the list of devices
+ struct I2cDevice* next;
+
+} I2cDevice;
+
+};
+
+////////////////////////////////////////////////////////////////////////////
+// FastI2cController
+////////////////////////////////////////////////////////////////////////////
+
+
+/// A model of a "fast-mode" I2C Controller
+///
+/// The PORE engine only uses the new "fast-mode" protocol to communicate with
+/// "I2C Controllers" that implement the physical memory interfaces for SBE
+/// memories. These controllers may be either real I2C controllers (like for
+/// SEEPROM) or pseudo-I2C-controllers like the PNOR and OTPROM controllers.
+/// The "fast-mode" is a new subset of the full I2C controller interface that
+/// only uses 4 registers. This model only models fast-mode accesses, and
+/// only in the precise way that PORE engines use fast-mode controllers for
+/// memory fetches, loads and stores. It will return errors for use of the
+/// legacy mode registers or otherwise legal sequences that are simply not
+/// modeled.
+///
+/// Each controller manages a number of "ports". Each port is a physical I2C
+/// bus, and devices attached to each port (bus) must have unique device IDs.
+/// We model the devices attached to a port independently. Each controller
+/// maintains a list of I2cDevice mapped to its ports. The underlying
+/// devices are currently all of the I2cMemory class.
+
+class
+vsbe::FastI2cController : public PibSlave
+{
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ /// \enum FastI2cState
+ ///
+ /// The state of the controller. Sequences of register operations are
+ /// only allowed in a prescribed sequence, depending on the state of the
+ /// controller. The ERROR state represents a bug in the model and is
+ /// non-recoverable.
+ enum FastI2cState {
+ ERROR,
+ IDLE,
+ ADDRESS_WRITE_ONGOING,
+ DATA_READ_ONGOING,
+ DATA_AVAILABLE,
+ WRITE_DATA_EXPECTED,
+ DATA_WRITE_ONGOING
+ };
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ FastI2cController();
+
+ virtual ~FastI2cController();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Attach a memory model to the controller
+ ///
+ /// \param[in] i_memory A configured I2cMemory
+ ///
+ /// \param[in] i_port The port (bus) number the memory is attached to
+ ///
+ /// \param[in] i_deviceAddress The device ID of the memory device on the bus
+ ///
+ /// \retval me Either 0 for success, ME_INVALID_ARGUMENT or
+ /// ME_AMBIGUOUS_CONFIGURATION.
+ ModelError
+ attachMemory(I2cMemory* i_memory,
+ const unsigned i_port,
+ const unsigned i_deviceAddress);
+
+ /// Handle a PIB transaction
+ ///
+ /// \param[in,out] io_transaction An abstract PIB transaction
+ ///
+ /// The FastI2cController is an indirect memory. In general several PIB
+ /// transactions are required to fetch a single doubleword of code or data
+ /// from the memory.
+ ///
+ /// \retval rc Either an "OK" return code for success, or a code
+ /// describing the error.
+ virtual fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// Find a device in the list of devices attached to this controller
+ ///
+ /// \param[in] i_port The port number to search
+ ///
+ /// \param[in] i_deviceAddress The device address to search
+ ///
+ /// \retval device A pointer to the device if found, otherwise 0.
+ I2cDevice* findDevice(const unsigned i_port,
+ const unsigned i_deviceAddress);
+
+ /// Extract the I2C address from the CONTROL register
+ ///
+ /// \param[in] i_control The FastI2cControl register
+ ///
+ /// \retval address The indirect I2C address, taken from bytes 4-7 of the
+ /// control register depending on how many address bytes are indicated in
+ /// the control.
+ uint32_t getI2cAddress(const FastI2cControlRegister i_control);
+
+ /// Perform an I2C address write to an attached device.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError addressWrite();
+
+ /// Perform an I2C data read from an attached device.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError dataRead();
+
+ /// Begin an I2C data write an attached device.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError initialDataWrite();
+
+ /// Finalize an I2C data write an attached device.
+ ///
+ /// \param[in] i_data The final bytes of a data write, left justtified.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError finalDataWrite(const uint64_t i_data);
+
+ /// A list of I2cDevice, each of which is assigned to a controler port and
+ /// maintains a unique device ID for that port.
+ I2cDevice* iv_devices;
+
+ /// The abstract state of the controller
+ FastI2cState iv_state;
+
+ /// The last value written to the control register
+ FastI2cControlRegister iv_control;
+
+ /// The last value generated in the status register
+ FastI2cStatusRegister iv_status;
+
+ /// The data FIFO. Data is left-justified in this register.
+ uint64_t iv_fifo;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ FastI2cController(const FastI2cController& i_rhs);
+ FastI2cController& operator=(const FastI2cController& i_rhs);
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// LpcController
+////////////////////////////////////////////////////////////////////////////
+
+/// Simplified model of the LPC controller as a fast-mode I2C controller
+///
+/// The LPC controller appears as a pseudo-FastI2cController with a couple of
+/// extra specializations. The fast-mode I2C controller specification
+/// is extended with two extra registers : The ECC start and stop
+/// addresses. We do not model ECC in our model, therefore this model only
+/// allows accesses that fall within the ECC window. The SBE will never
+/// address outside of the ECC window.
+
+class
+vsbe::LpcController : public FastI2cController
+{
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ LpcController();
+
+ virtual ~LpcController();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Handle a PIB transaction
+ ///
+ /// \param[in,out] io_transaction An abstract PIB transaction
+ ///
+ /// The LpcController is an indirect memory. In general several PIB
+ /// transactions are required to fetch a single doubleword of code or data
+ /// from the memory. The LpcController passes all transactions through to
+ /// the underlying FastI2cController except for reads/writes to the ECC
+ /// control registers. We require that any change to the ECC bounds be
+ /// made while the controller is in its IDLE state.
+ ///
+ /// \retval rc Either an "OK" return code for success, or a code
+ /// describing the error.
+ virtual fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The ECC start address register
+ uint64_t iv_eccStart;
+
+ /// The ECC stop address register
+ uint64_t iv_eccStop;
+};
+
+
+#endif // __VSBE_FASTI2C_H
diff --git a/src/usr/pore/poreve/porevesrc/hookmanager.C b/src/usr/pore/poreve/porevesrc/hookmanager.C
new file mode 100644
index 000000000..bf31e76b1
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/hookmanager.C
@@ -0,0 +1,575 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/hookmanager.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// $Id: hookmanager.C,v 1.12 2012/01/06 21:25:25 bcbrock Exp $
+
+/// \file hookmanager.C
+/// \brief A portable symbol table and hook execution facility
+
+#include <stdio.h>
+#include <string.h>
+
+#include "hookmanager.H"
+
+using namespace vsbe;
+
+
+#ifndef ULL
+/// The printf() checker for 64-bit GCC throws a warning if a uint64_t is
+/// printed as %llx - I have no idea why, but by casting them to (unsigned
+/// long long) the warning goes away.
+#define ULL(x) ((unsigned long long)(x))
+#endif
+
+fapi::ReturnCode vsbe::hookOk;
+HookManager* HookManager::s_instance = 0;
+
+
+////////////////////////////////////////////////////////////////////////////
+// CharPointerComparison
+////////////////////////////////////////////////////////////////////////////
+
+bool
+CharPointerComparison::operator()(char const* i_lhs,
+ char const* i_rhs) const
+{
+ return strcmp(i_lhs, i_rhs) < 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookManager
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////// Creators //////////////////////////////
+
+HookManager::HookManager() :
+ iv_error(HOOK_OK)
+{
+}
+
+
+HookManager::~HookManager()
+{
+}
+
+
+///////////////////////////// Accessors //////////////////////////////
+
+fapi::ReturnCode
+HookManager::runInstructionHook(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ InstructionHookMap::iterator ihmi;
+ fapi::ReturnCode rc;
+
+ ihmi = instance()->iv_instructionHookMap.find(i_hook);
+ if (ihmi == instance()->iv_instructionHookMap.end()) {
+ rc = 0;
+ } else {
+ rc = (ihmi->second)(i_address, i_hook, i_parameter, io_pore, i_target);
+ }
+ return rc;
+}
+
+
+fapi::ReturnCode
+HookManager::runReadHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+
+{
+ return instance()->runHooks(HOOK_READ_INTERACTIVE, HOOK_READ_EXTRACTED,
+ i_address, io_pore, i_target);
+}
+
+
+fapi::ReturnCode
+HookManager::runWriteHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ return instance()->runHooks(HOOK_WRITE_INTERACTIVE, HOOK_WRITE_EXTRACTED,
+ i_address, io_pore, i_target);
+}
+
+
+fapi::ReturnCode
+HookManager::runFetchHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ return instance()->runHooks(HOOK_FETCH_INTERACTIVE, HOOK_FETCH_EXTRACTED,
+ i_address, io_pore, i_target);
+}
+
+
+HookError
+HookManager::findGlobalSymbol(const char* i_symbol,
+ bool& o_found,
+ GlobalSymbolInfo& io_info)
+{
+ GlobalSymbolMap::iterator gsmi;
+
+ o_found = false;
+ if (!instance()->iv_error) {
+ gsmi = instance()->iv_globalSymbolMap.find(i_symbol);
+ if (gsmi != instance()->iv_globalSymbolMap.end()) {
+ o_found = true;
+ io_info = *(gsmi->second);
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::globalSymbolList(GlobalSymbolList& io_symbols, const char* i_types)
+{
+ GlobalSymbolMap::iterator gsmi;
+
+ if (!instance()->iv_error) {
+ for (gsmi = instance()->iv_globalSymbolMap.begin();
+ gsmi != instance()->iv_globalSymbolMap.end();
+ gsmi++) {
+
+ if ((i_types == 0) ||
+ (strchr(i_types, gsmi->second->iv_type) != 0)) {
+ io_symbols.push_back(*gsmi);
+ }
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+void
+HookManager::report(const int i_options)
+{
+ InstructionHookMap::iterator ihmi;
+ HookedAddressMap::iterator hami;
+ HookedFileMap::iterator hfmi;
+ GlobalSymbolMap::iterator gsmi;
+ Hook* hook;
+ const HookTable* table;
+ size_t entry;
+ char type;
+ ExtractedHook* exHook;
+
+ if (i_options != 0) {
+
+ FAPI_INF("");
+ FAPI_INF("------------------------------------------------------");
+ FAPI_INF("-- HookManager @ %p", instance());
+ FAPI_INF("------------------------------------------------------");
+
+ if (i_options & HM_REPORT_HOOKED_ADDRESS_MAP) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Hooked Address Map : %zu unique addresses ---",
+ instance()->iv_hookedAddressMap.size());
+ FAPI_INF("");
+
+ for (hami = instance()->iv_hookedAddressMap.begin();
+ hami != instance()->iv_hookedAddressMap.end();
+ hami++) {
+
+ for (hook = hami->second; hook != 0; hook = hook->iv_next) {
+ switch (hook->iv_type) {
+
+ case HOOK_READ_INTERACTIVE:
+ case HOOK_WRITE_INTERACTIVE:
+ case HOOK_FETCH_INTERACTIVE:
+ switch (hook->iv_type) {
+ case HOOK_READ_INTERACTIVE: type = 'r'; break;
+ case HOOK_WRITE_INTERACTIVE: type = 'w'; break;
+ case HOOK_FETCH_INTERACTIVE: type = 'x'; break;
+ default: type = '?'; break; // For GCC -Wall
+ }
+ FAPI_INF("%04x:%08x %c %p",
+ hami->first.iv_memorySpace,
+ hami->first.iv_offset,
+ type, hook->iv_hook);
+ break;
+
+ case HOOK_READ_EXTRACTED:
+ case HOOK_WRITE_EXTRACTED:
+ case HOOK_FETCH_EXTRACTED:
+ switch (hook->iv_type) {
+ case HOOK_READ_EXTRACTED: type = 'r'; break;
+ case HOOK_WRITE_EXTRACTED: type = 'w'; break;
+ case HOOK_FETCH_EXTRACTED: type = 'x'; break;
+ default: type = '?'; break; // For GCC -Wall
+ }
+ exHook = (ExtractedHook*)(hook->iv_hook);
+ FAPI_INF("%04x:%08x %8zu %s",
+ hami->first.iv_memorySpace, hami->first.iv_offset,
+ exHook->iv_index, exHook->iv_file);
+ break;
+
+ default: break; // For GCC -Wall
+ }
+ }
+ }
+ }
+
+ if (i_options & HM_REPORT_HOOK_TABLES) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Hook Tables : %zu hooked files---",
+ instance()->iv_hookedFileMap.size());
+
+ for (hfmi = instance()->iv_hookedFileMap.begin();
+ hfmi != instance()->iv_hookedFileMap.end();
+ hfmi++) {
+
+ FAPI_INF("");
+ FAPI_INF("%s", hfmi->first);
+
+ table = hfmi->second;
+ for (entry = 0; entry < table->iv_entries; entry++) {
+ FAPI_INF("%8zu %p",
+ entry, table->iv_hooks[entry]);
+ }
+ }
+ }
+
+ if (i_options & HM_REPORT_INSTRUCTION_HOOK_MAP) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Instruction Hook Map ---");
+ FAPI_INF("");
+
+ for (ihmi = instance()->iv_instructionHookMap.begin();
+ ihmi != instance()->iv_instructionHookMap.end();
+ ihmi++) {
+
+ FAPI_INF("%06x %p",
+ ihmi->first, ihmi->second);
+ }
+ }
+
+ if (i_options & HM_REPORT_GLOBAL_SYMBOL_MAP) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Global Symbol Map ---");
+ FAPI_INF("");
+
+ for (gsmi = instance()->iv_globalSymbolMap.begin();
+ gsmi != instance()->iv_globalSymbolMap.end();
+ gsmi++) {
+
+ FAPI_INF("%04x:%08x %c %s",
+ gsmi->second->iv_address.iv_memorySpace,
+ gsmi->second->iv_address.iv_offset,
+ gsmi->second->iv_type,
+ gsmi->first);
+ }
+ }
+
+ FAPI_INF("");
+ FAPI_INF("------------------------------------------------------");
+ FAPI_INF("");
+ }
+}
+
+
+//////////////////////////// Manipulators ////////////////////////////
+
+HookError
+HookManager::registerInstructionHook(const uint32_t i_index,
+ HookInstructionHook i_hookRoutine)
+{
+ InstructionHookMap::iterator ihmi;
+
+ if (!instance()->iv_error) {
+
+ ihmi = instance()->iv_instructionHookMap.find(i_index);
+ if (ihmi == instance()->iv_instructionHookMap.end()) {
+
+ instance()->iv_instructionHookMap[i_index] = i_hookRoutine;
+
+ } else {
+ if (ihmi->second != i_hookRoutine) {
+ FAPI_ERR("%s : Static hook collision for index : %u",
+ __FUNCTION__, i_index);
+ instance()->iv_error = HOOK_STATIC_COLLISION;
+ }
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::registerHookTable(const char* i_file,
+ const HookTable* i_table)
+{
+ if (!instance()->iv_error) {
+
+ if (instance()->iv_hookedFileMap.find(i_file) !=
+ instance()->iv_hookedFileMap.end()) {
+
+ FAPI_ERR("%s : File name collision : %s",
+ __FUNCTION__, i_file);
+ instance()->iv_error = HOOK_FILE_NAME_COLLISION;
+ } else {
+ instance()->iv_hookedFileMap[i_file] = i_table;
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::registerHook(const PoreAddress& i_address,
+ Hook* io_hook)
+{
+ HookedAddressMap::iterator hami;
+ Hook* hook;
+
+ if (!instance()->iv_error) {
+
+ hami = instance()->iv_hookedAddressMap.find(i_address);
+ if (hami != instance()->iv_hookedAddressMap.end()) {
+ for (hook = hami->second;
+ hook->iv_next != 0;
+ hook = hook->iv_next);
+ hook->iv_next = io_hook;
+ } else {
+ instance()->iv_hookedAddressMap[i_address] = io_hook;
+ }
+ io_hook->iv_next = 0;
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::registerGlobalSymbol(const char* i_symbol,
+ const GlobalSymbolInfo* i_info)
+{
+ if (!instance()->iv_error) {
+
+ if (instance()->iv_globalSymbolMap.find(i_symbol) !=
+ instance()->iv_globalSymbolMap.end()) {
+
+ FAPI_ERR("%s : Multiply defined symbol : %s",
+ __FUNCTION__, i_symbol);
+ instance()->iv_error = HOOK_MULTIPLY_DEFINED_SYMBOL;
+ } else {
+ instance()->iv_globalSymbolMap[i_symbol] = i_info;
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::addInteractiveHook(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine)
+{
+ Hook* hook = new Hook();
+ HookError rc;
+
+ instance()->iv_error = HOOK_OK;
+ if (hook == 0) {
+ rc = HOOK_MEMORY_ALLOCATION_FAILED;
+ } else {
+ switch (i_type) {
+ case HOOK_READ_INTERACTIVE:
+ case HOOK_WRITE_INTERACTIVE:
+ case HOOK_FETCH_INTERACTIVE:
+ rc = HOOK_OK;
+ hook->iv_type = i_type;
+ hook->iv_hook = (void*)i_hookRoutine;
+ registerHook(i_address, hook);
+ break;
+ default:
+ delete hook;
+ rc = HOOK_ILLEGAL_TYPE;
+ }
+ }
+ instance()->iv_error = rc;
+ return rc;
+}
+
+
+HookError
+HookManager::deleteInteractiveHooks(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine)
+{
+ HookedAddressMap::iterator hami;
+ Hook **last, *hook, *next;
+ HookError rc;
+ bool deleted = false;
+
+ switch (i_type) {
+ case HOOK_READ_INTERACTIVE:
+ case HOOK_WRITE_INTERACTIVE:
+ case HOOK_FETCH_INTERACTIVE:
+
+ hami = instance()->iv_hookedAddressMap.find(i_address);
+ if (hami != instance()->iv_hookedAddressMap.end()) {
+ for (last = &(hami->second), hook = hami->second;
+ hook != 0;
+ hook = next) {
+ next = hook->iv_next;
+ if ((hook->iv_type == i_type) &&
+ ((i_hookRoutine == 0) ||
+ (hook->iv_hook) == i_hookRoutine)) {
+ delete hook;
+ deleted = true;
+ *last = next;
+ } else {
+ last = &(hook->iv_next);
+ }
+ }
+ }
+ if ((i_hookRoutine == 0) || deleted) {
+ if (hami->second == 0) {
+ instance()->iv_hookedAddressMap.erase(hami);
+ }
+ rc = HOOK_OK;
+ } else {
+ rc = HOOK_INTERACTIVE_DELETE_FAILED;
+ }
+ break;
+
+ default:
+ rc = HOOK_ILLEGAL_TYPE;
+ }
+ instance()->iv_error = rc;
+ return rc;
+}
+
+
+void
+HookManager::clearError()
+{
+ instance()->iv_error = HOOK_OK;
+}
+
+
+////////////////////////// Implementation ////////////////////////////
+
+fapi::ReturnCode
+HookManager::runHooks(const HookType i_interactiveType,
+ const HookType i_extractedType,
+ const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ HookedAddressMap::iterator hami;
+ Hook* hook;
+ ExtractedHook *exHook;
+ HookedFileMap::iterator hfmi;
+ const HookTable* table;
+ fapi::ReturnCode rc;
+
+ hami = instance()->iv_hookedAddressMap.find(i_address);
+ if (hami != instance()->iv_hookedAddressMap.end()) {
+
+ for (hook = hami->second;
+ (hook != 0) && rc.ok();
+ hook = hook->iv_next) {
+
+ if (hook->iv_type == i_interactiveType) {
+
+ rc = ((AddressBasedHook)(hook->iv_hook))(i_address,
+ i_interactiveType,
+ io_pore,
+ i_target);
+
+ } else if (hook->iv_type == i_extractedType) {
+
+ exHook = (ExtractedHook*)(hook->iv_hook);
+ hfmi = instance()->iv_hookedFileMap.find(exHook->iv_file);
+ if (hfmi == instance()->iv_hookedFileMap.end()) {
+
+ FAPI_ERR("%s : Address %04x:%08x is hooked from "
+ "file '%s', but no HookTable can be found "
+ "for the file.",
+ __FUNCTION__,
+ i_address.iv_memorySpace,
+ i_address.iv_offset,
+ exHook->iv_file);
+ instance()->iv_error = HOOK_TABLE_MISSING;
+ rc = 1; /// \todo Define this error
+
+ } else {
+
+ table = hfmi->second;
+ if (exHook->iv_index > table->iv_entries) {
+
+ FAPI_ERR("%s : Address %04x:%08x is hooked from "
+ "file '%s' at index %zu, "
+ "but the index exceeds "
+ "the number of hooks indexed for the "
+ "file (%zu).",
+ __FUNCTION__,
+ i_address.iv_memorySpace,
+ i_address.iv_offset,
+ hfmi->first, exHook->iv_index,
+ table->iv_entries);
+ instance()->iv_error = HOOK_INDEX_FAILURE;
+ rc = 1; /// \todo Define this error
+
+ } else {
+
+ rc =
+ (table->iv_hooks[exHook->iv_index])
+ (i_address, i_extractedType, io_pore, i_target);
+ }
+ }
+ } else {
+
+ FAPI_ERR("%s : Bug in HookManager - Unexpected type",
+ __FUNCTION__);
+ instance()->iv_error = HOOK_BUG;
+ rc = 1; /// \todo Define this error
+ }
+ if (!rc.ok()) break;
+ }
+ }
+ return rc;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookInitializer
+////////////////////////////////////////////////////////////////////////////
+
+HookInitializer::HookInitializer(HookManagerInitializer i_function)
+{
+ i_function();
+}
+
+
+HookInitializer::~HookInitializer()
+{
+}
diff --git a/src/usr/pore/poreve/porevesrc/hookmanager.H b/src/usr/pore/poreve/porevesrc/hookmanager.H
new file mode 100644
index 000000000..5323392c9
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/hookmanager.H
@@ -0,0 +1,859 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/hookmanager.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_HOOKMANAGER_H
+#define __VSBE_HOOKMANAGER_H
+
+// $Id: hookmanager.H,v 1.16 2012/01/06 21:25:25 bcbrock Exp $
+
+/// \file hookmanager.H
+/// \brief A portable symbol table and hook execution facility
+///
+/// Although the concept of a HookManager is generic, this implementation is
+/// specific to the FAPI PoreVe environment.
+///
+/// A hook is a C/C++ subroutine called during execution of the PoreVe. A
+/// hook is either associated with a HOOKI instruction, or with a particular
+/// PORE effective address. Address-based hooks are either read, write or
+/// fetch hooks, and may have either been installed interactively (e.g., by a
+/// debugger or hand-written code) or extracted from a source file. We make a
+/// distinction because extracted hooks are indexed via static tables created
+/// by processing an assembler source file, whereas interactive hooks are
+/// inserted individually. Extracted hooks are assumed to be characterized by
+/// permanent static data structures and can not be deleted. Interactive
+/// hooks can be created and deleted at will.
+///
+/// \todo Once the HBI use of the HookManager is finalized, it may be
+/// necessary to split this into 2 classes, one for HBI and another for Cronus
+/// verisons of PoreVe.
+///
+/// \todo Figure out if there is a way to make this more generic without having
+/// to use a template.
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#include <list>
+#include <map>
+#include <utility>
+
+#include <fapi.H>
+
+#include "poremodel.H"
+
+namespace vsbe {
+
+ struct HookTable;
+ struct ExtractedHook;
+ struct Hook;
+ struct GlobalSymbolInfo;
+ class HookManager;
+ class HookInitializer;
+ class PoreAddress;
+ class PoreAddressComparison;
+ class CharPointerComparison;
+ class Pore;
+
+ /// An "OK" return code for use by hook routines
+ extern fapi::ReturnCode hookOk;
+
+ /// \enum HookType
+ ///
+ /// The type of a hook. See the comments for the file hookmanager.H.
+ enum HookType {
+ HOOK_INSTRUCTION,
+ HOOK_READ_INTERACTIVE,
+ HOOK_WRITE_INTERACTIVE,
+ HOOK_FETCH_INTERACTIVE,
+ HOOK_READ_EXTRACTED,
+ HOOK_WRITE_EXTRACTED,
+ HOOK_FETCH_EXTRACTED
+ };
+
+ /// The type of a HOOK instruction hook
+ ///
+ /// \param[in] i_address The effective address of the HOOK instruction
+ ///
+ /// \param[in] i_hook The low-order 24 bits of the HOOK instruction
+ ///
+ /// \param[in] i_Parameter A 64-bit parameter for the hook
+ ///
+ /// \param[in,out] io_pore The Pore model, to allow the hook to examine or
+ /// modify the state of the PORE.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ typedef fapi::ReturnCode
+ (*HookInstructionHook)(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// The type of an address-based hook
+ ///
+ /// \param[in] i_address The effective address associated with the hook
+ ///
+ /// \param[in] i_type The type of the address-based hook
+ ///
+ /// \param[in,out] io_pore A reference to the Pore model, to allow the
+ /// hook to examine or modify the state of the PORE.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ typedef fapi::ReturnCode
+ (*AddressBasedHook)(const PoreAddress& i_address,
+ const HookType i_type,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// \enum HookError
+ ///
+ /// These error conditions are recognized both while the hook manager is
+ /// being initialized, and at run time. The last error code generated is
+ /// stored in the iv_error field of the HookManager.
+ enum HookError {
+ HOOK_OK = 0,
+ /// File name collision between hooked files
+ HOOK_FILE_NAME_COLLISION = 1,
+ /// Multiply defined symbol
+ HOOK_MULTIPLY_DEFINED_SYMBOL = 2,
+ /// A HookTable for a file is missing, suggesting hooks are out of
+ /// sync with the hooked sources
+ HOOK_TABLE_MISSING = 3,
+ /// Hook index too large, suggesting hooks are out of sync with the
+ /// hooked sources
+ HOOK_INDEX_FAILURE = 4,
+ /// An attempt was made to map more than one hook to a static hook
+ /// index.
+ HOOK_STATIC_COLLISION = 5,
+ /// Deprecated: An instruction hook was called for but not found
+ HOOK_INSTRUCTION_NOT_FOUND = 6,
+ /// An illegal HookType was specified for an API
+ HOOK_ILLEGAL_TYPE = 7,
+ /// Memory allocation failure for a new interactive hook
+ HOOK_MEMORY_ALLOCATION_FAILED = 8,
+ /// A request to delete a specific interactive hook failed
+ HOOK_INTERACTIVE_DELETE_FAILED = 9,
+ /// There is a bug in the HookManager
+ HOOK_BUG = 10,
+ };
+
+ /// \defgroup hookmanager_report_options HookManager Report Options
+ ///
+ /// By default, the HookManager::report() method prints all elements of
+ /// the report. An OR-combination of these flags can also be supplied as
+ /// the argument to explicitly specify that individual sections of the
+ /// report be printed.
+ ///
+ /// @{
+
+ /// Print the hooked address map
+ const int HM_REPORT_HOOKED_ADDRESS_MAP = 0x1;
+
+ /// Print the hook tables
+ const int HM_REPORT_HOOK_TABLES = 0x2;
+
+ /// Print the instruction hook map
+ const int HM_REPORT_INSTRUCTION_HOOK_MAP = 0x4;
+
+ /// Print the global symbol map
+ const int HM_REPORT_GLOBAL_SYMBOL_MAP = 0x8;
+
+ /// @}
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookTable
+////////////////////////////////////////////////////////////////////////////
+
+/// A table of AddressBasedHook function pointers associated with a source
+/// file.
+///
+/// These structures are created by the \e hook_extractor script as it
+/// processes the input to the assembler. Therefore the size of the \a
+/// iv_hooks table is constant and known at compile time. To save space the
+/// name of the file is not included here - instead the file name is the map
+/// key.
+
+struct
+vsbe::HookTable {
+
+ /// The number of hooks defined for the file
+ size_t iv_entries;
+
+ /// The table of addresses of the hook routines
+ AddressBasedHook *iv_hooks;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// ExtractedHook
+////////////////////////////////////////////////////////////////////////////
+
+/// An index record for a hook extracted from a source file
+
+struct
+vsbe::ExtractedHook {
+
+ /// The file name of the hooked source file
+ const char* iv_file;
+
+ /// The index of the hook within the file
+ size_t iv_index;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// Hook
+////////////////////////////////////////////////////////////////////////////
+
+/// A reference to a hook associated with a particular PORE address
+///
+/// The hook architecture allows multiple hooks to be associated with a single
+/// address. This situation could arise both by design and also by accident
+/// depending for example on conditional compilation or macro expansion. To
+/// support all of read, write and fetch hooks as well as static
+/// initialization of extracted hooks, this structure holds a generic hook
+/// pointer and a \a type field that indicates whether to interpret the
+/// pointer as a pointer to an ExtractedHook, or a direct pointer to an
+/// AddressBasedHook.
+
+struct
+vsbe::Hook {
+
+ /// The type of hook; See the enumeration HookType
+ HookType iv_type;
+
+ /// Either an AddressBasedHook or a pointer to an ExtractedHook, depending
+ /// on the HookType
+ void* iv_hook;
+
+ /// List linkage
+ struct Hook* iv_next;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// GlobalSymbolInfo
+////////////////////////////////////////////////////////////////////////////
+
+/// Global Symbol Information
+///
+/// Global symbols are mapped by name. This structure includes the symbol
+/// address as a PoreAddress plus type information.
+
+struct
+vsbe::GlobalSymbolInfo {
+
+ /// The symbol address
+ PoreAddress iv_address;
+
+ /// The symbol type
+ ///
+ /// Symbol types are the character codes reported by \e nm:
+ ///
+ /// - \c B Global BSS (uninitialized data)
+ /// - \c C Global common (uninitialized data)
+ /// - \c D Global initialized data
+ /// - \c T Global text (code)
+ /// - \c R Global read only data
+ char iv_type;
+};
+
+
+namespace vsbe {
+ /// An STL list of <const char *, const GlobalSymbolInfo*> pairs
+ ///
+ /// This structure is defined for use in calls to
+ /// HookManager::globalSymbolList().
+ typedef std::list< std::pair<const char*, const GlobalSymbolInfo*> >
+ GlobalSymbolList;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreAddressComparison
+////////////////////////////////////////////////////////////////////////////
+
+/// PoreAddress comparison class
+///
+/// This class defines the comparison operator for STL containers using a
+/// PoreAddress as the key.
+
+////////////////////////////////////////////////////////////////////////////
+// CharPointerComparison
+////////////////////////////////////////////////////////////////////////////
+
+/// char* comparison class
+///
+/// This class defines the comparison operator for STL containers using a
+/// char* as the key.
+
+class
+vsbe::CharPointerComparison {
+
+public:
+
+ CharPointerComparison() {}
+
+ ~CharPointerComparison() {}
+
+ /// Compare CharPointer*
+ ///
+ /// \param[in] i_lhs Left hand side object
+ ///
+ /// \param[in] i_rhs Right hand side object
+ ///
+ /// \retval rc This is a simply strcmp(ilhs, irhs) < 0
+ bool operator() (char const* i_lhs,
+ char const* i_rhs) const;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ // STL requires a copy operator
+ CharPointerComparison& operator=(const CharPointerComparison& rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookManager
+////////////////////////////////////////////////////////////////////////////
+
+/// A singleton class for managing code hooks for PORE VE
+///
+/// The hook manager is a portable C++ implementation of a symbol table for
+/// hook functions, hooked instructions and global symbols. Only one
+/// HookManager exists at any time. All methods are static and internally
+/// reference a singleton instance of a HookManager. The HookManager supports
+/// two main types of hooks:
+///
+/// - Pre-defined hooks associated with the PORE HOOKI instruction. The HOOKI
+/// instruction encodes an unsigned integer index of a hook routine to execute
+/// at that point, and also includes an uninterpreted 64-bit parameter. The
+/// mapping of hook indices to hook routines will likely be done
+/// statically. The HOOK instruction is otherwise a NOP.
+///
+/// - Address-based hooks are hooks that are attached to data loads and stores
+/// or instruction fetches. These hooks are normally attached by a scripting
+/// discipline that processes the input of the assembler to extract the hooks
+/// into a separate build and load path. Debugging environments can also add
+/// and delete hooks at run time.
+///
+/// The symbol table architecure and layout were designed to simplify the
+/// mapping and reduce space for the case that hooks are required during a
+/// space-constrained HBI procedure. Most symbol table data are defined as
+/// constants in the shared objects that initialize the hooks, and should
+/// never need to be copied.
+///
+/// The HookManager maintains 4 maps:
+///
+/// - A map that maps predefined hook indices encoded in HOOKI instructions to
+/// the routines that implement the hook. This map is created by calls of
+/// registerInstructionHook().
+///
+/// - A map that maps a source file name to a HookTable, that is table of
+/// function pointers to the routines that implement the hooks. This map is
+/// created by calls of registerHookTable().
+///
+/// - A map that maps a 48-bit \e effective PORE address to a list of Hook
+/// objects that identify the hook(s) associated with a PORE address. This map
+/// is created by calls of registerHook().
+///
+/// - A map that maps a PORE global symbol name to a pair <address, type>.
+/// This map is created by calls of registerGlobalSymbol().
+
+class
+vsbe::HookManager {
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ /// A map of HOOKI instruction indices to a HookInstructionHook
+ ///
+ /// This map is created by calls of registerInstructionHook(). The
+ /// application that provides the semantics of each HOOKI instruction
+ /// index will make these calls. The map is used by the
+ /// runInstructionHook() API to locate the entry point associated with a
+ /// HOOKI index.
+ typedef std::map<uint32_t, HookInstructionHook> InstructionHookMap;
+
+ /// A map of file names to hook routine tables
+ ///
+ /// This mapping is created by the *.hook.cc file that is generated by the
+ /// hook_extractor script for each file of assembler source code. Each
+ /// one of the *.hook.cc files maps the source code file name to a table
+ /// of entry points of the hooks extracted from that file. The
+ /// hook_indexer script references these tables to map hooked PORE
+ /// addresses to the entry point that implements the hook.
+ typedef std::map<const char*, const HookTable*> HookedFileMap;
+
+ /// A map of PORE addresses to lists of hooks
+ ///
+ /// This map is created by the registerHook() API. For extracted hooks,
+ /// these calls are made from the *.hooks.cc file created by the
+ /// hook_indexer from the symbol table of the final link image. The
+ /// registerHook() API can also be called dynamically by advanced
+ /// applications like the PDBG debugger for PORE programs. This map is
+ /// referenced by the runHooks() API.
+ ///
+ /// \note The comparison operator being used here is '<' on the uint64_t
+ /// form of the PoreAddress.
+ typedef std::map<const PoreAddress, Hook*> HookedAddressMap;
+
+ /// A map of global symbol names to their parameters
+ ///
+ /// This map is created by calls of registerGlobalSymbol(), called from
+ /// the *.hooks.cc file created by the hook_indexer script. This mapping
+ /// allows the allows the application to find global symbol addresses
+ /// using the findGlobalSymbol() API.
+ typedef std::map<const char*, const GlobalSymbolInfo*,
+ CharPointerComparison> GlobalSymbolMap;
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ virtual ~HookManager();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ /// Access the singleton instance
+ ///
+ /// This is a standard design pattern: If the static singleton instance of
+ /// the class already exists, return it. Otherwise create it first.
+ static HookManager* instance() {
+ if (s_instance == 0) {
+ s_instance = new HookManager();
+ }
+ return s_instance;
+ }
+
+ /// Run a hook assigned to a HOOKI instruction encoding
+ ///
+ /// \param[in] i_address The effective address of the HOOKI instruction.
+ ///
+ /// \param[in] i_hook The index of the hook to run, taken from the
+ /// low-order 24 bits of the HOOKI instruction.
+ ///
+ /// \param[in] i_parameter A 64-bit parameter for the hook.
+ ///
+ /// \param[in,out] io_pore A reference to the Pore object, to allow hooks
+ /// to examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// \retval rc If there is a hook routine associated with the hook index
+ /// \a i_hook, then this is the FAPI return code returned by the hook,
+ /// otherwise an "ok" (0) FAPI return code. There is no requirememt that
+ /// a hook routine be present in the Hookmanager for any instruction hook
+ /// index.
+ static fapi::ReturnCode
+ runInstructionHook(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Run any hooks associated with a data read of an effective address
+ ///
+ /// \param[in] i_address The effective address of the data read
+ ///
+ /// \param[in,out] io_pore A reference to the Pore object, to allow hooks
+ /// to examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// If supported by the environment this method will be called before
+ /// every data read to run any hooks associated with reading the address.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ static fapi::ReturnCode
+ runReadHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Run any hooks associated with a data write of an effective address
+ ///
+ /// \param[in] i_address The effective address of the data write
+ ///
+ /// \param[in,out] io_pore A pointer to the Pore object, to allow hooks to
+ /// examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ static fapi::ReturnCode
+ runWriteHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Run any hooks associated with an instruction fetch of an effective
+ /// address
+ ///
+ /// \param[in] i_address The effective address of the instruction fetch
+ ///
+ /// \param[in,out] io_pore A pointer to the Pore object, to allow hooks to
+ /// examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// If supported by the environment this method will be called before
+ /// every instruction fetch to run any hooks associated with executing the
+ /// address.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ static fapi::ReturnCode
+ runFetchHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Find a global symbol in the HookManager symbol table
+ ///
+ /// \param[in] i_symbol The global symbol name to search for
+ ///
+ /// \param[out] o_found Indicates whether the symbol was found
+ ///
+ /// \param[in,out] io_info If the symbol is was found, this
+ /// reference is modified to contain the symbol information, otherwise the
+ /// reference is not modified.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set at entry. To clear the
+ /// error status use clearError().
+ static HookError
+ findGlobalSymbol(const char* i_symbol,
+ bool& o_found,
+ GlobalSymbolInfo& io_info);
+
+ /// Update a list of GlobalSymbolInfo based on the current state
+ ///
+ /// \param[in,out] io_symbols This is a reference to an instance of
+ /// GlobalSymbolList, an STL list of <const char*, const GlobalSymbolInfo*>
+ /// pairs.
+ ///
+ /// \param[in] i_types This optional parameter is a 0-terminated character
+ /// string containing 0 or more character codes of symbol types. Only
+ /// symbols whose type code is an element of the string are appended to \a
+ /// io_symbols. If \a i_types is 0 (or defaulted) then all global symbols
+ /// are returned. It probably doesn't make sense to call
+ /// globalSymbolList() with \a i_types as "" since this call would have no
+ /// effect.
+ ///
+ /// This routine takes a reference to a GlobalSymbolList, and operates by
+ /// appending (using the STL list push_back() method) a pair consisting of
+ /// the symbol name string and a pointer to a GlobalSymbolInfo structure
+ /// for each global symbol currently stored in the Global Symbol Table
+ /// that matches the symbol type filter. Type filtering is described with
+ /// the \a i_types argument. Global symbols are appended to \a io_symbols
+ /// in the lexicographic order defined by strcmp() < 0 on the character
+ /// string symbol names (i.e., they come back sorted by name).
+ ///
+ /// globalSymbolList() only appends to the list passed as the \a
+ /// io_symbols reference. Use the STL list clear() method to clear the
+ /// list if necessary prior to calling globalSymbolList().
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set at entry. To clear the
+ /// error status use clearError().
+ static HookError
+ globalSymbolList(GlobalSymbolList& io_symbols, const char* i_types = 0);
+
+ /// Report the HookManager state to the FAPI_INF() stream
+ ///
+ /// \param[in] i_options Options are selected as an OR-combination of the
+ /// options documented as \ref hookmanager_report_options. By default all
+ /// elements of the report are printed.
+ ///
+ /// \retval 0 Success
+ static void
+ report(const int i_options = -1);
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Register a HOOKI instruction hook with the HookManager
+ ///
+ /// \param[in] i_index The hook index as it will be stored in the HOOKI
+ /// instruction.
+ ///
+ /// \param[in] i_hookRoutine The hook routine
+ ///
+ /// It is considered an immediate fatal error (HOOK_STATIC_COLLISION) if
+ /// an attempt is made to map a single index to different hooks. Although
+ /// the HookManager could be easily modified to support multiple static
+ /// hooks for a single index if required, the current thinking is that
+ /// this more likely represents an error in assigning hook indices rather
+ /// than a useful feature.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerInstructionHook(const uint32_t i_index,
+ HookInstructionHook i_hookRoutine);
+
+ /// Register a hook table with the hook manager
+ ///
+ /// \param[in] i_file The file name associated with the HookTable. This
+ /// string is assumed to be a permanent static allocation and is not
+ /// copied or storage managed by the HookManager.
+ ///
+ /// \param[in] i_table A pointer to a HookTable structure. This structure
+ /// is assumed to be a permanent static allocation and is not copied or
+ /// storage managed by the HookManager.
+ ///
+ /// The table is mapped by the hook manager based on the file name stored
+ /// in the table. It is considered an immediate fatal error
+ /// (HOOK_FILE_NAME_COLLISION) if a file name collision is detected.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerHookTable(const char* i_file,
+ const HookTable* i_table);
+
+ /// Register an extracted Hook structure with the hook manager
+ ///
+ /// \param[in] i_address The effective address of a hooked
+ /// instruction.
+ ///
+ /// \param[in,out] io_hook An initialized Hook structure.
+ ///
+ /// This method is used directly by code generated from an extraction
+ /// script to install a hook for an address, due to the fact that
+ /// extracted hooks are initialized from preconstructed static objects.
+ /// This is also used as an internal method by addInteractiveHook().
+ ///
+ /// If more than one hook is associated with an address, later hooks are
+ /// added at the end of the list of hooks. When the hooks are run they
+ /// are run in list order.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerHook(const PoreAddress& i_address,
+ Hook* io_hook);
+
+ /// Register a global symbol with the hook manager
+ ///
+ /// \param[in] i_symbol The symbol name. This string is assumed to be a
+ /// permanent static allocation and is not copied or storage managed by
+ /// the HookManager.
+ ///
+ /// \param[in] i_info Information about the symbol. This structure is
+ /// assumed to be a permanent static allocation and is not copied or
+ /// storage managed by the HookManager.
+ ///
+ /// For simplicity, it is considered an immediate fatal error
+ /// (HOOK_MULTIPLY_DEFINED_SYMBOL) to hook a symbol more than once. If we
+ /// need to provide similarly-named symbols in different address spaces
+ /// then we'll need to revisit the implementation.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerGlobalSymbol(const char* i_symbol,
+ const GlobalSymbolInfo* i_info);
+
+ /// Add an interactive hook to a PoreAddress
+ ///
+ /// \param[in] i_address The effective address of the hooked
+ /// instruction or data.
+ ///
+ /// \param[in] i_type The hook type, which must be one of the *INTERACTIVE
+ /// types.
+ ///
+ /// \param[in] i_hookRoutine The AddressBasedHook that implements the hook.
+ ///
+ /// Create and install an interactive hook of \a i_type for an effective
+ /// PORE address. If more than one hook is associated with an address,
+ /// later hooks are added at the end of the list of hooks. When the hooks
+ /// are run they are run in list order.
+ ///
+ /// \retval rc A non-zero return value indicates any error that occurred.
+ /// This method fails immediately if HookManager error status is set at
+ /// entry. To clear the error status use clearError().
+ static HookError
+ addInteractiveHook(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine);
+
+ /// Delete interactive hooks of a given type from a PoreAddress
+ ///
+ /// \param[in] i_address The effective address of the hooked
+ /// instruction or data.
+ ///
+ /// \param[in] i_type The hook type, which must be one of the *INTERACTIVE
+ /// types.
+ ///
+ /// \param[in] i_hookRoutine The AddressBasedHook that implements the
+ /// hook, or a default value of 0 which means to delete all interactive
+ /// hooks of the given type from the address.
+ ///
+ /// By default, delete all interactive hooks of \a i_type from an
+ /// effective PORE address. If \a i_hook is not 0, then all occurrences
+ /// of only that particular hook are deleted.
+ ///
+ /// \retval rc A non-zero return value indicates any error that occurred.
+ /// This method fails immediately if HookManager error status is set at
+ /// entry. To clear the error status use clearError().
+ static HookError
+ deleteInteractiveHooks(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine = 0);
+
+ /// Clear the HookManager error status
+ ///
+ /// The HookManager has 'sticky' error status - new operations on the
+ /// HookManager will fail if the error status is non-zero. This method
+ /// clears the error status.
+ static void
+ clearError();
+
+ ////////////////////////// Implementation ////////////////////////////
+
+ /// The last HookError encountered
+ ///
+ /// Many of the HookError conditions arise during load-time
+ /// initialization, when there's really no recourse for trapping or
+ /// handling them. Instead, if the iv_error is non-0 then all load-time
+ /// HookManager APIs return immediately, allowing some diagnosis (of the
+ /// first error) after initialization. The interactive methods set and
+ /// return \a iv_error with the final return code but do not block further
+ /// operations.
+ HookError iv_error;
+
+ // NB: s_instance must be public for the Simics workaround
+
+ /// The singleton instance of the HookManager
+ static HookManager* s_instance;
+
+protected:
+
+ /// The instruction hook map
+ InstructionHookMap iv_instructionHookMap;
+
+ /// The hooked file map
+ HookedFileMap iv_hookedFileMap;
+
+ /// The hooked address map
+ ///
+ /// The HookManager system maintains an invariant that if an entry in this
+ /// map exists, then the list of hooks associated with that address is not
+ /// empty (i.e., the pointer is not 0).
+ HookedAddressMap iv_hookedAddressMap;
+
+ /// The global symbol map
+ GlobalSymbolMap iv_globalSymbolMap;
+
+ /// Run a specific type of hook
+ ///
+ /// \param[in] i_interactiveType One of the *INTERACTIVE HookType.
+ ///
+ /// \param[in] i_extractedType The *EXTRACTED counterpart of the
+ /// interactive type.
+ ///
+ /// \param[in] i_address The current effective address.
+ ///
+ /// \param[in,out] io_pore The Pore model, to allow the hook to examine or
+ /// modify the state of the PORE.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// This is a helper method for runReadHooks(), runWriteHooks() and
+ /// runFetchHooks() that actually does the search and execution, given an
+ /// interactive and extracted hook type to search.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ fapi::ReturnCode
+ runHooks(const HookType i_interactiveType,
+ const HookType i_extractedType,
+ const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ HookManager();
+ HookManager(const HookManager& i_rhs);
+ HookManager& operator=(const HookManager& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookInitializer
+////////////////////////////////////////////////////////////////////////////
+
+/// A dummy class used to initialize the HookManager
+///
+/// Initialization of the HookManager depends on the ability of C++ to run
+/// object constructors at load time. Each hook file and indexing file
+/// contains an initialization function that installs information into the
+/// symbol table. Each hook file also creates an instance of the
+/// HookInitializer whose sole purpose is to run the initialization function
+/// in its constructor at load time.
+
+class
+vsbe::HookInitializer {
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ /// The type of a HookManager initializer function
+ typedef void (*HookManagerInitializer)();
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create an HookInitializer
+ ///
+ /// \param[in] i_function The function to call during construction of the
+ /// otherwise empty object.
+ HookInitializer(HookManagerInitializer i_function);
+
+ ~HookInitializer();
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ HookInitializer(const HookInitializer& rhs);
+ HookInitializer& operator=(const HookInitializer& rhs);
+};
+
+
+#endif // __VSBE_HOOKMANAGER_H
diff --git a/src/usr/pore/poreve/porevesrc/pib2cfam.C b/src/usr/pore/poreve/porevesrc/pib2cfam.C
new file mode 100644
index 000000000..cf6100767
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pib2cfam.C
@@ -0,0 +1,167 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pib2cfam.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: pib2cfam.C,v 1.9 2012/01/09 21:22:50 jeshua Exp $
+
+/// \file pib2cfam.C
+/// \brief A temporary hack while waiting for hardware updates - a simple
+/// PibSlave that maps a small range of PIB addresses to CFAM addresses.
+///
+/// \todo Verify the assumption that the high-order 32 bits of the 64-bit data
+/// are the bits that are read and written to the CFAM register.
+
+#include "pib2cfam.H"
+//JDS TODO - remove the ECMD headers once we've got attribute support
+#ifndef __HOSTBOOT_MODULE
+#include "fapiSharedUtils.H"
+#include "ecmdUtils.H"
+#endif
+using namespace vsbe;
+
+
+////////////////////////////// Creators //////////////////////////////
+
+Pib2Cfam::Pib2Cfam()
+{
+}
+
+
+Pib2Cfam::~Pib2Cfam()
+{
+}
+
+
+//////////////////////////// Manipulators ////////////////////////////
+
+static uint32_t
+translateAddress(uint32_t address, fapi::Target* i_target)
+{
+ //JDS TODO - change this to get attribute ATTR_FSI_GP_REG_SCOM_ACCESS
+ bool fsi_gpreg_scom_access = false;
+#ifndef __HOSTBOOT_MODULE
+ ecmdChipData chipdata;
+ ecmdChipTarget e_target;
+ uint32_t rc;
+ std::string chip_type;
+
+ fapiTargetToEcmdTarget( *i_target, e_target);
+ rc = ecmdGetChipData(e_target, chipdata);
+ if( rc ) printf( "Problem with getchipdata\n" );
+ chip_type = chipdata.chipType;
+
+ if( chip_type == "centaur" ) {
+ fsi_gpreg_scom_access = false;
+ } else {
+ fsi_gpreg_scom_access = true;
+ }
+#endif
+
+ if( fsi_gpreg_scom_access ) {
+ return (address - 0x00050000) + 0x2800;
+ } else {
+ return (address - 0x00050000) + 0x1000;
+ }
+}
+
+
+fapi::ReturnCode
+Pib2Cfam::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ switch (io_transaction.iv_mode) {
+
+ case ACCESS_MODE_READ:
+
+ switch (io_transaction.iv_address) {
+
+ case 0x00050012:
+ case 0x00050013:
+ case 0x00050014:
+ case 0x00050015:
+ case 0x00050016:
+ case 0x00050019:
+ case 0x0005001A:
+ case 0x0005001B:
+ rc = fapiGetCfamRegister(*iv_target,
+ translateAddress(io_transaction.iv_address, iv_target),
+ *iv_dataBuffer);
+ if (rc.ok()) {
+ io_transaction.iv_data =
+ ((uint64_t)iv_dataBuffer->getWord(0)) << 32;
+ me = ME_SUCCESS;
+ } else {
+ me = ME_FAILURE;
+ }
+ break;
+ default:
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ }
+ break;
+
+ case ACCESS_MODE_WRITE:
+
+ switch (io_transaction.iv_address) {
+
+ case 0x00050012:
+ case 0x00050013:
+ case 0x00050014:
+ case 0x00050015:
+ case 0x00050016:
+ case 0x0005001B:
+ iv_dataBuffer->setWordLength(1);
+ iv_dataBuffer->setWord(0, io_transaction.iv_data >> 32);
+ rc = fapiPutCfamRegister(*iv_target,
+ translateAddress(io_transaction.iv_address, iv_target),
+ *iv_dataBuffer);
+ if (rc.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_FAILURE;
+ }
+ break;
+
+ case 0x00050019:
+ case 0x0005001A:
+ rc = 1;
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ break;
+
+ default:
+ rc = 1;
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ }
+ break;
+
+ default:
+ rc = 1;
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ break;
+ }
+ io_transaction.busError(me);
+ return rc;
+}
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/poreve/porevesrc/pib2cfam.H b/src/usr/pore/poreve/porevesrc/pib2cfam.H
new file mode 100644
index 000000000..329d3f0a3
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pib2cfam.H
@@ -0,0 +1,94 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pib2cfam.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_PIB2CFAM_H
+#define __VSBE_PIB2CFAM_H
+
+// $Id: pib2cfam.H,v 1.3 2011/06/21 00:07:35 bcbrock Exp $
+
+/// \file pib2cfam.H
+/// \brief A temporary hack while waiting for hardware updates - a simple
+/// PibSlave that maps a small range of PIB addresses to CFAM addresses.
+
+#include "bus.H"
+
+namespace vsbe {
+
+ class Pib2Cfam;
+
+ /// PIB base address of PIB range mapped by Pib2Cfam
+ const uint32_t PIB2CFAM_PIB_BASE = 0x00050012;
+
+ /// Number of PIB addresses mapped by Pib2Cfam
+ const int PIB2CFAM_PIB_SIZE = ((0x0005001b - 0x00050012) + 1);
+}
+
+
+/// Map PIB accesses to CFAM accesses
+
+class
+vsbe::Pib2Cfam : public PibSlave {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ Pib2Cfam();
+
+ virtual ~Pib2Cfam();
+
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Pib2Cfam operation
+ ///
+ /// \param[in,out] io_transaction A PIB transaction object
+ ///
+ /// This object converts PIB transactions in a certain range in the
+ /// virtual environment to FAPI PutCfamregister() and GetCfamRegister()
+ /// calls, returning the FAPI return code from the translated calls.
+ ///
+ /// The following PIB registers are mapped to CFAM registers:
+ ///
+ /// - PIB 0x00050012 -> CFAM 0x1012, FSIGP3, R/W
+ /// - PIB 0x00050013 -> CFAM 0x1013, FSIGP4, R/W
+ /// - PIB 0x00050014 -> CFAM 0x1014, FSIGP5, R/W
+ /// - PIB 0x00050015 -> CFAM 0x1015, FSIGP6, R/W
+ /// - PIB 0x00050016 -> CFAM 0x1016, FSIGP7, R/W
+ /// - PIB 0x00050019 -> CFAM 0x1019, OSC switch sense 1, R
+ /// - PIB 0x0005001A -> CFAM 0x101A, OSC switch sense 2, R
+ /// - PIB 0x0005001B -> CFAM 0x101B, GP3 Mirror, R/W
+ ///
+ /// \retval rc The fapi::ReturnCode returned by the underlying
+ /// PutCfamRegister() or GetCfamRegister() call.
+ fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ Pib2Cfam(const Pib2Cfam& rhs);
+ Pib2Cfam& operator=(const Pib2Cfam& rhs);
+};
+
+#endif // __VSBE_PIB2CFAM_H
diff --git a/src/usr/pore/poreve/porevesrc/pore.C b/src/usr/pore/poreve/porevesrc/pore.C
new file mode 100644
index 000000000..8f09e2e29
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pore.C
@@ -0,0 +1,269 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pore.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// $Id: pore.C,v 1.13 2011/11/17 19:05:22 jeshua Exp $
+
+/// \file pore.C
+/// \brief The implementation of the PoreInterface for the PoreVe environment
+
+#include "pore.H"
+
+using namespace vsbe;
+
+
+///////////////////////// Control Interface /////////////////////////
+
+ModelError
+Pore::forceBranch(const char* i_symbol)
+{
+ ModelError me;
+ HookError he;
+ bool found;
+ GlobalSymbolInfo info;
+
+ he = HookManager::findGlobalSymbol(i_symbol, found, info);
+ if (he || !found) {
+ me = ME_ILLEGAL_FORCED_BRANCH;
+ } else {
+ me = PoreInterface::forceBranch(info.iv_address);
+ }
+ return me;
+}
+
+
+//////////////////// PoreInterface Methods /////////////////////////
+
+/// \bug We need a FAPI return code for an illegaly configured model
+
+void
+Pore::pibMaster(PibTransaction& io_transaction)
+{
+ ModelError me;
+
+ if (iv_pib == 0) {
+ me = ME_NO_BUS_MODEL;
+ io_transaction.busError(me);
+ iv_fapiReturnCode = 1; /// \bug Need a return code
+ } else {
+ iv_fapiReturnCode = iv_pib->operation(io_transaction);
+ me = io_transaction.iv_modelError;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::ociMaster(OciTransaction& io_transaction)
+{
+ ModelError me;
+
+ if (iv_oci == 0) {
+ me = ME_NO_BUS_MODEL;
+ io_transaction.busError(me);
+ iv_fapiReturnCode = 1; /// \bug Need a return code
+ } else {
+ iv_fapiReturnCode = iv_oci->operation(io_transaction);
+ me = io_transaction.iv_modelError;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::wait(const uint32_t i_count)
+{
+ uint64_t simCycles;
+ uint64_t nsDelay;
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ nsDelay = (uint64_t)((i_count * 1e9) / PORE_FREQUENCY);
+
+ simCycles = (uint64_t)
+ (SIMULATOR_TICK_FREQUENCY * (i_count / PORE_FREQUENCY));
+ nsDelay += 1; // Always round up the real delay.
+ iv_fapiReturnCode = fapiDelay(nsDelay, simCycles);
+
+ if (iv_fapiReturnCode == 0) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_WAIT_FAILURE;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runInstructionHook(i_address, i_hook, i_parameter,
+ *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_INSTRUCTION_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookRead(const PoreAddress& i_address)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runReadHooks(i_address, *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_READ_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookWrite(const PoreAddress& i_address)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runWriteHooks(i_address, *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_WRITE_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookFetch(const PoreAddress& i_address)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runFetchHooks(i_address, *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_FETCH_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+//////////////////////// PibSlave Methods ////////////////////////////
+
+// All offsets are known to be legal. PIB offsets are converted to OCI
+// offsets used in the register read/write methods.
+
+fapi::ReturnCode
+Pore::operation(Transaction& io_transaction)
+{
+ ModelError me;
+ fapi::ReturnCode rc;
+
+ switch (io_transaction.iv_mode) {
+
+ case ACCESS_MODE_READ:
+ me = registerRead((PoreRegisterOffset)(io_transaction.iv_offset * 8),
+ io_transaction.iv_data);
+ break;
+
+ case ACCESS_MODE_WRITE:
+ me = registerWrite((PoreRegisterOffset)(io_transaction.iv_offset * 8),
+ io_transaction.iv_data);
+ break;
+
+ default:
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ break;
+ }
+
+ if (me) {
+ rc = 1; /// \bug Fix this
+ }
+ io_transaction.busError(me);
+ return rc;
+}
+
+
+////////////////////////////// Creators //////////////////////////////
+
+Pore::Pore(PoreIbufId i_id) :
+ PoreInterface(i_id),
+ iv_pib(0),
+ iv_oci(0),
+ iv_target(NULL)
+{
+}
+
+
+Pore::~Pore()
+{
+}
+
+
+//////////////////// Interface Extensions /////////////////////////
+
+void
+Pore::configure(fapi::Target* i_target, Bus* i_pib, Bus* i_oci,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base, uint64_t i_size, int i_permissions)
+{
+ iv_target = i_target;
+ iv_pib = i_pib;
+ iv_oci = i_oci;
+ PibSlave::configure(i_target, i_dataBuffer,
+ i_base, i_size, i_permissions);
+}
+
+
+fapi::ReturnCode
+Pore::getFapiReturnCode()
+{
+ return iv_fapiReturnCode;
+}
+
+
diff --git a/src/usr/pore/poreve/porevesrc/pore.H b/src/usr/pore/poreve/porevesrc/pore.H
new file mode 100644
index 000000000..7b773d0ad
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pore.H
@@ -0,0 +1,259 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pore.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_PORE_H
+#define __VSBE_PORE_H
+
+// $Id: pore.H,v 1.14 2011/11/17 19:04:47 jeshua Exp $
+
+/// \file pore.H
+/// \brief The implementation of the PoreInterface for the PoreVe environment
+
+#include <fapi.H>
+
+#include "bus.H"
+#include "poremodel.H"
+#include "hookmanager.H"
+
+ #ifdef VBU_HACKS
+ #include "fapiSharedUtils.H"
+ #include "ecmdUtils.H"
+ #endif // VBU_HACKS
+
+
+namespace vsbe {
+
+ class Pore;
+
+ /// This is the putative tick frequency of the simulation environment,
+ /// used to model the wait() method.
+ const double SIMULATOR_TICK_FREQUENCY = 12e9;
+
+ /// This is the expected operating frequency of the PORE hardware engine,
+ /// used to model the wait() method.
+ const double PORE_FREQUENCY = 600e6;
+};
+
+
+/// The implementation of the PoreInterface for the PoreVe environment
+///
+/// This class provides implementations of the virtual interface to the
+/// PoreModel for the PoreVe environment. The Pore is configured by providing
+/// pointers to the PIB and OCI bus models of the environment. The Pore also
+/// contains the last FAPI return code produced by an operation in the virtual
+/// environment.
+///
+/// The Pore class is also derived from the PibSlave class. This enables the
+/// PORE engine to 'self-SCOM' PORE control registers that are not visible as
+/// part of the architected state. Since our PoreVe environment does not
+/// included a generic OCB bridge, all self-SCOM must be programmed using PIB
+/// addresses.
+
+class
+vsbe::Pore : public PoreInterface,
+ public PibSlave
+{
+
+public:
+
+ ///////////////////////// Control Interface /////////////////////////
+
+ /// Force a branch to a global symbol name
+ ///
+ /// \param[in] i_symbol A global symbol name; the branch target
+ ///
+ /// Pore provides a variant of PoreModel::forceBranch() that forces a
+ /// branch to a global symbol, assuming the global symbol is known to
+ /// HookManager. The error code ME_ILLEGAL_FORCED_BRANCH is returned if
+ /// the symbol is not known to the HookManager.
+ ///
+ /// See PoreModel::forceBranch() for more information
+ ///
+ /// \retval me Either 0 for success or a ModelError code.
+ virtual ModelError
+ forceBranch(const char* i_symbol);
+
+
+ //////////////////// PoreInterface Methods /////////////////////////
+
+ /// See PoreModel::pibMaster() for the interface specification
+ ///
+ /// Run the transaction on the PoreVe PIB Bus model. FAPI errors from
+ /// running PIB/PCB transactions are converted to PCB return codes and
+ /// stored in the \a iv_pcbReturnCode field of the \a io_transaction.
+ void
+ pibMaster(PibTransaction& io_transaction);
+
+ /// See PoreModel::ociMaster() for the interface specification
+ ///
+ /// Run the transaction on the PoreVe OCI Bus model. FAPI errors from
+ /// running OCI transactions are converted to abstract return codes and
+ /// stored in the \a iv_ociReturnCode field of the \a io_transaction.
+
+ void
+ ociMaster(OciTransaction& io_transaction);
+
+ /// See PoreModel::wait() for the interface specification
+ ///
+ /// Simulate a WAIT of \a i_count PORE cycles. The implementation
+ /// attempts to accurately model the wait based on the assumed PORE clock
+ /// frequency, and for simulation, the assumed simulation clock frequency.
+ /// If execution of the WAIT results in a FAPI error, the FAPI error is
+ /// stored in the \a iv_fapiReturnCode.
+
+ void
+ wait(const uint32_t i_count);
+
+ /// See PoreModel::hookInstruction() for the interface specification
+ ///
+ /// Use the HookManager to run the numbered hook called out by a PORE
+ /// HOOKI instruction. It is not considered an error to request a hook
+ /// that is not mapped in the HookManager. If execution of the hook
+ /// results in a FAPI error, the FAPI error is stored in the
+ /// \a iv_fapiReturnCode.
+ void
+ hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter);
+
+ /// See PoreModel::hookRead() for the interface specification
+ ///
+ /// Run any hooks associated with a read of the given effective address.
+ /// If execution of the hook results in a FAPI error, the FAPI error is
+ /// stored in the \a iv_fapiReturnCode.
+ void
+ hookRead(const PoreAddress& i_address);
+
+ /// See PoreModel::hookWrite() for the interface specification
+ ///
+ /// Run any hooks associated with a write of the given effective address.
+ /// If execution of the hook results in a FAPI error, the FAPI error is
+ /// stored in the \a iv_fapiReturnCode.
+ void
+ hookWrite(const PoreAddress& i_address);
+
+ /// See PoreModel::hookFetch() for the interface specification
+ ///
+ /// Run any hooks associated with an instruction fetch of the given
+ /// effective address. If execution of the hook results in a FAPI error,
+ /// the FAPI error is stored in the \a iv_fapiReturnCode.
+ void
+ hookFetch(const PoreAddress& i_address);
+
+ /// See PoreModel::errorIntr() for the interface specification
+ ///
+ /// Currently not implemented by Pore.
+ void
+ errorIntr(void) {}
+
+ /// See PoreModel::fatalErrorIntr() for the interface specification
+ ///
+ /// Currently not implemented by Pore.
+ void
+ fatalErrorIntr(void) {}
+
+
+ //////////////////////// PibSlave Methods ////////////////////////////
+
+ /// See Slave::operation() for the interface specification
+ virtual fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create the Pore
+ ///
+ /// \param[in] i_id The IBUF ID (PORE engine type) of the PORE model to
+ /// create.
+ Pore(PoreIbufId i_id);
+
+ virtual ~Pore();
+
+ //////////////////// Interface Extensions /////////////////////////
+
+ /// Configure the Pore model by providing pointers to the Bus models
+ ///
+ /// \param[in] i_target A pointer to the FAPI target object associated
+ /// with the PORE model, for use in hooks and for purposes of the
+ /// PibSlave.
+ ///
+ /// \param[in] i_pib A Bus model (to be) configured as a PIB bus.
+ ///
+ /// \param[in] i_oci A Bus model (to be) configured as an OCI bus.
+ ///
+ /// \param[in] i_dataBuffer See Slave::configure()
+ ///
+ /// \param[in] i_base See Slave::configure()
+ ///
+ /// \param[in] i_size See Slave::configure()
+ ///
+ /// \param[in] i_permissions See Slave::configure()
+ ///
+ /// This interface is introduced simply to encapsulate everything about
+ /// the Pore that needs to be configured to create a system.
+ void
+ configure(fapi::Target* i_target, Bus* i_pib, Bus* i_oci,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base, uint64_t i_size, int i_permissions);
+
+ /// Get the FAPI return code from the model
+ ///
+ /// \retval rc The last FAPI return code from any PORE operations in the
+ /// environment.
+ fapi::ReturnCode
+ getFapiReturnCode();
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The PoreVe PIB Bus model
+ Bus* iv_pib;
+
+ /// The PoreVe OCI Bus model
+ Bus* iv_oci;
+
+ /// The last FAPI return code
+ ///
+ /// Operations in the PoreVe environment return FAPI ReturnCode objects.
+ /// The FAPI return code is stored here, and the ModelError returned to
+ /// the PoreModel dependson the type of error.
+ fapi::ReturnCode iv_fapiReturnCode;
+
+ /// A pointer to the FAPI target associated with this PORE engine
+ ///
+ /// The Pore object holds this pointer for use as an argument to hook
+ /// routines.
+ fapi::Target* iv_target;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+
+ Pore(const Pore& i_rhs);
+ Pore& operator=(const Pore& i_rhs);
+};
+
+#endif // __VSBE_PORE_H
diff --git a/src/usr/pore/poreve/porevesrc/poreve.C b/src/usr/pore/poreve/porevesrc/poreve.C
new file mode 100644
index 000000000..e0a841cdd
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/poreve.C
@@ -0,0 +1,480 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/poreve.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// $Id: poreve.C,v 1.15 2011/12/14 22:11:51 bcbrock Exp $
+
+/// \file poreve.C
+/// \brief The PORE Virtual Environment
+
+#include "poreve.H"
+
+using namespace vsbe;
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVeBase
+////////////////////////////////////////////////////////////////////////////
+
+
+PoreVeBase::PoreVeBase(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget) :
+ iv_pore(i_id),
+ iv_pnorMemory(PNOR_ADDRESS_BYTES),
+ iv_id(i_id),
+ iv_masterTarget(i_masterTarget),
+ iv_slaveTarget(i_masterTarget)
+{
+ uint32_t porePibBase;
+
+ // Configure the PORE. Only the PIB bus is connected, the OCI bus remains
+ // unconnected (0). The PIB self-SCOM interface configuration is a
+ // function of which PORE egine is being configured. Technically we should
+ // barf if \a i_id is not PORE_SBE or PORE_SLW, but HBI doesn't want any
+ // throw()s.
+
+ if (i_id == PORE_SLW) {
+ porePibBase = PORE_SLW_PIB_BASE;
+ } else {
+ porePibBase = PORE_SBE_PIB_BASE;
+ }
+
+ iv_pore.configure(&iv_slaveTarget, &iv_pib, 0,
+ &iv_dataBuffer,
+ porePibBase, PORE_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_pore);
+
+ // Configure the PNOR controller and attach its memory
+
+ iv_pnorController.configure(&iv_masterTarget,
+ &iv_dataBuffer,
+ PNOR_PIB_BASE,
+ PNOR_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_pnorController);
+
+ iv_pnorController.attachMemory(&iv_pnorMemory,
+ PNOR_I2C_PORT,
+ PNOR_I2C_DEVICE_ADDRESS);
+
+
+ // Configure the PIB catch-all model
+
+ iv_pibDefault.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PIB_DEFAULT_PIB_BASE,
+ PIB_DEFAULT_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachSecondarySlave(&iv_pibDefault);
+}
+
+
+PoreVeBase::~PoreVeBase()
+{
+}
+
+
+// This is a temporary hack: Until the final specification of the reset state
+// of the PORE-SBE engine is available, we initialize the PORE-SBE engine
+// here. This is simpler than trying to keep the PMX model up to date as we
+// mess with chaging requirements, and it's also better for PMX to assume
+// that the PORE-SBE is halted at PMX-IPL, since PMX/Simics is really a model
+// for OCC firmware. This initializaton of PORE-SBE is done here rather than
+// in the PoreModel because we have the memory address assumptions here.
+//
+// If this is a PORE-SBE, then the machine comes up running from OTPROM.
+
+/// \bug Temporary hack
+
+void
+PoreVeBase::reset(fapi::Target i_slaveTarget)
+{
+ iv_slaveTarget = i_slaveTarget;
+ iv_pore.restart();
+ HookManager::clearError();
+
+ if (iv_id == PORE_SBE) {
+
+ // The PMX model comes up halted in OCI space. We set the PC to
+ // OTPROM space and run() 0 instructions. This will clear the stop bit
+ // to start execution.
+
+ PoreAddress pc;
+ uint64_t ran;
+
+ pc.setFromPibAddress(OTPROM_PIB_BASE);
+ iv_pore.setPc(pc);
+ iv_pore.run(0, ran);
+ }
+}
+
+
+int
+PoreVeBase::run(uint64_t i_instructions, uint64_t& o_ran)
+{
+ return iv_pore.run(i_instructions, o_ran);
+}
+
+
+ModelError
+PoreVeBase::getscom(const uint32_t i_address, uint64_t& o_data, int& o_rc)
+{
+ PibTransaction t;
+
+ t.iv_address = i_address;
+ t.iv_mode = ACCESS_MODE_READ;
+
+ iv_pib.operation(t);
+
+ o_data = t.iv_data;
+ o_rc = t.iv_pcbReturnCode;
+ return t.iv_modelError;
+}
+
+
+ModelError
+PoreVeBase::putscom(const uint32_t i_address, const uint64_t i_data, int& o_rc)
+{
+ PibTransaction t;
+
+ t.iv_address = i_address;
+ t.iv_data = i_data;
+ t.iv_mode = ACCESS_MODE_WRITE;
+
+ iv_pib.operation(t);
+
+ o_rc = t.iv_pcbReturnCode;
+ return t.iv_modelError;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVe
+////////////////////////////////////////////////////////////////////////////
+
+PoreVe::PoreVe(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget) :
+ PoreVeBase(i_id, i_masterTarget),
+ iv_seepromMemory(SEEPROM_ADDRESS_BYTES)
+{
+ uint32_t porePibBase;
+
+ // Reconfigure the Pore - this doesn't hurt anything in the previous
+ // configuration in the base class as this is a set of simple pointer and
+ // data assignments. But it's another reason to jettison the requirement
+ // for the base class. The PORE was attached to the PIB in the base
+ // class.
+
+ if (i_id == PORE_SLW) {
+ porePibBase = PORE_SLW_PIB_BASE;
+ } else {
+ porePibBase = PORE_SBE_PIB_BASE;
+ }
+
+ iv_pore.configure(&iv_slaveTarget, &iv_pib, &iv_oci,
+ &iv_dataBuffer,
+ porePibBase, PORE_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ // Configure the OTPROM
+
+ iv_otprom.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ OTPROM_PIB_BASE,
+ OTPROM_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_EXECUTE,
+ &iv_otpromMemory);
+
+ iv_pib.attachPrimarySlave(&iv_otprom);
+
+
+ // Configure the PIBMEM
+
+ iv_pibmem.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PIBMEM_PIB_BASE,
+ PIBMEM_PIB_SIZE,
+ ACCESS_MODE_READ |
+ ACCESS_MODE_WRITE |
+ ACCESS_MODE_EXECUTE,
+ &iv_pibmemMemory);
+
+ iv_pib.attachPrimarySlave(&iv_pibmem);
+
+
+ // Configure the SEEPROM controller
+
+ iv_seepromController.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ SEEPROM_PIB_BASE,
+ SEEPROM_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_seepromController);
+
+ iv_seepromController.attachMemory(&iv_seepromMemory,
+ SEEPROM_I2C_PORT,
+ SEEPROM_I2C_DEVICE_ADDRESS);
+
+ // Configure Mainstore
+
+ iv_main.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ MAINSTORE_OCI_BASE,
+ MAINSTORE_OCI_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE,
+ &iv_mainMemory);
+
+ iv_oci.attachPrimarySlave(&iv_main);
+
+
+ // Configure SRAM
+
+ iv_sram.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ SRAM_OCI_BASE,
+ SRAM_OCI_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE,
+ &iv_sramMemory);
+
+ iv_oci.attachPrimarySlave(&iv_sram);
+
+
+#ifdef PM_HACKS
+ // This device provides write-only access to a single control register in
+ // the PMC.
+
+ iv_pmc.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PMC_OCI_BASE,
+ PMC_OCI_SIZE,
+ ACCESS_MODE_WRITE);
+
+ iv_oci.attachPrimarySlave(&iv_pmc);
+#endif // PM_HACKS
+
+
+#ifdef VBU_HACKS
+ // Configure the temporary Pib2Cfam component
+
+ iv_pib2Cfam.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PIB2CFAM_PIB_BASE,
+ PIB2CFAM_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_pib2Cfam);
+
+ // Configure the temporary sbeVital component
+
+ iv_sbeVital.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ SBEVITAL_PIB_BASE,
+ SBEVITAL_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_sbeVital);
+
+#ifndef SIMPLE_VBU_HACKS_ONLY
+
+ // The VBU_HACKS above are simple - they don't require complex eCMD support so
+ // we can test them easily with the poreve/test/fapistub test case.
+
+ // The VBU hacks below are complicated to emulate, so we don't even try in
+ // the test/fapistub test case.
+
+ // Configure the Broadside scan component if using BROADSIDE scan
+ //JDS TODO - add a check for broadside scan mode
+ ecmdConfigValid_t validOutput;
+ std::string tmpStr;
+ uint32_t tmpNum;
+ uint32_t rc;
+ ecmdChipTarget e_target;
+
+ //JDS TODO - change this to get attribute
+ fapiTargetToEcmdTarget( iv_slaveTarget, e_target);
+ rc = ecmdGetConfiguration(e_target, "SIM_BROADSIDE_MODE",
+ validOutput, tmpStr, tmpNum );
+ if( rc ||
+ validOutput == ECMD_CONFIG_VALID_FIELD_NONE ||
+ validOutput == ECMD_CONFIG_VALID_FIELD_NUMERIC )
+ {
+ FAPI_ERR( "Unable to determine SIM_BROADSIDE_MODE\n" );
+ }
+ else
+ {
+ size_t pos = tmpStr.find( "scan" );
+ if( pos != (uint32_t)-1 )
+ {
+// iv_bsscan_ex00.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX00_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex00);
+
+ iv_bsscan_ex01.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX01_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex01);
+
+ iv_bsscan_ex02.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX02_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex02);
+
+ iv_bsscan_ex03.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX03_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex03);
+
+ iv_bsscan_ex04.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX04_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex04);
+
+ iv_bsscan_ex05.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX05_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex05);
+
+ iv_bsscan_ex06.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX06_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex06);
+
+// iv_bsscan_ex07.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX07_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex07);
+
+// iv_bsscan_ex08.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX08_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex08);
+
+ iv_bsscan_ex09.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX09_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex09);
+
+ iv_bsscan_ex10.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX10_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex10);
+
+ iv_bsscan_ex11.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX11_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex11);
+
+ iv_bsscan_ex12.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX12_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex12);
+
+ iv_bsscan_ex13.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX13_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex13);
+
+ iv_bsscan_ex14.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX14_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex14);
+
+// iv_bsscan_ex15.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX15_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex15);
+ } //end SIM_BROADSIDE_MODE has scan
+ } //end was able to read SIM_BROADSIDE_MODE
+
+#endif // SIMPLE_VBU_HACKS_ONLY
+#endif // VBU_HACKS
+}
+
+
+PoreVe::~PoreVe()
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/usr/pore/poreve/porevesrc/poreve.H b/src/usr/pore/poreve/porevesrc/poreve.H
new file mode 100644
index 000000000..4c2281940
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/poreve.H
@@ -0,0 +1,535 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/poreve.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_POREVE_H
+#define __VSBE_POREVE_H
+
+// $Id: poreve.H,v 1.18 2011/12/16 21:47:59 bcbrock Exp $
+
+/// \file poreve.H
+/// \brief The PORE Virtual Environment
+///
+/// The PORE Virtual Environment is a container class that contains a Pore
+/// model along with the Bus and Memory models that comprise a Pore system.
+/// These system models offer very little in the way of interfaces other than
+/// a way to reset() the simulation and a run() method to clock the
+/// simulation. Instead, most operations on the PORE (including setting up the
+/// initial state) are performed directly on the Pore model data member \a
+/// iv_pore itself. Similarly, memories are configured by map() operations
+/// directly on the memory objects.
+///
+/// The system components are created and interconnected in a simple two-step
+/// process:
+///
+/// - When objects are created any truly static configuration parameters are
+/// passed as arguments of the constructor.
+///
+/// - After all components are constructed, simple code sequences stitch
+/// together the components using a configure() method provided by each class
+/// of component.
+///
+/// This two-step sequence eliminates the problem of loops that would arise if
+/// we tried to configure the network in the constructor, and is very similar
+/// to the way that Simics models are configured.
+///
+/// The final PoreVe model is constructed in two steps. We first define a
+/// PoreVeBase model. This is a stripped down environment that only contains
+/// a PORE engine and the exact components required for the HBI application of
+/// PORE-SBE. The Vsbe facade class is later provided as the interface to
+/// PoreVeBase.
+///
+/// The second step of the derivation is to add all of the remaining
+/// components to create the full PoreVe model for use in VBU and lab
+/// applications. The derivation is done this way to make the PoreVeBase as
+/// small as possible in terms of both code and data size. Ideally however
+/// the differences (in code and data size) will turn out to be small enough
+/// such that we can drop the separate models and simply always create the
+/// full PoreVe model, using the Vsbe facade as the high-level interface for
+/// HBI. Frankly, the system design would probably be more robust if we had
+/// only one model - we may go ahead and merge the models anyway.
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#include "fapi.H"
+
+#include "fasti2c.H"
+#include "poremodel.H"
+#include "pore.H"
+
+#ifdef VBU_HACKS
+#include "pib2cfam.H"
+#include "bsscan.H"
+#include "sbevital.H"
+#endif // VBU_HACKS
+
+#ifndef POREVE_STATISTICS
+#define POREVE_STATISTICS 0
+#endif
+
+namespace vsbe {
+
+ class PoreVeBase;
+ class PoreVe;
+
+ /// \defgroup poreve_config Parameters of PoreVe Configurations
+ ///
+ /// These parameters are required for configuring the PoreVe system model.
+ ///
+ /// \bug Many of these parameters are fake for now and will be system
+ /// dependent.
+ ///
+ /// @{
+
+ //////////////////////////////////////////////////////////////////////
+ // PORE
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of PORE-SBE control registers
+ const uint32_t PORE_SBE_PIB_BASE = 0x000e0000;
+
+ /// The PIB base address of PORE-SLW control registers
+ const uint32_t PORE_SLW_PIB_BASE = 0x00068000;
+
+ /// The size of the PORE control register space.
+ const uint64_t PORE_PIB_SIZE = ((uint64_t)SIZEOF_VISIBLE_PORE_STATE) / 8;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // OTPROM
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the OTPROM memory controller
+ const uint32_t OTPROM_PIB_BASE = 0x00010000;
+
+ /// The number of PIB \e registers defined by the OTPROM memory controller
+ ///
+ /// PIB memories are 8-byte \e word addressed. The maximum amount of
+ /// memory accessible through the controller is (OTPROM_PIB_SIZE * 8)
+ /// bytes.
+ const uint64_t OTPROM_PIB_SIZE = 0x200;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PIBMEM
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the PIBMEM memory controller
+ const uint32_t PIBMEM_PIB_BASE = 0x00080000;
+
+ /// The number of PIB \e registers defined by the PIBMEM memory controller
+ ///
+ /// PIB memories are 8-byte \e word addressed. The maximum amount of
+ /// memory accessible through the controller is (PIBMEM_PIB_SIZE * 8)
+ /// bytes (3KB).
+ const uint64_t PIBMEM_PIB_SIZE = 0x180;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PNOR
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the PNOR (LPCM) memory controller
+ const uint32_t PNOR_PIB_BASE = 0x000b0000;
+
+ /// The number of registers defined by the PNOR memory controller
+ const size_t PNOR_PIB_SIZE = LPCM_REGISTERS;
+
+ /// The number of bytes in a PNOR address (actually a parameter of the
+ /// memory attached to the controller)
+ const size_t PNOR_ADDRESS_BYTES = 4;
+
+ /// The PNOR I2C Port Number
+ const unsigned PNOR_I2C_PORT = 0;
+
+ /// The PNOR I2C Device Address
+ const unsigned PNOR_I2C_DEVICE_ADDRESS = 0;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // SEEPROM
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the SEEPROM memory controller
+ const uint32_t SEEPROM_PIB_BASE = 0x000c0000;
+
+ /// The number of registers defined by the SEEPROM memory controller
+ const uint64_t SEEPROM_PIB_SIZE = FASTI2C_REGISTERS;
+
+ /// The number of bytes in an SEEPROM address
+ const uint64_t SEEPROM_ADDRESS_BYTES = 2;
+
+ /// The SEEPROM I2C Port Number
+ const unsigned SEEPROM_I2C_PORT = 0;
+
+ /// The SEEPROM I2C Device Address
+ ///
+ /// \bug This value (0) is bogus, need the real value from the system
+ /// design.
+ const unsigned SEEPROM_I2C_DEVICE_ADDRESS = 0;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PIB Default Catch-All Model
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the default PIB slave
+ const uint32_t PIB_DEFAULT_PIB_BASE = 0x0;
+
+ /// The number of registers defined by the default PIB slave
+ const uint64_t PIB_DEFAULT_PIB_SIZE = 0x100000000ull;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // OCI-Attached Components
+ //////////////////////////////////////////////////////////////////////
+
+ /// The OCI base address of the OCI PBA->Mainstore bridge
+ ///
+ /// We go ahead and map the entire 1GB. During configuration the actual
+ /// memory area in use will be defined by Memory::map() calls.
+ const uint32_t MAINSTORE_OCI_BASE = 0x00000000;
+
+ /// The OCI PBA->Mainstore bridge maps 1GB of the address space
+ const uint64_t MAINSTORE_OCI_SIZE = 0x40000000;
+
+
+ /// The OCI base address of the SRAM
+ const uint32_t SRAM_OCI_BASE = 0xfff80000;
+
+ /// The OCI SRAM is 512KB
+ const uint64_t SRAM_OCI_SIZE = 0x00080000;
+
+ /// The OCI address of the PMC_PORE_REQ_STAT_REG Register
+ ///
+ /// This is the only OCI control register that PORE-SLW should access, so
+ /// its size is limited to 8 bytes.
+ const uint32_t PMC_OCI_BASE = 0x40010480;
+
+ /// PORE-SLW is only allowed to access a specific 8 bytes of the OCI
+ /// control register space.
+ const uint64_t PMC_OCI_SIZE = 8;
+
+ /// @}
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVeBase
+////////////////////////////////////////////////////////////////////////////
+
+/// The base class (HBI-only components) of PoreVe.
+///
+/// This model contains only those components required for HBI applications
+/// of the PORE virtual environment. Currently this is only
+///
+/// - A Pore
+/// - A PIB bus
+/// - A PNOR memory model
+/// - A PibSlave to catch any getscom()/putscom() destined for the PIB
+
+class
+vsbe::PoreVeBase {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Construct the PoreVeBase
+ ///
+ /// \param[in] i_id The PORE IBUF_ID (engine type) of the Pore component.
+ /// This will be PORE_SBE for host boot/SBE applications, and PORE_SLW for
+ /// testing Sleep/Winkle applications.
+ ///
+ /// \param[in] i_masterTarget The fapi::Target associated with the master
+ /// chip in an HBI master/slave configuration. This target is also
+ /// installed into \a iv_slaveTarget by the constructor.
+ PoreVeBase(const PoreIbufId i_id, const fapi::Target i_masterTarget);
+
+ virtual ~PoreVeBase();
+
+
+ //////////////////// Simulation Interface /////////////////////////
+
+ /// Reset the simulation to target a new slave
+ ///
+ /// \param[in] i_slaveTarget The slave target of the new slave
+ ///
+ /// The reset() method is provided to cleanly reset the simulation for
+ /// simulation with a new slave target. Once reset, the application is
+ /// responsible for setting up the register state of the Pore and invoking
+ /// the run() method to begin simulation.
+ virtual void
+ reset(fapi::Target i_slaveTarget);
+
+
+ /// See PoreModel::run()
+ ///
+ /// This API is provided as a convenience. Currently the only model in
+ /// the system that is 'clocked' is the PoreModel.
+ virtual int
+ run(const uint64_t i_instructions, uint64_t& o_ran);
+
+
+ /// Run a 'getscom' on the virtual PIB
+ ///
+ /// \param[in] i_address A 32-bit SCOM address
+ ///
+ /// \param[out] o_data The 64-bit SCOM data returned from the read
+ ///
+ /// \param[out] o_rc The 3-bit PIB/PCB error code returned from the PIB
+ /// transaction, see the PcbReturnCode enum in transaction.H.
+ ///
+ /// This method allows a caller to run a read transaction on the virtual
+ /// PIB bus, observing the same PIB configuration seen by the virtual PORE
+ /// engine. Accesses of PIB/PCB addresses that are modeled in the virtual
+ /// model return modeled results, and accesses of non-modeled addresses
+ /// are converted into FAPI calls.
+ ///
+ /// \returns A return value of 0 indicates success of the method call, but
+ /// does not guarantee that the PIB transaction succeeded. It will also be
+ /// necessary to also observe that PIB/PCB return code \a o_rc was
+ /// returned as 0. A non-0 return code from the method indicates a
+ /// modeling error.
+ virtual ModelError
+ getscom(const uint32_t i_address, uint64_t& o_data, int& o_rc);
+
+
+ /// Run a 'putscom' on the virtual PIB
+ ///
+ /// \param[in] i_address A 32-bit SCOM address
+ ///
+ /// \param[out] i_data The 64-bit SCOM write data
+ ///
+ /// \param[out] o_rc The 3-bit PIB/PCB error code returned from the PIB
+ /// transaction, see the PcbReturnCode enum in transaction.H.
+ ///
+ /// This method allows a caller to run a write transaction on the virtual
+ /// PIB bus, observing the same PIB configuration seen by the virtual PORE
+ /// engine. Accesses of PIB/PCB addresses that are modeled in the virtual
+ /// model update modeled registers, and accesses of non-modeled addresses
+ /// are converted into FAPI calls.
+ ///
+ /// \returns A return value of 0 indicates success of the method call, but
+ /// does not guarantee that the PIB transaction succeeded. It will also be
+ /// necessary to also observe that PIB/PCB return code \a o_rc was
+ /// returned as 0. A non-0 return code from the method indicates a
+ /// modeling error.
+ virtual ModelError
+ putscom(const uint32_t i_address, const uint64_t i_data, int& o_rc);
+
+
+ //////////////////// Public Implementation ////////////////////////////
+
+ /// The Pore model
+ Pore iv_pore;
+
+ /// The PIB bus model
+ Bus iv_pib;
+
+ /// The PNOR controller model
+ FastI2cController iv_pnorController;
+
+ /// The PNOR memory model
+ I2cMemory iv_pnorMemory;
+
+ /// The secondary PIB slave.
+ ///
+ /// This slave routes all operations that do not hit in a PIB-attached
+ /// memory model to hardware via FAPI getscom/putcom.
+ PibSlave iv_pibDefault;
+
+
+ //////////////////// Protected Implementation ///////////////////////////
+
+protected:
+
+ /// The PORE IBUF ID of the PORE engine
+ PoreIbufId iv_id;
+
+ /// The master fapi::Target
+ ///
+ /// HBI applications differentiate between the \e master chip that is
+ /// brought up first, and the \e slave chips that the master then
+ /// initializes. The master target is considered a constant and is
+ /// provided in the constructor. The master target is always associated
+ /// with the PNOR; the other memory components are associated with the
+ /// slave target. A pointer to this data member is provided to the PNOR
+ /// model during configuration.
+ fapi::Target iv_masterTarget;
+
+
+ /// The slave fapi::Target
+ ///
+ /// HBI applications differentiate between the \e master chip that is
+ /// brought up first, and the \e slave chips that the master then
+ /// initializes. The slave target is considered a variable and the
+ /// reset() method is provided to safely reset the system and modify the
+ /// slave target after construction. Note that the slave target is
+ /// initialized to be identical to the master target by the constructor.
+ /// A pointer to this data member is provided to all slaves other that the
+ /// PNOR model during configuration.
+ fapi::Target iv_slaveTarget;
+
+
+ /// The common ecmdDataBufferBase for all FAPI APIs
+ ///
+ /// To save memory space we only allocate one FAPI data buffer that is
+ /// used by all FAPI APIs that require a ecmdDataBuffer. A pointer to
+ /// this data member is provided to all slaves during configuration.
+ ecmdDataBufferBase iv_dataBuffer;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreVeBase(const PoreVeBase& i_rhs);
+ PoreVeBase& operator=(const PoreVeBase& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVe
+////////////////////////////////////////////////////////////////////////////
+
+
+/// The full PoreVe configuration
+///
+/// This derivation from PoreVeBase adds the remaining PIB models not required
+/// by the HBI application, as well as all of the OCI models. Note that
+/// unlike the PIB there is no catch-all for OCI accesses; An access must hit
+/// within one of the defined memory maps, otherwise the access is considered
+/// an error.
+
+class
+vsbe::PoreVe : public vsbe::PoreVeBase {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Construct the PoreVe
+ ///
+ /// \param[in] i_id The PORE IBUF_ID (engine type) of the Pore component.
+ /// This will be PORE_SBE for host boot/SBE applications, and PORE_SLW for
+ /// testing Sleep/Winkle applications.
+ ///
+ /// \param[in] i_masterTarget The fapi::Target associated with the master
+ /// chip in an HBI master/slave configuration. This target is also
+ /// installed into \a iv_slaveTarget by the constructor.
+ PoreVe(const PoreIbufId i_id, const fapi::Target i_masterTarget);
+
+ virtual ~PoreVe();
+
+ /// Create a PoreVe (subclass) by static link-time selection
+ ///
+ /// \param[in] i_id The PORE IBUF_ID (engine type) of the Pore component.
+ /// This will be PORE_SBE for host boot/SBE applications, and PORE_SLW for
+ /// testing Sleep/Winkle applications.
+ ///
+ /// \param[in] i_masterTarget The fapi::Target associated with the master
+ /// chip in an HBI master/slave configuration. This target is also
+ /// installed into \a iv_slaveTarget by the constructor.
+ ///
+ /// \param[in] i_arg A private argument for the created model. In the
+ /// case of a debugged model this is a character string naming a script to
+ /// be run when the debugger starts. The PoreVe ignores this argument.
+ ///
+ /// The static create() method is provided to enable link-time selection
+ /// of a subclass of PoreVe, in particular to allow a common FAPI PoreVe
+ /// procedure to create either a 'normal' or 'debug' version of PoreVe.
+ static PoreVe* create(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget,
+ const void* i_arg);
+
+ //////////////////// Public Implementation ////////////////////////////
+
+ /// The OTPROM controller model
+ PibMemory iv_otprom;
+
+ /// The OTPROM memory model
+ Memory iv_otpromMemory;
+
+ /// The PIBMEM controller model - No advanced functions implemented for now
+ PibMemory iv_pibmem;
+
+ /// The PIPMEM memory model
+ Memory iv_pibmemMemory;
+
+ /// The SEEPROM controller model
+ FastI2cController iv_seepromController;
+
+ /// The SEEPROM memory model
+ I2cMemory iv_seepromMemory;
+
+ /// The OCI bus model
+ Bus iv_oci;
+
+ /// The Mainstore memory controller model
+ OciMemory iv_main;
+
+ /// The Mainstore memory model
+ Memory iv_mainMemory;
+
+ /// The SRAM controller model
+ OciMemory iv_sram;
+
+ /// The SRAM memory model
+ Memory iv_sramMemory;
+
+#ifdef PM_HACKS
+ OciSlaveWritable iv_pmc;
+#endif // PM_HACKS
+
+#ifdef VBU_HACKS
+ /// The temporary Pib2Cfam PIB Slave
+ Pib2Cfam iv_pib2Cfam;
+
+ /// The temporary sbeVital PIB Slave
+ SbeVital iv_sbeVital;
+
+ /// The Broadside Scan components for each EX
+ // Bsscan iv_bsscan_ex00;
+ Bsscan iv_bsscan_ex01;
+ Bsscan iv_bsscan_ex02;
+ Bsscan iv_bsscan_ex03;
+ Bsscan iv_bsscan_ex04;
+ Bsscan iv_bsscan_ex05;
+ Bsscan iv_bsscan_ex06;
+ // Bsscan iv_bsscan_ex07;
+ // Bsscan iv_bsscan_ex08;
+ Bsscan iv_bsscan_ex09;
+ Bsscan iv_bsscan_ex10;
+ Bsscan iv_bsscan_ex11;
+ Bsscan iv_bsscan_ex12;
+ Bsscan iv_bsscan_ex13;
+ Bsscan iv_bsscan_ex14;
+ // Bsscan iv_bsscan_ex15;
+#endif
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreVe(const PoreVe& i_rhs);
+ PoreVe& operator=(const PoreVe& i_rhs);
+};
+
+#endif // __VSBE_POREVE_H
diff --git a/src/usr/pore/poreve/porevesrc/sbevital.C b/src/usr/pore/poreve/porevesrc/sbevital.C
new file mode 100644
index 000000000..1a80337db
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/sbevital.C
@@ -0,0 +1,82 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/sbevital.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: sbevital.C,v 1.1 2011/09/19 00:25:32 jeshua Exp $
+
+/// \file sbevital.C
+/// \brief A temporary hack to create the SBE vital reg before HW has it
+///
+#ifdef VBU_HACKS
+
+#include "sbevital.H"
+#include "fapiSharedUtils.H"
+#include "ecmdUtils.H"
+using namespace vsbe;
+
+
+////////////////////////////// Creators //////////////////////////////
+
+SbeVital::SbeVital()
+{
+ iv_data = 0;
+}
+
+
+SbeVital::~SbeVital()
+{
+}
+
+
+//////////////////////////// Manipulators ////////////////////////////
+
+fapi::ReturnCode
+SbeVital::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc=0;
+ ModelError me;
+
+ FAPI_INF("In sbeVital\n");
+
+ //On a ring write, put the data into the ring
+ if( io_transaction.iv_mode == ACCESS_MODE_WRITE)
+ {
+ iv_data = io_transaction.iv_data >> 32;
+ me = ME_SUCCESS;
+ }
+ else if( io_transaction.iv_mode == ACCESS_MODE_READ )
+ {
+ io_transaction.iv_data = ((uint64_t)(iv_data)) << 32;
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+
+ io_transaction.busError(me);
+ return rc;
+}
+#endif
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/poreve/porevesrc/sbevital.H b/src/usr/pore/poreve/porevesrc/sbevital.H
new file mode 100644
index 000000000..66aa83f96
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/sbevital.H
@@ -0,0 +1,85 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/sbevital.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// 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 __VSBE_SBEVITAL_H
+#define __VSBE_SBEVITAL_H
+
+// $Id: sbevital.H,v 1.1 2011/09/19 00:25:32 jeshua Exp $
+
+/// \file sbevital.H
+/// \brief A hack to intercept scan operations and make them broadside
+
+#include "bus.H"
+
+namespace vsbe {
+
+ class SbeVital;
+
+ /// PIB base address of PIB range mapped by SbeVital
+ const uint32_t SBEVITAL_PIB_BASE = 0x0005001C;
+
+ /// Number of PIB addresses mapped by SbeVital
+ const int SBEVITAL_PIB_SIZE = 1;
+
+}
+
+
+/// Map PIB accesses to CFAM accesses
+
+class
+vsbe::SbeVital : public PibSlave {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ SbeVital();
+
+ virtual ~SbeVital();
+
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// SbeVital operation
+ ///
+ /// \param[in,out] io_transaction A PIB transaction object
+ ///
+ /// This object converts PIB transactions in a certain range in the
+ /// virtual environment to broadside getRing and putRing operations,
+ /// returning the FAPI return code from the translated calls.
+ ///
+ /// \retval rc The fapi::ReturnCode returned by the underlying
+ /// getRing() or putRing() call.
+ fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ SbeVital(const SbeVital& rhs);
+ SbeVital& operator=(const SbeVital& rhs);
+
+ uint32_t iv_data;
+};
+
+#endif // __VSBE_SBEVITAL_H
OpenPOWER on IntegriCloud