summaryrefslogtreecommitdiffstats
path: root/src/usr/scom
diff options
context:
space:
mode:
authorMatt Ploetz <maploetz@us.ibm.com>2016-06-02 13:24:24 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2016-07-24 19:22:13 -0400
commitc91b4070b8ddfa92749d94bd044c6b078305a2cd (patch)
tree3990677b77d56134e901049a69a1ae35af2c129a /src/usr/scom
parent70204fd1a50184f3817ea654af47ef74b90e9752 (diff)
downloadtalos-hostboot-c91b4070b8ddfa92749d94bd044c6b078305a2cd.tar.gz
talos-hostboot-c91b4070b8ddfa92749d94bd044c6b078305a2cd.zip
Add support for Indirect Scom Form 1
Change-Id: Ie99a7ec8fe78a77db22a565a39e036679f8a01f9 RTC: 151098 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/25317 Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/scom')
-rw-r--r--src/usr/scom/runtime/test/testscom_rt.H207
-rw-r--r--src/usr/scom/scom.C234
-rw-r--r--src/usr/scom/scom.H56
-rw-r--r--src/usr/scom/test/scomtest.H208
4 files changed, 673 insertions, 32 deletions
diff --git a/src/usr/scom/runtime/test/testscom_rt.H b/src/usr/scom/runtime/test/testscom_rt.H
index b51d93540..a098cb004 100644
--- a/src/usr/scom/runtime/test/testscom_rt.H
+++ b/src/usr/scom/runtime/test/testscom_rt.H
@@ -846,7 +846,7 @@ public:
TS_FAIL( "ScomTest::test_Translate_SCOM_MBA_MBS> ERROR : Unexpected error log from write1" );
fails++;
errlCommit(l_err,SCOM_COMP_ID);
- }
+ }
delete l_err;
}
@@ -859,7 +859,6 @@ public:
for( uint64_t x = 0; x < NUM_ADDRS-2; x++ )
{
memset(read_data, 0, sizeof read_data);
-
//only run if the target exists
if(test_data[x].target == NULL)
{
@@ -881,7 +880,6 @@ public:
op_size,
DEVICE_SCOM_ADDRESS(test_data[x].addr) );
-
if( l_err )
{
TRACFCOMP(g_trac_scom, "ScomTest::test_TranslateScom_MBA_MBS> [%d] Read: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
@@ -916,8 +914,211 @@ public:
//@todo - write error path testcase for FSI scom using bad address
+ /**
+ * @brief multi chip SCOM test
+ *
+ */
+ void test_Form1IBSCOMreadWrite_proc(void)
+ {
+
+ TRACFCOMP( g_trac_scom, "ScomTest::test_Form1IBSCOMreadWrite_proc> Start" );
+
+/*
+ * TODO RTC 158024 - Enable form 1 test case
+
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ errlHndl_t l_err = NULL;
+
+ //@VBU workaround - Disable Indirect SCOM test case o
+ //Test case read/writes to valid addresses and is
+ //potentially destructive on VBU
+ if (TARGETING::is_vpo())
+ {
+ return;
+ }
+
+ // Setup some targets to use
+ enum {
+ myPROC0,
+ NUM_TARGETS
+ };
+ TARGETING::Target* scom_targets[NUM_TARGETS];
+ for( uint64_t x = 0; x < NUM_TARGETS; x++ )
+ {
+ scom_targets[x] = NULL;
+ }
+
+ // Target Proc 9 - the FSI wrap-back connection in simics
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,0);
+
+ scom_targets[myPROC0] = TARGETING::targetService().toTarget(epath);
+ for( uint64_t x = 0; x < NUM_TARGETS; x++ )
+ {
+ //only run if the target exists
+ if(scom_targets[x] == NULL)
+ {
+ TRACDCOMP( g_trac_scom, "ScomTestForm1 - TARGET = NULL - 1 x = %d", x);
+ continue;
+ }
+ else if ((scom_targets[x]->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useXscom == 0) &&
+ (scom_targets[x]->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useFsiScom == 0))
+ {
+ // If both FSI and XSCOM are not enabled.. then ignore..
+ TRACDCOMP(g_trac_scom, "INDIRECT SCOMForm1>> SKIPPING ");
+ scom_targets[x] = NULL; //remove from our list
+ }
+ else if (scom_targets[x]->getAttr<TARGETING::ATTR_HWAS_STATE>().functional != true)
+ {
+ TRACDCOMP( g_trac_scom, "ScomTest::test_FSISCOMreadWriteForm1 > Target %d is not functional", x );
+ scom_targets[x] = NULL; //remove from our list
+ }
+ }
+
+ // scratch data to use
+
+ struct {
+ TARGETING::Target* target;
+ uint64_t addr;
+ uint64_t data;
+ bool isFail;
+ } test_data[] = {
+ { scom_targets[myPROC0], 0x900003210D010BEE, 0x0004432112344321, false}, // Form 1
+ { scom_targets[myPROC0], 0x9000012307011BEE, 0x000443211234ABAB, false }, // Form 1
+ { scom_targets[myPROC0], 0x9000000007011BEE, 0x123443211234ABAB, true }, // Form 1
+ { scom_targets[myPROC0], 0x9FEEDB0B0DEADBEE, 0x000443211234ABAB, true }, // Form 1
+ };
+ const uint64_t NUM_ADDRS = sizeof(test_data)/sizeof(test_data[0]);
+
+ size_t op_size = sizeof(uint32_t);
+
+ // write all the test registers
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(test_data[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+ total++;
+ l_err = deviceWrite( test_data[x].target,
+ &(test_data[x].data),
+ op_size,
+ DEVICE_SCOM_ADDRESS(test_data[x].addr) );
+
+ if(!test_data[x].isFail && l_err )
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomForm1_proc> [%d] Write: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomForm1_proc> ERROR : Unexpected error log from device write: addr=0x%X, RC=%X ", test_data[x].addr, l_err->reasonCode() );
+ fails++;
+ errlCommit(l_err,SCOM_COMP_ID);
+ l_err = NULL;
+ }
+ else if(test_data[x].isFail && !l_err )
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomForm1_proc> [%d] Write: Expected an Error from device write: addr=0x%X", x, test_data[x].addr );
+ TS_FAIL( "ScomTest::test_IndirectScomForm1_proc> ERROR : Expected an error log from device write and did not get one : addr=0x%X", test_data[x].addr );
+ fails++;
+ }
+ else if(l_err)
+ {
+ //delete expected errors
+ delete l_err;
+ }
+ }
+ // Now lets make sure the data is correct
+ // Form 1 doesn't support read. Simics action is set up to write to
+ // a regigster whcih will we scom
+ // allocate space for read data
+ struct {
+ TARGETING::Target* target;
+ uint64_t addr;
+ } read_addresses[] = {
+ { scom_targets[myPROC0], 0x0D010123 }, // Form 1
+ { scom_targets[myPROC0], 0x07011123 }, // Form 1
+ };
+ const uint64_t READ_ADDRS = sizeof(read_addresses)/sizeof(read_addresses[0]);
+ uint64_t read_form1data[READ_ADDRS];
+
+ memset(read_form1data, 0, sizeof read_form1data);
+
+ // read all the read registers
+ for( uint64_t x = 0; x < READ_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(read_addresses[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceRead( read_addresses[x].target,
+ &(read_form1data[x]),
+ op_size,
+ DEVICE_SCOM_ADDRESS(read_addresses[x].addr) );
+
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> [%d] read written data: Unxpected Error from device : addr=0x%X, RC=%X", x, read_addresses[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomreadWriteForm1_proc> ERROR : Unxpected Error on reading written data : addr=0x%X, RC=%X", read_addresses[x].addr, l_err->reasonCode() );
+ fails++;
+ }
+ if((read_form1data[x] & 0x000000000000FFFF) !=
+ (test_data[x].data & 0x000000000000FFFF))
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> [%d] Read: Data miss-match : addr=0x%X, read_form1data=0x%llx, write_data=0x%llx", x, read_addresses[x].addr, read_form1data[x], test_data[x].data);
+ TS_FAIL( "ScomTest::test_IndirectScomreadWriteForm1_proc> ERROR : Data miss-match between read and expected data" );
+ fails++;
+ }
+ }
+
+ // allocate space for read data
+ uint64_t read_data[NUM_ADDRS];
+
+ memset(read_data, 0, sizeof read_data);
+
+ // read all the test registers
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(test_data[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceRead( test_data[x].target,
+ &(read_data[x]),
+ op_size,
+ DEVICE_SCOM_ADDRESS(test_data[x].addr) );
+
+ // Form1 doesn't support read so if we don't get an error back, that's bad
+ if(!l_err)
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> [%d] Read: Expected Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomreadWriteForm1_proc> ERROR : Expected Error on READ : addr=0x%X, RC=%X", test_data[x].addr, l_err->reasonCode() );
+ fails++;
+ }
+ // else, if we are form1 and DO get an error back on read, that's expected.
+ else
+ {
+ //delete expected errors
+ delete l_err;
+ }
+ }
+*/
+ }
/**
diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C
index 152b8b1ee..b0ac02519 100644
--- a/src/usr/scom/scom.C
+++ b/src/usr/scom/scom.C
@@ -180,11 +180,6 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
errlHndl_t l_err = NULL;
- enum { MAX_INDSCOM_TIMEOUT_NS = 100000 }; //=.1ms
-
- mutex_t* l_mutex = NULL;
- bool need_unlock = false;
-
do {
// In HOSTBOOT_RUNTIME we always defer indirect scoms to Sapphire.
#ifndef __HOSTBOOT_RUNTIME
@@ -202,15 +197,115 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
break;
#ifndef __HOSTBOOT_RUNTIME
}
-
- // We are performing an indirect scom.
- uint64_t elapsed_indScom_time_ns = 0;
uint64_t l_io_buffer = 0;
uint64_t temp_scomAddr = 0;
+ uint8_t form = 0;
memcpy(&l_io_buffer, io_buffer, 8);
memcpy(&temp_scomAddr, &i_addr, 8);
+ // Bits 0:3 of the address hold the indirect and form bits
+ // We shift out 60 bits to read the form bit here
+ form = (i_addr >> 60) & 1;
+
+ // If the form is 0, we are using the "old" indirect scom method
+ if (form == 0)
+ {
+ // setupForm0ScomRegs sets up the registers for form0 scom op
+ l_err = doForm0IndirectScom(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_accessType,
+ i_addr);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_scom,
+ "checkIndirectAndDoScom: Error from doForm0IndirectScom");
+ break;
+ }
+ }
+
+ // If form is equal to 1, we are using new FBC method
+ else if (form == 1)
+ {
+ l_err = doForm1IndirectScom(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ i_accessType,
+ i_addr);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_scom,
+ "checkIndirectAndDoScom: Error from doForm1IndirectScom");
+ break;
+
+ }
+ }
+
+ // Unsupported form, break out
+ else
+ {
+ TRACFCOMP(g_trac_scom, "Unsupported indirect scom form %d", form);
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_CHECK_INDIRECT_AND_DO_SCOM
+ * @reasoncode SCOM::SCOM_INVALID_FORM
+ * @userdata1 Address
+ * @userdata2 HUID of Target
+ * @devdesc Unsupported indirect scom form
+ * @custdesc A problem occurred during the IPL of the system.
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM_CHECK_INDIRECT_AND_DO_SCOM,
+ SCOM_INVALID_FORM,
+ i_addr,
+ get_huid(i_target),
+ true /*Add HB Software Callout*/);
+
+ break;
+ }
+
+#endif // __HOSTBOOT_RUNTIME
+ } while(0);
+
+ if(i_opMode & fapi2::IGNORE_HW_ERROR)
+ {
+ TRACFCOMP(g_trac_scom, "IGNORE_HW_ERROR opmode detected for scom, any errors are being deleted");
+ delete l_err;
+ }
+
+ return l_err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+errlHndl_t doForm0IndirectScom(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr)
+{
+ errlHndl_t l_err = NULL;
+
+ enum { MAX_INDSCOM_TIMEOUT_NS = 100000 }; //=.1ms
+
+ mutex_t* l_mutex = NULL;
+ bool need_unlock = false;
+ uint64_t elapsed_indScom_time_ns = 0;
+ uint64_t l_io_buffer = 0;
+ uint64_t temp_scomAddr = 0;
+
+ memcpy(&l_io_buffer, io_buffer, 8);
+ memcpy(&temp_scomAddr, &i_addr, 8);
+
+ do {
// Get the 20bit indirect scom address
temp_scomAddr = temp_scomAddr & 0x001FFFFF00000000;
@@ -227,11 +322,9 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
// bit 48-63 - local addr
i_addr = i_addr & 0x000000007FFFFFFF;
-
// If we are doing a read. We need to do a write first..
if(i_opType == DeviceFW::READ)
{
-
// use the chip-specific mutex attribute
l_mutex =
i_target->getHbMutexAttr<TARGETING::ATTR_SCOM_IND_MUTEX>();
@@ -252,9 +345,9 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
i_addr);
if (l_err != NULL)
- {
+ {
break;
- }
+ }
// Need to check loop on read until we see done, error,
// or we timeout
@@ -336,11 +429,11 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
}
else
{
- //Add the callouts for the specific PCB/PIB error
- PIB::addFruCallouts( i_target,
- scomout.piberr,
- i_addr,
- l_err );
+ //Add the callouts for the specific PCB/PIB error
+ PIB::addFruCallouts( i_target,
+ scomout.piberr,
+ i_addr,
+ l_err );
}
//Add this target to the FFDC
@@ -505,15 +598,8 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
.addToLog(l_err);
}
} // end of write
-#endif // __HOSTBOOT_RUNTIME
} while(0);
- if(i_opMode & fapi2::IGNORE_HW_ERROR)
- {
- TRACFCOMP(g_trac_scom, "IGNORE_HW_ERROR opmode detected for scom, any errors are being deleted");
- delete l_err;
- }
-
if( need_unlock )
{
mutex_unlock(l_mutex);
@@ -521,7 +607,107 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
return l_err;
}
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+errlHndl_t doForm1IndirectScom(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t l_io_buffer = 0;
+ uint64_t temp_scomAddr = 0;
+ uint64_t l_data_from_addr = 0;
+
+ memcpy(&l_io_buffer, io_buffer, 8);
+ memcpy(&temp_scomAddr, &i_addr, 8);
+
+ do {
+ if(i_opType == DeviceFW::READ)
+ {
+ TRACFCOMP(g_trac_scom, "doForm1IndirectScom: Indirect Scom Form 1"
+ " does not support read op");
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_DO_FORM_1_INDIRECT_SCOM
+ * @reasoncode SCOM::SCOM_FORM_1_READ_REQUEST
+ * @userdata1 Address
+ * @userdata2 Operation Type
+ * @devdesc No read op on form 1 indirect scom.
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM_DO_FORM_1_INDIRECT_SCOM,
+ SCOM_FORM_1_READ_REQUEST,
+ i_addr,
+ i_opType,
+ true /*Add HB SW Callout*/);
+
+ break;
+ }
+ // We want to make sure the user inputted data bits 0:11 are zero
+ // so we can push addr(20:31) in it.
+ if ((l_io_buffer & 0xFFF0000000000000) != 0)
+ {
+ TRACFCOMP(g_trac_scom, "doForm1IndirectScom> User supplied "
+ "data(0:11) is not Zero: data out of range");
+
+ /*@
+ * @errortype
+ * @moduleid SCOM::SCOM_DO_FORM_1_INDIRECT_SCOM
+ * @reasoncode SCOM::SCOM_FORM_1_INVALID_DATA
+ * @userdata1 Address
+ * @userdata2 User supplied data
+ * @devdesc Bits 0:11 in user supplied data is not zero
+ */
+ l_err = new ERRORLOG::ErrlEntry(
+ ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ SCOM_DO_FORM_1_INDIRECT_SCOM,
+ SCOM_FORM_1_INVALID_DATA,
+ i_addr,
+ l_io_buffer,
+ true /*Add HB SW Callout*/);
+
+ break;
+ }
+
+ // Set up Address reg
+ // cmdreg = addr(32:63)
+ temp_scomAddr = i_addr & 0x00000000FFFFFFFF;
+
+ // Set up data regs
+ // data(0:11) = addr(20:31)
+ l_data_from_addr = i_addr & 0x00000FFF00000000;
+ // Do some bit shifting so things line up nicely
+ l_data_from_addr = (l_data_from_addr << 20 );
+
+ // data(12:63) = data(12:63)
+ // Set Data reg
+ l_io_buffer = l_io_buffer | l_data_from_addr;
+
+ // Now perform the op requested using the
+ // local io_buffer with the indirect addr imbedded.
+ l_err = doScomOp(i_opType,
+ i_target,
+ & l_io_buffer,
+ io_buflen,
+ i_accessType,
+ temp_scomAddr);
+
+ if (l_err != NULL)
+ {
+ TRACFCOMP(g_trac_scom, "doForm1IndirectScom: Write op fail");
+ break;
+ }
+
+ }while(0);
+
+ return l_err;
+}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/usr/scom/scom.H b/src/usr/scom/scom.H
index 7b6729e54..817c255ec 100644
--- a/src/usr/scom/scom.H
+++ b/src/usr/scom/scom.H
@@ -149,9 +149,8 @@ errlHndl_t doScomOp(DeviceFW::OperationType i_opType,
/**
* @brief Performs a SCom operation
- * This function performs a SCOM operation by calling doScomOP after
- * It handles whether the address is a regular or an indirect SCOM
- * address
+ * This function determines whether the scom in inband or not, and the
+ * form of the scom operation. It then calls the apporpriate doForm operation
*
* @param[in] i_opType Operation type
* @param[in] i_target SCom target
@@ -175,6 +174,57 @@ errlHndl_t checkIndirectAndDoScom(DeviceFW::OperationType i_opType,
uint64_t i_addr,
uint64_t i_opMode);
+/**
+ * @brief Performs a SCom operation
+ * This function sets up the needed scom registers based on form 0
+ * and calls doScomOp
+ *
+ * @param[in] i_opType Operation type
+ * @param[in] i_target SCom target
+ * @param[in/out] io_buffer Read: pointer to output data storage
+ * Write: pointer to data to be written
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: size of output data
+ * Write: size of data written
+ * @param[in] i_accessType Select from DeviceFW::AccessType enum
+ * @see usr/devicefw/userif.H
+ * @param[in] i_addr Scom Address Value.
+ *
+ * @return errlHndl_t
+ */
+
+errlHndl_t doForm0IndirectScom(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr);
+
+/**
+ * @brief Performs a SCom operation
+ * This function sets up the needed scom registers based on form 1
+ * and calls doScomOp
+ *
+ * @param[in] i_opType Operation type
+ * @param[in] i_target SCom target
+ * @param[in/out] io_buffer Read: pointer to output data storage
+ * Write: pointer to data to be written
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: size of output data
+ * Write: size of data written
+ * @param[in] i_accessType Select from DeviceFW::AccessType enum
+ * @see usr/devicefw/userif.H
+ * @param[in] i_addr Scom Address Value.
+ *
+ * @return errlHndl_t
+ */
+errlHndl_t doForm1IndirectScom(DeviceFW::OperationType i_opType,
+ TARGETING::Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ uint64_t i_addr);
+
}; // End namespace
diff --git a/src/usr/scom/test/scomtest.H b/src/usr/scom/test/scomtest.H
index d9d8129e1..2b5a0b3c9 100644
--- a/src/usr/scom/test/scomtest.H
+++ b/src/usr/scom/test/scomtest.H
@@ -411,7 +411,6 @@ public:
scom_targets[x] = NULL;
}
-
// Target Proc 9 - the FSI wrap-back connection in simics
TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
epath.addLast(TARGETING::TYPE_SYS,0);
@@ -458,7 +457,6 @@ public:
};
const uint64_t NUM_ADDRS = sizeof(test_data)/sizeof(test_data[0]);
-
size_t op_size = sizeof(uint32_t);
// write all the test registers
@@ -552,9 +550,215 @@ public:
}
TRACFCOMP( g_trac_scom, "ScomTest::test_IndirectScomreadWrite_proc> %d/%d fails", fails, total );
+ }
+
+ /**
+ * @brief SCOM test Indirect SCOM form 1
+ *
+ */
+ void test_IndirectScomForm1(void)
+ {
+ TRACFCOMP( g_trac_scom, "ScomTest::test_IndirectScomForm1ReadWrite> Start" );
+/*
+ * TODO RTC 158024 - Enable form 1 test case
+
+ uint64_t fails = 0;
+ uint64_t total = 0;
+ errlHndl_t l_err = NULL;
+
+ //@VBU workaround - Disable Indirect SCOM test case o
+ //Test case read/writes to valid addresses and is
+ //potentially destructive on VBU
+ if (TARGETING::is_vpo())
+ {
+ return;
+ }
+
+ // Setup some targets to use
+ enum {
+ myPROC0,
+ NUM_TARGETS
+ };
+ TARGETING::Target* scom_targets[NUM_TARGETS];
+ for( uint64_t x = 0; x < NUM_TARGETS; x++ )
+ {
+ scom_targets[x] = NULL;
+ }
+
+ // Target Proc 9 - the FSI wrap-back connection in simics
+ TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL);
+ epath.addLast(TARGETING::TYPE_SYS,0);
+ epath.addLast(TARGETING::TYPE_NODE,0);
+ epath.addLast(TARGETING::TYPE_PROC,0);
+
+ scom_targets[myPROC0] = TARGETING::targetService().toTarget(epath);
+
+ for( uint64_t x = 0; x < NUM_TARGETS; x++ )
+ {
+ //only run if the target exists
+ if(scom_targets[x] == NULL)
+ {
+ TRACDCOMP( g_trac_scom, "ScomTestForm1 - TARGET = NULL - 1 x = %d", x);
+ continue;
+ }
+ else if ((scom_targets[x]->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useXscom == 0) &&
+ (scom_targets[x]->getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useFsiScom == 0))
+ {
+ // If both FSI and XSCOM are not enabled.. then ignore..
+ TRACDCOMP(g_trac_scom, "INDIRECT SCOMForm1>> SKIPPING ");
+ scom_targets[x] = NULL; //remove from our list
+ }
+ else if (scom_targets[x]->getAttr<TARGETING::ATTR_HWAS_STATE>().functional != true)
+ {
+ TRACDCOMP( g_trac_scom, "ScomTest::test_FSISCOMreadWriteForm1 > Target %d is not functional", x );
+ scom_targets[x] = NULL; //remove from our list
+ }
+ }
+
+ // scratch data to use
+
+ struct {
+ TARGETING::Target* target;
+ uint64_t addr;
+ uint64_t data;
+ bool isFail;
+ } test_data[] = {
+ { scom_targets[myPROC0], 0x900003210D010BEE, 0x0004432112344321, false}, // Form 1
+ { scom_targets[myPROC0], 0x9000012307011BEE, 0x000443211234ABAB, false }, // Form 1
+ { scom_targets[myPROC0], 0x9000000007011BEE, 0x123443211234ABAB, true }, // Form 1
+ { scom_targets[myPROC0], 0x9FEEDB0B0DEADBEE, 0x000443211234ABAB, true }, // Form 1
+ };
+ const uint64_t NUM_ADDRS = sizeof(test_data)/sizeof(test_data[0]);
+
+ size_t op_size = sizeof(uint32_t);
+
+ // write all the test registers
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(test_data[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceWrite( test_data[x].target,
+ &(test_data[x].data),
+ op_size,
+ DEVICE_SCOM_ADDRESS(test_data[x].addr) );
+
+ if(!test_data[x].isFail && l_err )
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomForm1_proc> [%d] Write: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomForm1_proc> ERROR : Unexpected error log from device write: addr=0x%X, RC=%X ", test_data[x].addr, l_err->reasonCode() );
+ fails++;
+ errlCommit(l_err,SCOM_COMP_ID);
+ l_err = NULL;
+ }
+ else if(test_data[x].isFail && !l_err )
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomForm1_proc> [%d] Write: Expected an Error from device write: addr=0x%X", x, test_data[x].addr );
+ TS_FAIL( "ScomTest::test_IndirectScomForm1_proc> ERROR : Expected an error log from device write and did not get one : addr=0x%X", test_data[x].addr );
+ fails++;
+ }
+ else if(l_err)
+ {
+ //delete expected errors
+ delete l_err;
+ }
+ }
+ // Now lets make sure the data is correct
+ // Form 1 doesn't support read. Simics action is set up to write to
+ // a regigster whcih will we scom
+ // allocate space for read data
+ struct {
+ TARGETING::Target* target;
+ uint64_t addr;
+ } read_addresses[] = {
+ { scom_targets[myPROC0], 0x0D010123 }, // Form 1
+ { scom_targets[myPROC0], 0x07011123 }, // Form 1
+ };
+ const uint64_t READ_ADDRS = sizeof(read_addresses)/sizeof(read_addresses[0]);
+ uint64_t read_form1data[READ_ADDRS];
+
+ memset(read_form1data, 0, sizeof read_form1data);
+
+ // read all the read registers
+ for( uint64_t x = 0; x < READ_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(read_addresses[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceRead( read_addresses[x].target,
+ &(read_form1data[x]),
+ op_size,
+ DEVICE_SCOM_ADDRESS(read_addresses[x].addr) );
+
+ if(l_err)
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> [%d] read written data: Unxpected Error from device : addr=0x%X, RC=%X", x, read_addresses[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomreadWriteForm1_proc> ERROR : Unxpected Error on reading written data : addr=0x%X, RC=%X", read_addresses[x].addr, l_err->reasonCode() );
+ fails++;
+ }
+ if((read_form1data[x] & 0x000000000000FFFF) !=
+ (test_data[x].data & 0x000000000000FFFF))
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> [%d] Read: Data miss-match : addr=0x%X, read_form1data=0x%llx, write_data=0x%llx", x, read_addresses[x].addr, read_form1data[x], test_data[x].data);
+ TS_FAIL( "ScomTest::test_IndirectScomreadWriteForm1_proc> ERROR : Data miss-match between read and expected data" );
+ fails++;
+ }
+ }
+
+ // allocate space for read data
+ uint64_t read_data[NUM_ADDRS];
+
+ memset(read_data, 0, sizeof read_data);
+
+ // read all the test registers
+ for( uint64_t x = 0; x < NUM_ADDRS; x++ )
+ {
+ //only run if the target exists
+ if(test_data[x].target == NULL)
+ {
+ continue;
+ }
+
+ op_size = sizeof(uint64_t);
+
+ total++;
+ l_err = deviceRead( test_data[x].target,
+ &(read_data[x]),
+ op_size,
+ DEVICE_SCOM_ADDRESS(test_data[x].addr) );
+
+ // Form1 doesn't support read so if we don't get an error back, that's bad
+ if(!l_err)
+ {
+ TRACFCOMP(g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> [%d] Read: Expected Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() );
+ TS_FAIL( "ScomTest::test_IndirectScomreadWriteForm1_proc> ERROR : Expected Error on READ : addr=0x%X, RC=%X", test_data[x].addr, l_err->reasonCode() );
+ fails++;
+ }
+ // else, if we are form1 and DO get an error back on read, that's expected.
+ else
+ {
+ //delete expected errors
+ delete l_err;
+ }
+ }
+ TRACFCOMP( g_trac_scom, "ScomTest::test_IndirectScomreadWriteForm1_proc> %d/%d fails", fails, total );
+*/
}
+
void test_P9_ScomTranslations(void)
{
TRACFCOMP( g_trac_scom, "ScomTest::test_P9_ScomTranslations> Start" );
OpenPOWER on IntegriCloud