diff options
author | Matt Ploetz <maploetz@us.ibm.com> | 2016-06-02 13:24:24 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-07-24 19:22:13 -0400 |
commit | c91b4070b8ddfa92749d94bd044c6b078305a2cd (patch) | |
tree | 3990677b77d56134e901049a69a1ae35af2c129a | |
parent | 70204fd1a50184f3817ea654af47ef74b90e9752 (diff) | |
download | talos-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>
-rw-r--r-- | src/include/usr/scom/scomreasoncodes.H | 4 | ||||
-rw-r--r-- | src/usr/scom/runtime/test/testscom_rt.H | 207 | ||||
-rw-r--r-- | src/usr/scom/scom.C | 234 | ||||
-rw-r--r-- | src/usr/scom/scom.H | 56 | ||||
-rw-r--r-- | src/usr/scom/test/scomtest.H | 208 |
5 files changed, 677 insertions, 32 deletions
diff --git a/src/include/usr/scom/scomreasoncodes.H b/src/include/usr/scom/scomreasoncodes.H index 289f34f57..dfa183b29 100644 --- a/src/include/usr/scom/scomreasoncodes.H +++ b/src/include/usr/scom/scomreasoncodes.H @@ -37,6 +37,7 @@ namespace SCOM SCOM_FIND_PARENT_TARGET = 0x03, SCOM_CHECK_INDIRECT_AND_DO_SCOM = 0x04, SCOM_TRANSLATE_P9 = 0x05, + SCOM_DO_FORM_1_INDIRECT_SCOM = 0x06, }; enum scomReasonCode @@ -54,6 +55,9 @@ namespace SCOM SCOM_TRANS_CANT_FIND_PARENT = SCOM_COMP_ID | 0x0B, SCOM_TARGET_ADDR_MISMATCH = SCOM_COMP_ID | 0x0C, SCOM_ISCHIPUNITSCOM_INVALID = SCOM_COMP_ID | 0x0D, + SCOM_INVALID_FORM = SCOM_COMP_ID | 0x0E, + SCOM_FORM_1_INVALID_DATA = SCOM_COMP_ID | 0x0F, + SCOM_FORM_1_READ_REQUEST = SCOM_COMP_ID | 0x10, }; enum UserDetailsTypes 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" ); |