From 914b46ba52822c63799ebf60ebcc4df200d3371b Mon Sep 17 00:00:00 2001 From: Missy Connell Date: Mon, 30 Jan 2012 10:14:46 -0600 Subject: Scom Translate for EX, MCS, MBA/MBS Change-Id: Iff47274d72c3994923234c998894671db6e833ba Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/632 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- src/build/citest/etc/bbuild | 2 +- src/include/usr/scom/scomreasoncodes.H | 48 +++ src/usr/scom/makefile | 2 +- src/usr/scom/scom.C | 44 ++- src/usr/scom/scom.H | 36 ++- src/usr/scom/scomtrans.C | 496 +++++++++++++++++++++++++++++ src/usr/scom/scomtrans.H | 120 +++++++ src/usr/scom/test/scomtest.H | 550 ++++++++++++++++++++++++++++++++- 8 files changed, 1281 insertions(+), 17 deletions(-) create mode 100644 src/include/usr/scom/scomreasoncodes.H create mode 100644 src/usr/scom/scomtrans.C create mode 100644 src/usr/scom/scomtrans.H diff --git a/src/build/citest/etc/bbuild b/src/build/citest/etc/bbuild index cb4953f9f..06eeabac1 100644 --- a/src/build/citest/etc/bbuild +++ b/src/build/citest/etc/bbuild @@ -1 +1 @@ -/esw/fips760/Builds/b1129a_1149.760 +/esw/fips760/Builds/b0131a_1205.760 diff --git a/src/include/usr/scom/scomreasoncodes.H b/src/include/usr/scom/scomreasoncodes.H new file mode 100644 index 000000000..d2ffa7e79 --- /dev/null +++ b/src/include/usr/scom/scomreasoncodes.H @@ -0,0 +1,48 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/include/usr/xscom/scomreasoncodes.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef __SCOM_REASONCODES_H +#define __SCOM_REASONCODES_H + +#include + +namespace SCOM +{ + enum scomModuleId + { + SCOM_PERFORM_OP = 0x00, + SCOM_TRANSLATE = 0x01, + SCOM_PERFORM_TRANSLATE = 0x02, + SCOM_FIND_PARENT_TARGET = 0x03, + + }; + + enum scomReasonCode + { + SCOM_INVALID_ADDR = SCOM_COMP_ID | 0x01, + SCOM_NO_MATCHING_PARENT = SCOM_COMP_ID | 0x02, + SCOM_TRANS_INVALID_TYPE = SCOM_COMP_ID | 0x03, + SCOM_TRANS_UNSUPPORTED = SCOM_COMP_ID | 0x04, + }; +}; + +#endif diff --git a/src/usr/scom/makefile b/src/usr/scom/makefile index a7b4a6403..451ed17de 100644 --- a/src/usr/scom/makefile +++ b/src/usr/scom/makefile @@ -23,7 +23,7 @@ ROOTPATH = ../../.. MODULE = scom -OBJS = scom.o +OBJS = scom.o scomtrans.o SUBDIRS = test.d diff --git a/src/usr/scom/scom.C b/src/usr/scom/scom.C index 8bfdbf004..07a5754db 100644 --- a/src/usr/scom/scom.C +++ b/src/usr/scom/scom.C @@ -35,6 +35,7 @@ #include #include #include "scom.H" +#include // Trace definition trace_desc_t* g_trac_scom = NULL; @@ -56,7 +57,6 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, scomPerformOp); - /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, @@ -67,19 +67,45 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, va_list i_args) { errlHndl_t l_err = NULL; - mutex_t* l_mutex = NULL; + uint64_t l_scomAddr = va_arg(i_args,uint64_t); + + + l_err = checkIndirectAndDoScom(i_opType, + i_target, + io_buffer, + io_buflen, + i_accessType, + l_scomAddr); + + return l_err; +} + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +errlHndl_t checkIndirectAndDoScom(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; + mutex_t* l_mutex = NULL; + // If the indirect scom bit is 0, then doing a regular scom - if( (l_scomAddr & 0x8000000000000000) == 0) + if( (i_addr & 0x8000000000000000) == 0) { l_err = doScomOp(i_opType, i_target, io_buffer, io_buflen, i_accessType, - l_scomAddr); + i_addr); } // We are performing an indirect scom. else @@ -88,7 +114,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, uint64_t temp_scomAddr; memcpy(&l_io_buffer, io_buffer, 8); - memcpy(&temp_scomAddr, &l_scomAddr, 8); + memcpy(&temp_scomAddr, &i_addr, 8); // Get the 20bit indirect scom address temp_scomAddr = temp_scomAddr & 0x001FFFFF00000000; @@ -100,7 +126,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, l_io_buffer = l_io_buffer | temp_scomAddr; // zero out the indirect address from the buffer.. - l_scomAddr = l_scomAddr & 0x00000000EFFFFFFFF; + i_addr = i_addr & 0x00000000EFFFFFFFF; // If we are doing a read. We need to do a write first.. if(i_opType == DeviceFW::READ) @@ -121,7 +147,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, & l_io_buffer, io_buflen, i_accessType, - l_scomAddr); + i_addr); if (l_err != NULL) { @@ -136,7 +162,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, io_buffer, io_buflen, i_accessType, - l_scomAddr); + i_addr); mutex_unlock(l_mutex); @@ -154,7 +180,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, & l_io_buffer, io_buflen, i_accessType, - l_scomAddr); + i_addr); } } diff --git a/src/usr/scom/scom.H b/src/usr/scom/scom.H index f39720aae..d4b76a165 100644 --- a/src/usr/scom/scom.H +++ b/src/usr/scom/scom.H @@ -35,8 +35,9 @@ namespace SCOM /** * @brief Performs a SCom operation - * This function performs a SCOM operation by calling doScomOP. It - * handles whether the address a regular or an indirect SCOM address + * This function performs a SCOM operation by calling + * checkIndirectScomOP. It handles whether the address + * a regular or an indirect SCOM address * * @param[in] i_opType Operation type, see DeviceFW::OperationType * in driverif.H @@ -78,9 +79,7 @@ errlHndl_t scomPerformOp(DeviceFW::OperationType i_opType, * Write: size of data written * @param[in] i_accessType Select from DeviceFW::AccessType enum * (usrif.H) - * @param[in] i_args This is an argument list for DD framework. - * In this function, there's only one argument, - * which is the SCom address value. + * @param[in] i_addr scom Address Value * * @return errlHndl_t */ @@ -92,6 +91,33 @@ errlHndl_t doScomOp(DeviceFW::OperationType i_opType, uint64_t i_addr); +/** + * @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 + * + * @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 + * (usrif.H) + * @param[in] i_addr Scom Address Value. + * + * @return errlHndl_t + */ +errlHndl_t checkIndirectAndDoScom(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 #endif diff --git a/src/usr/scom/scomtrans.C b/src/usr/scom/scomtrans.C new file mode 100644 index 000000000..eaf42b98b --- /dev/null +++ b/src/usr/scom/scomtrans.C @@ -0,0 +1,496 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/scom/scomtrans.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file scomtrans.C + * + * @brief Implementation of SCOM operations + */ + +/*****************************************************************************/ +// I n c l u d e s +/*****************************************************************************/ +#include +#include +#include +#include +#include +#include "scom.H" +#include "scomtrans.H" +#include + +// Trace definition +extern trace_desc_t* g_trac_scom; + +namespace SCOM +{ + + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::SCOM, + TARGETING::TYPE_EX, + scomTranslate); + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::SCOM, + TARGETING::TYPE_MBS, + scomTranslate); + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::SCOM, + TARGETING::TYPE_MBA, + scomTranslate); + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::SCOM, + TARGETING::TYPE_MCS, + scomTranslate); + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::SCOM, + TARGETING::TYPE_XBUS, + scomTranslate); + +DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD, + DeviceFW::SCOM, + TARGETING::TYPE_ABUS, + scomTranslate); + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +errlHndl_t scomTranslate(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args) + +{ + errlHndl_t l_err = NULL; + + bool l_invalidAddr = false; + + uint64_t i_addr = va_arg(i_args,uint64_t); + + // Get the attribute type. + TARGETING::TYPE l_type = i_target->getAttr(); + + // get the specific entry to determine the address. + TARGETING::EntityPath epath; + + if (i_target->tryGetAttr(epath)) + { + if (l_type == TARGETING::TYPE_EX) + { + + // Below are the assumptions used for the EX translate + /*EX + Mask : 0x1F00_0000 + Range 1 : 0x1000_0000 - 0x10FF_FFFF + ... + ... + bits 3:7 correspond to what EX chiplet is targeted. + where 0x10XXXXXX is for EX0 + ... + where 0x13XXXXXX is for EX3 + where 0x14XXXXXX is for EX4 + ... + where 0x1CXXXXXX is for EX12 + + + original mask = 0x000000001F000000 + change that to be 0x7F000000 to catch other chiplets.*/ + + // check to see that the Address is in the correct range + if ((i_addr & SCOM_TRANS_EX_MASK) == SCOM_TRANS_EX_BASEADDR) + { + // Call the function that performs the translate + l_err = scomPerformTranslate(epath, + TARGETING::TYPE_EX, + TARGETING::TYPE_PROC, + 24, + SCOM_TRANS_EX_MASK, + i_target, + i_addr ); + } + else + { + // set invalid addr to true.. and create errorlog below. + l_invalidAddr = true; + } + } + else if (l_type == TARGETING::TYPE_MCS) + { + /* ring 6 = MCL + MC0 MCS0 = 0x02011800 MCS-0 range 0 + MC0 MCS1 = 0x02011880 MCS-1 range 0 + remainder + MC1 MCS0 = 0x02011900 MCS-2 range 1 + MC1 MCS0 = 0x02011980 MCS-3 range 1 + remainder + IOMC0 = 0x02011A00 -NOT targeting this range.. + ring 7 = MCR + MC2 MCS0 = 0x02011C00 MCS-4 range 2 + MC2 MCS1 = 0x02011C80 MCS-5 range 2 + remainder + MC3 MCS0 = 0x02011D00 MCS-6 range 3 + MC3 MCS1 = 0x02011D80 MCS-7 range 3 + remainder + + original mask = 0x0000000002011D80 + Need the mask to be 0x7FFFFF80*/ + + + uint64_t l_instance; + + // Check that we are working with the correct address range + if ((i_addr & SCOM_TRANS_MCS_MASK) == SCOM_TRANS_MCS_BASEADDR ) + { + + // Need to extract what instance of the entity we are at + l_instance = + epath.pathElementOfType(TARGETING::TYPE_MCS).instance; + + // based on the instance, update the address + + // range 1 - add 0x100 to the addr + if( (l_instance / 2) == 1) + { + i_addr += 0x100; + } + // range 2 - add 0x400 to the addr + else if( (l_instance / 2) == 2) + { + i_addr += 0x400; + } + // range 3 - add 0x500 to the addr + else if( (l_instance / 2) == 3) + { + i_addr += 0x500; + } + + // add 0x80 if the instance%2 is nonzero. + if (l_instance % 2) + { + i_addr += 0x80; + } + + // Call to set the target to the parent target type + l_err = scomfindParentTarget(epath, + TARGETING::TYPE_PROC, + i_target); + } + else + { + l_invalidAddr = true; + } + } + else if (l_type == TARGETING::TYPE_XBUS) + { + //*** temporarily put an error log indicating not supported until we + // have info from the hardware team + + TRACFCOMP(g_trac_scom, "SCOM_TRANSLATE-unsupported target type=0x%X", l_type); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_TRANSLATE + * @reasoncode SCOM::SCOM_TRANS_UNSUPPORTED + * @userdata1 Address + * @userdata2 Target Type that failed + * @devdesc Scom Translate not supported for this type + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_TRANSLATE, + SCOM_TRANS_UNSUPPORTED, + i_addr, + l_type); + + } + else if (l_type == TARGETING::TYPE_ABUS) + { + //*** temporarily put an error log indicating not supported until we have info + // from the hardware team + TRACFCOMP(g_trac_scom, "SCOM_TRANSLATE-unsupported target type=0x%X", l_type); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_TRANSLATE + * @reasoncode SCOM::SCOM_TRANS_UNSUPPORTED + * @userdata1 Address + * @userdata2 Target Type that failed + * @devdesc Scom Translate not supported for this type + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_TRANSLATE, + SCOM_TRANS_UNSUPPORTED, + i_addr, + l_type); + + + } + else if (l_type == TARGETING::TYPE_MBS) + { + /* + MBS + Mask : NA + Range 1 : 0x02010000 - 0x0201FFFF + + default>physical:sys-0/node-0/membuf-10/mbs-0 + + */ + // NO address shifting required.. no mask.. + // just get parent. + l_err = scomfindParentTarget(epath, + TARGETING::TYPE_MEMBUF, + i_target); + + } + else if (l_type == TARGETING::TYPE_MBA) + { + /* + MBA + Mask : 0x03010800 + Range 1 : 0x03010400 - 0301043F # MBA01 + Range 2 : 0x03010600 - 030106FF # MBA01 MCBIST + Range 4 : 0x03010C00 - 03010C3F # MBA23 + Range 5 : 0x03010E00 - 03010EFF # MBA23 MCBIST + + Original mask from hdw team is: 03010800 + The mask needs to be 0x7FFFF800 in order make sure we + don't have any other valid address bits on for another + chiplet. + + bits 20 correspond to what MBA chiplet is targeted. + where 0x03010000 is for MBA01 + where 0x03010800 is for MBA23 + + In the XML.. the + physical:sys-0/node-0/membuf-10/mbs-0/mba-1 + + Assuming the MBA we are accessing is under the Centaur + not the processor.. for now. + */ + // check to see that the Address is in the correct range + if ((i_addr & SCOM_TRANS_MBA_MASK) == SCOM_TRANS_MBA_BASEADDR) + { + + l_err = scomPerformTranslate(epath, + TARGETING::TYPE_MBA, + TARGETING::TYPE_MEMBUF, + 11, + SCOM_TRANS_MBA_MASK, + i_target, + i_addr ); + } + else + { + // got and error.. bad address.. write an errorlog.. + l_invalidAddr = true; + } + } + else + { + //*** temporarily put an error log indicating not supported until we have info + // from the hardware team + TRACFCOMP(g_trac_scom, "SCOM_TRANSLATE.. Invalid target type=0x%X", l_type); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_TRANSLATE + * @reasoncode SCOM::SCOM_TRANS_INVALID_TYPE + * @userdata1 Address + * @userdata2 Target Type that failed + * @devdesc Scom Translate not supported for this type + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_TRANSLATE, + SCOM_TRANS_INVALID_TYPE, + i_addr, + l_type); + + + } + } + + if (l_invalidAddr) + { + + TRACFCOMP(g_trac_scom, "scomTranslate-Invalid Address i_addr=0x%X", i_addr); + + /*@ + * @errortype + * @moduleid SCOM::SCOM_TRANSLATE + * @reasoncode SCOM::SCOM_INVALID_ADDR + * @userdata1 Address + * @userdata2 Unit type that failed + * @devdesc Invalid address for that unit + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_TRANSLATE, + SCOM_INVALID_ADDR, + i_addr, + l_type); + l_err->collectTrace("SCOM",1024); + + } + + if (l_err == NULL) + { + + // call the routine that will do the indirect scom + // and then call the correct device driver. + l_err = SCOM::checkIndirectAndDoScom(i_opType, + i_target, + io_buffer, + io_buflen, + i_accessType, + i_addr); + } + return l_err; +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +errlHndl_t scomPerformTranslate(TARGETING::EntityPath i_epath, + TARGETING::TYPE i_ctype, + TARGETING::TYPE i_ptype, + int i_shift, + int i_mask, + TARGETING::Target * &o_target, + uint64_t &i_addr ) +{ + + errlHndl_t l_err = NULL; + + uint64_t l_instance; + + // Need to extract what instance of the entity we are at we are + // for this target. + l_instance = i_epath.pathElementOfType(i_ctype).instance; + + // shift the instance variable over specificed number of + // bits with the chiplet area + l_instance = l_instance << i_shift; + + // Check the address against the mask + if (i_addr & i_mask) + { + // add the instance of this target to the address + i_addr = i_addr | l_instance; + } + else + { + /*@ + * @errortype + * @moduleid SCOM::SCOM_PERFORM_TRANSLATE + * @reasoncode SCOM::SCOM_INVALID_ADDR + * @userdata1 Address + * @userdata2 Unit type that failed + * @devdesc Invalid Address for the mask passed in. + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_PERFORM_TRANSLATE, + SCOM_INVALID_ADDR, + i_addr, + o_target->getAttr()); + + l_err->collectTrace("SCOM",1024); + + TRACFCOMP(g_trac_scom,"SCOMPERFORMTRANSLATE Invalid Address.i_addr =0x%X for mask = 0x%X", i_addr, i_mask); + + return (l_err); + } + + + l_err = scomfindParentTarget(i_epath, + i_ptype, + o_target); + + return l_err; + +} + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +errlHndl_t scomfindParentTarget( TARGETING::EntityPath i_epath, + TARGETING::TYPE i_ptype, + TARGETING::Target * &o_target) +{ + + errlHndl_t l_err = NULL; + + bool foundParent = false; + + // This routine passes in a given target.. the goal is to find its parent + // target that matches the passed in parent type. + + // This loop takes the last item off the entity path and + // checks to see if it matches the parent type.. If it does + // we exit.. it continues to loop until it either finds + // a match, or runs out of elements. + do + { + // remove the last entry from the entity path.. + i_epath.removeLast(); + + int lastEntry = i_epath.size() - 1; + + // if the type equals the type passed in. then create the target + if (i_epath[lastEntry].type == i_ptype) + { + // return the target to be the parent type. + o_target = TARGETING::targetService().toTarget(i_epath); + + foundParent = true; + + break; + } + } + while (i_epath.size() != 0); + + if (!foundParent) + { + // got and error.. bad address.. write an errorlog.. + /*@ + * @errortype + * @moduleid SCOM::SCOM_PERFORM_TRANSLATE + * @reasoncode SCOM::SCOM_NO_MATCHING_PARENT + * @userdata1 Parent type requested + * @userdata2 Unit type that failed + * @devdesc Did not find parent type requested + */ + l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SCOM_FIND_PARENT_TARGET, + SCOM_NO_MATCHING_PARENT, + i_ptype, + o_target->getAttr()); + + l_err->collectTrace("SCOM",1024); + + // Need to write and errorlog and return.. + TRACFCOMP(g_trac_scom, "TRANSLATE..Did not find parent type=0x%X ", i_ptype); + } + + return l_err; +} + + +} // end namespace diff --git a/src/usr/scom/scomtrans.H b/src/usr/scom/scomtrans.H new file mode 100644 index 000000000..e65cc3511 --- /dev/null +++ b/src/usr/scom/scomtrans.H @@ -0,0 +1,120 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/scom/scomtrans.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2011 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef __SCOMTRANS_H +#define __SCOMTRANS_H + +#include + +/** @file scomtrans.H + * @brief Provides the interfaces to perform a SCom + */ + +namespace SCOM +{ + + + enum ScomTransMask + { + SCOM_TRANS_EX_MASK = 0x000000007F000000, + SCOM_TRANS_MCS_MASK = 0x000000007FFFFF80, + SCOM_TRANS_MBA_MASK = 0x000000007FFFF800, + }; + + enum ScomTransBaseAddr + { + SCOM_TRANS_EX_BASEADDR = 0x0000000010000000, + SCOM_TRANS_MCS_BASEADDR = 0x0000000002011800, + SCOM_TRANS_MBA_BASEADDR = 0x0000000003010000, + }; + + + +/** + * @brief Performs a SCom Translation of the scom address + * This function performs the translation and get the + * correct target and continues the scom Operation. + * + * @param[in] i_opType Operation type, see DeviceFW::OperationType + * in driverif.H + * @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 + * (usrif.H) + * @param[in] i_args This is an argument list for DD framework. + * In this function, there's only one argument, + * which is the SCom address value. + */ +errlHndl_t scomTranslate(DeviceFW::OperationType i_opType, + TARGETING::Target* i_target, + void* io_buffer, + size_t& io_buflen, + int64_t i_accessType, + va_list i_args); + + +/** + * @brief Utility function does the address translation for + * unit types that have similar unit identifying strategy + * + * @param[in] i_epath entity path is passed in + * @param[in] i_ctype Current targets target type + * @param[in] i_ptype Target type of the parent + * @param[in] i_shift Number of bits the instance needs to shift + * @param[in] i_mask Mask value + * @param[in|out] o_target SCom target is passed in and after + * translation return a scomable target + * @param[in|out} i_addr Address passed in and return as a + * translated address + * @return errlHndl_t + */ +errlHndl_t scomPerformTranslate(TARGETING::EntityPath i_epath, + TARGETING::TYPE i_ctype, + TARGETING::TYPE i_ptype, + int i_shift, + int i_mask, + TARGETING::Target * &o_target, + uint64_t &i_addr ); + +/** + * @brief This function finds the parent target type and returns + * that as the new target + * + * @param[in] i_epath SCom target is passed in and return + * the parent type requested + * @param[in] i_ptype Target type needed for the parent requested + * @param[in|out] o_target SCom target is passed in and after + * translation return a parent target + * @return errlHndl_t + */ +errlHndl_t scomfindParentTarget( TARGETING::EntityPath i_epath, + TARGETING::TYPE i_ptype, + TARGETING::Target * &o_target); + + +}; // End namespace + +#endif diff --git a/src/usr/scom/test/scomtest.H b/src/usr/scom/test/scomtest.H index 183ac0ebc..543c589cc 100644 --- a/src/usr/scom/test/scomtest.H +++ b/src/usr/scom/test/scomtest.H @@ -260,7 +260,6 @@ public: uint64_t addr; uint64_t data; } test_data[] = { - { scom_targets[CENTAUR0], 0x00012345 , 0x1111222233334444 }, //@fixme - address should be 0x02011403 but simics is adding parity... { scom_targets[CENTAUR0], 0x02011402 , 0x123456789ABCDEF0 }, { scom_targets[CENTAUR0], 0x02011672 , 0x1122334455667788 }, @@ -348,6 +347,20 @@ public: 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 + TARGETING::EntityPath syspath(TARGETING::EntityPath::PATH_PHYSICAL); + syspath.addLast(TARGETING::TYPE_SYS,0); + TARGETING::Target* sys = TARGETING::targetService().toTarget(syspath); + uint8_t vpo_mode = 0; + if( sys + && sys->tryGetAttr(vpo_mode) + && (vpo_mode == 1) ) + { + return; + } + // Setup some targets to use enum { @@ -473,6 +486,541 @@ public: } + + + + + void test_TranslateScom_EX(void) + { + + TRACFCOMP( g_trac_scom, "ScomTest::test_TranslateScom> Start" ); + + 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 + TARGETING::EntityPath syspath(TARGETING::EntityPath::PATH_PHYSICAL); + syspath.addLast(TARGETING::TYPE_SYS,0); + TARGETING::Target* sys = TARGETING::targetService().toTarget(syspath); + uint8_t vpo_mode = 0; + if( sys + && sys->tryGetAttr(vpo_mode) + && (vpo_mode == 1) ) + { + return; + } + + // Setup some targets to use + enum { + myProc0, + myEX1, + myEX5, + NUM_TARGETS + }; + + TARGETING::Target* scom_targets[NUM_TARGETS]; + for( uint64_t x = 0; x < NUM_TARGETS; x++ ) + { + scom_targets[x] = NULL; + } + + // Target Proc 0 - to make sure we have XSCOM and FSISCOM attributes + 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); + + // Only check the Proc or Membuf targets to look at the SCOM attributes + if ((scom_targets[myProc0] != NULL) && + (scom_targets[myProc0]->getAttr().useXscom == 0) && + (scom_targets[myProc0]->getAttr().useFsiScom == 0)) + { + // If both FSI and XSCOM are not enabled.. then ignore.. + TRACFCOMP(g_trac_scom, "TRANSLATE SCOM>> SKIPPING "); + scom_targets[myProc0] = NULL; //remove from our list + } + + + if (scom_targets[myProc0] != NULL) + { + // Add the Ex1 to the path and create new target + epath.addLast(TARGETING::TYPE_EX,1); + scom_targets[myEX1] = TARGETING::targetService().toTarget(epath); + + // remote EX1 target (off of sys-0/node-0/proc-0/EX1) + epath.removeLast(); + + // add EX5 target. + epath.addLast(TARGETING::TYPE_EX,5); + scom_targets[myEX5] = TARGETING::targetService().toTarget(epath); + } + // scratch data to use + //@fixme: Need to either fabricate some fake registers to use or save off data before modifying SCOMs to avoid + // corrupting the HW. + + struct { + TARGETING::Target* target; + uint64_t addr; + uint64_t data; + } test_data[] = { + { scom_targets[myEX1], 0x100F0120 ,0x7676767676767676}, + { scom_targets[myEX5], 0x100F0166, 0x9191919191919191}, + { scom_targets[myEX5], 0x130F0166, 0xabcdabcdabcdabcd}, // invalid unit 0 address + { scom_targets[myEX1], 0x000F0166, 0xabcdabcdabcdabcd}, // invalid address range for target + }; + 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( l_err ) + { + // last 2 writes have expected failure conditions. + if ((x == NUM_ADDRS-1) || (x == NUM_ADDRS-2)) + { + TRACDCOMP( g_trac_scom, "ScomTest::test_translate_EX.. Expected Error log returned> " ); + } + else + { + TRACFCOMP(g_trac_scom, "ScomTest::test_translate_scom_EX> [%d] Write: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() ); + TS_FAIL( "ScomTest::test_translate_EX> ERROR : Unexpected error log from write1" ); + fails++; + errlCommit(l_err,SCOM_COMP_ID); + } + + delete l_err; + } + } + + // 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-2; 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) ); + + if( l_err ) + { + TRACFCOMP(g_trac_scom, "ScomTest::test_translate_scom_EX> [%d] Read: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() ); + TS_FAIL( "ScomTest::test_translate_scom_EX> ERROR : Unexpected error log from write1" ); + fails++; + errlCommit(l_err,SCOM_COMP_ID); + delete l_err; + } + else if((read_data[x]) != (test_data[x].data)) + { + TRACFCOMP(g_trac_scom, "ScomTest::test_translate_scom_EX> [%d] Read: Data miss-match : addr=0x%X, read_data=0x%llx, write_data=0x%llx", x, test_data[x].addr, read_data[x], test_data[x].data); + TS_FAIL( "ScomTest::test_translate_scom_EX> ERROR : Data miss-match between read and expected data" ); + fails++; + } + + } + + TRACFCOMP( g_trac_scom, "ScomTest::test_translateScom_EX> %d/%d fails", fails, total ); + + } + + + void test_TranslateScom_MCS(void) + { + + TRACFCOMP( g_trac_scom, "ScomTest::test_TranslateScom_MCS Start" ); + errlHndl_t l_err = NULL; + + uint64_t fails = 0; + uint64_t total = 0; + + + + //@VBU workaround - Disable Indirect SCOM test case o + //Test case read/writes to valid addresses and is + //potentially destructive on VBU + TARGETING::EntityPath syspath(TARGETING::EntityPath::PATH_PHYSICAL); + syspath.addLast(TARGETING::TYPE_SYS,0); + TARGETING::Target* sys = TARGETING::targetService().toTarget(syspath); + uint8_t vpo_mode = 0; + if( sys + && sys->tryGetAttr(vpo_mode) + && (vpo_mode == 1) ) + { + return; + } + + // Setup some targets to use + enum { + myProc0, + myMCS1, + myMCS2, + myMCS7, + myMCS4, + NUM_TARGETS + }; + + TARGETING::Target* scom_targets[NUM_TARGETS]; + for( uint64_t x = 0; x < NUM_TARGETS; x++ ) + { + scom_targets[x] = NULL; + } + + // Target Proc 0 - to make sure we have XSCOM and FSISCOM attributes + 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); + + // Only check the Proc or Membuf targets to look at the SCOM attributes + if ((scom_targets[myProc0] != NULL) && + (scom_targets[myProc0]->getAttr().useXscom == 0) && + (scom_targets[myProc0]->getAttr().useFsiScom == 0)) + { + // If both FSI and XSCOM are not enabled.. then ignore.. + TRACFCOMP(g_trac_scom, "TRANSLATE_SCOM_MCS>> SKIPPING "); + scom_targets[myProc0] = NULL; //remove from our list + } + + + if (scom_targets[myProc0] != NULL) + { + // Add the MCS(1) to the path and create new target + epath.addLast(TARGETING::TYPE_MCS,1); + scom_targets[myMCS1] = TARGETING::targetService().toTarget(epath); + + // remote MCS(1) (off of sys-0/node-0/proc-0/MCS1) + epath.removeLast(); + + // add MCS4 target. + epath.addLast(TARGETING::TYPE_MCS,4); + scom_targets[myMCS4] = TARGETING::targetService().toTarget(epath); + + // remote MCS4 target (off of sys-0/node-0/proc-0/MCS4) + epath.removeLast(); + + // add MCS2 target. + epath.addLast(TARGETING::TYPE_MCS,2); + scom_targets[myMCS2] = TARGETING::targetService().toTarget(epath); + + // remove MCS2 target (off of sys-0/node-0/proc-0/MCS4) + epath.removeLast(); + + // add MCS7 target. + epath.addLast(TARGETING::TYPE_MCS,7); + scom_targets[myMCS7] = TARGETING::targetService().toTarget(epath); + } + + // scratch data to use + //@fixme: Need to either fabricate some fake registers to use or save off data before modifying SCOMs to avoid + // corrupting the HW. + struct { + TARGETING::Target* target; + uint64_t addr; + uint64_t data; + } test_data[] = { + { scom_targets[myMCS1], 0x0201184A ,0x1111111122222222}, + { scom_targets[myMCS4], 0x0201184A, 0x3333333344444444}, + { scom_targets[myMCS2], 0x0201184A, 0x5555555566666666}, + { scom_targets[myMCS7], 0x0201184A, 0x7777777788888888}, +// { scom_targets[myMCS4], 0x02011C4A, 0x0101010101010101}, // invalid + // Unit for + // the + // target + { scom_targets[myMCS4], 0x0601184A, 0x0101010101010101}, // invalid address range + { scom_targets[myMCS4], 0x0200184A, 0x2323232323232323}, // Invalid address range for target + }; + 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( l_err ) + { + if ((x == NUM_ADDRS-1) || (x==NUM_ADDRS-2)) + { + TRACDCOMP( g_trac_scom, "ScomTest::test_translate MCS.. Expected Error log returned> x = %d", x ); + } + else + { + TRACFCOMP(g_trac_scom, "ScomTest::test_translate_Scom_MCS> [%d] Write: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() ); + TS_FAIL( "ScomTest::test_Translate_SCOM_mcs> ERROR : Unexpected error log from write1" ); + fails++; + errlCommit(l_err,SCOM_COMP_ID); + } + + delete l_err; + } + } + + // 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-2; 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) ); + + if( l_err ) + { + TRACFCOMP(g_trac_scom, "ScomTest::test_TranslateScom_MCS> [%d] Read: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() ); + TS_FAIL( "ScomTest::test_TranslateScom_MCS> ERROR : Unexpected error log from write1" ); + fails++; + errlCommit(l_err,SCOM_COMP_ID); + delete l_err; + } + else if((read_data[x]) != (test_data[x].data)) + { + TRACFCOMP(g_trac_scom, "ScomTest::test_TranslateScom_MCS> [%d] Read: Data miss-match : addr=0x%X, read_data=0x%llx, write_data=0x%llx", x, test_data[x].addr, read_data[x], test_data[x].data); + TS_FAIL( "ScomTest::test_TranslateScom_MCS> ERROR : Data miss-match between read and expected data" ); + fails++; + } + + } + + TRACFCOMP( g_trac_scom, "ScomTest::test_translateScom_MCS> %d/%d fails", fails, total ); + + } + + + + void test_TranslateScom_MBA_MBS(void) + { + TRACFCOMP( g_trac_scom, "ScomTest::test_TranslateScom_MBA_MBS Start" ); + + 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 + TARGETING::EntityPath syspath(TARGETING::EntityPath::PATH_PHYSICAL); + syspath.addLast(TARGETING::TYPE_SYS,0); + TARGETING::Target* sys = TARGETING::targetService().toTarget(syspath); + uint8_t vpo_mode = 0; + if( sys + && sys->tryGetAttr(vpo_mode) + && (vpo_mode == 1) ) + { + return; + } + + // Setup some targets to use + enum { + myMembuf0, + myMBS, + myMBA0, + myMBA1, + NUM_TARGETS + }; + + + TARGETING::Target* scom_targets[NUM_TARGETS]; + for( uint64_t x = 0; x < NUM_TARGETS; x++ ) + { + scom_targets[x] = NULL; + } + + // Target Proc 0 - to make sure we have XSCOM and FSISCOM attributes + TARGETING::EntityPath epath(TARGETING::EntityPath::PATH_PHYSICAL); + epath.addLast(TARGETING::TYPE_SYS,0); + epath.addLast(TARGETING::TYPE_NODE,0); + epath.addLast(TARGETING::TYPE_MEMBUF,0); + + scom_targets[myMembuf0] = TARGETING::targetService().toTarget(epath); + + if ( (scom_targets[myMembuf0] != NULL) && + (scom_targets[myMembuf0]->getAttr().useXscom == 0) && + (scom_targets[myMembuf0]->getAttr().useFsiScom == 0)) + { + // If both FSI and XSCOM are not enabled.. then ignore.. + TRACFCOMP(g_trac_scom, "TRANSLATE_SCOM_MBA_MBS>> SKIPPING "); + scom_targets[myMembuf0] = NULL; //remove from our list + } + + if(scom_targets[myMembuf0] != NULL) + { + // add MBS target. + epath.addLast(TARGETING::TYPE_MBS,0); + scom_targets[myMBS] = TARGETING::targetService().toTarget(epath); + + // add MBA0 target. + epath.addLast(TARGETING::TYPE_MBA,0); + scom_targets[myMBA0] = TARGETING::targetService().toTarget(epath); + + // remote MBA0 target (off of sys-0/node-0/membuf-0/MBS-0/MBA0) + epath.removeLast(); + + // Add MBA1 to the path and create new target + epath.addLast(TARGETING::TYPE_MBA,1); + scom_targets[myMBA1] = TARGETING::targetService().toTarget(epath); + } + // scratch data to use + //@fixme: Need to either fabricate some fake registers to use or save off data before modifying SCOMs to avoid + // corrupting the HW. + struct { + TARGETING::Target* target; + uint64_t addr; + uint64_t data; + } test_data[] = { + { scom_targets[myMBA0], 0x03010655 ,0x1111111122222222}, + { scom_targets[myMBA1], 0x03010655, 0x3333333344444444}, + { scom_targets[myMBS], 0x02011417, 0x1231231231231231}, + { scom_targets[myMBA0], 0x03010E55, 0x0101010101010101}, // invalid passing in a non-0 unit address + }; + 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) + { + TRACFCOMP( g_trac_scom, "MBA_MBS ScomTest before device write- TARGET = NULL x = %d", x); + + 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( l_err ) + { + // checking the read of NUM_ADDRs - 1 because the last entry written above failed as expected. + if (x == (NUM_ADDRS-1)) + { + TRACDCOMP( g_trac_scom, "ScomTest::test_translate MCS.. Expected Errorlog Returned> x = %d", x ); + } + else + { + TRACFCOMP(g_trac_scom, "ScomTest::test_translate_Scom_MBA_MBS> [%d] Write: Error from device : addr=0x%X, RC=%X", x, test_data[x].addr, l_err->reasonCode() ); + TS_FAIL( "ScomTest::test_Translate_SCOM_MBA_MBS> ERROR : Unexpected error log from write1" ); + fails++; + errlCommit(l_err,SCOM_COMP_ID); + } + + delete l_err; + } + } + + // allocate space for read data + uint64_t read_data[NUM_ADDRS]; + + // read all the test registers + for( uint64_t x = 0; x < NUM_ADDRS-1; x++ ) + { + memset(read_data, 0, sizeof read_data); + + //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) ); + + + 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() ); + TS_FAIL( "ScomTest::test_TranslateScom_MBA_MBS> ERROR : Unexpected error log from write1" ); + fails++; + errlCommit(l_err,SCOM_COMP_ID); + delete l_err; + } + else if((read_data[x]) != (test_data[x].data)) + { + TRACFCOMP(g_trac_scom, "ScomTest::test_TranslateScom_MBA_MBS> [%d] Read: Data miss-match : addr=0x%X, read_data=0x%llx, write_data=0x%llx", x, test_data[x].addr, read_data[x], test_data[x].data); + TS_FAIL( "ScomTest::test_TranslateScom_MBA_MBS> ERROR : Data miss-match between read and expected data" ); + fails++; + } + + } + + TRACFCOMP( g_trac_scom, "ScomTest::test_translateScom_MBA_MBS> %d/%d fails", fails, total ); + + } + + + + //@todo - write tests to verify connection between XSCOM and FSISCOM //@todo - write error path testcase for FSI scom using bad address -- cgit v1.2.1