diff options
| author | Dan Crowell <dcrowell@us.ibm.com> | 2013-01-07 12:31:20 -0600 |
|---|---|---|
| committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-01-15 11:57:02 -0600 |
| commit | f0036f0c657e090d38b58b8cd95b4ddde1d55b33 (patch) | |
| tree | 1601dc566fe7083603494a2b22d61fadf7fe5c03 /src/usr/vpd/test | |
| parent | a84cc4b307526e9895747f2e78bb36c93582d796 (diff) | |
| download | talos-hostboot-f0036f0c657e090d38b58b8cd95b4ddde1d55b33.tar.gz talos-hostboot-f0036f0c657e090d38b58b8cd95b4ddde1d55b33.zip | |
Refactor VPD code to eliminate redundancies
After noticing some redundant code and some odd include gymnastics
I pulled all of the VPD related code (spd,mvpd) into a single vpd
directory/module/component. This should make the addition of the
centaur fru vpd simpler as well.
Note: this is part of Story 39177 but not all of it, merging this
early to not hold up the work for Story 44009.
Change-Id: I7637a94d22e188050403ed5600b2d7f304c3d006
RTC: 39177
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/2863
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/vpd/test')
| -rwxr-xr-x | src/usr/vpd/test/dimmPrestest.H | 188 | ||||
| -rw-r--r-- | src/usr/vpd/test/makefile | 28 | ||||
| -rwxr-xr-x | src/usr/vpd/test/mvpdtest.H | 930 | ||||
| -rwxr-xr-x | src/usr/vpd/test/spdtest.H | 765 |
4 files changed, 1911 insertions, 0 deletions
diff --git a/src/usr/vpd/test/dimmPrestest.H b/src/usr/vpd/test/dimmPrestest.H new file mode 100755 index 000000000..ff8c3e4cb --- /dev/null +++ b/src/usr/vpd/test/dimmPrestest.H @@ -0,0 +1,188 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/vpd/test/dimmPrestest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __DIMMPRESTEST_H +#define __DIMMPRESTEST_H + +/** + * @file dimmPrestest.H + * + * @brief Test cases for DIMM Presence detect + */ +#include <sys/time.h> + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <targeting/common/predicates/predicates.H> + +#include <vpd/vpdreasoncodes.H> +#include <vpd/spdenums.H> +#include "spdtest.H" +#include "../spd.H" + +extern trace_desc_t* g_trac_spd; + +using namespace TARGETING; +using namespace SPD; + +class DIMMPresTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief This test is for testing the DIMM Presence detect logic. + */ + void testDimmPres ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + bool present = false; + size_t presentSize = sizeof(present); + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testDimmPres()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testDimmPres() - No DIMMs found!" ); + break; + } + + // Test only on first DIMM. + cmds++; + theTarget = dimmList[0]; + + // Check presence + err = deviceRead( theTarget, + &present, + presentSize, + DEVICE_PRESENT_ADDRESS() ); + + if( err ) + { + fails++; + TS_FAIL( "testDimmPres() - Error returned from DIMM Presence " + "Detect call!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + else if( presentSize != sizeof(present) ) + { + fails++; + TS_FAIL( "testDimmPrs() - Size of Presence buffer is not size " + "of boolean!" ); + continue; + } + else + { + // Test was good. + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testDimmPres - %d/%d fails", + fails, cmds ); + } + + + /** + * @brief This test tests that invalid sizes for Presence detect + * return errors. + */ + void testDimmPresInvalidSize ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + bool present = false; + size_t presentSize = 0x0; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testDimmPresInvalidSize()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testDimmPresInvalidSize() - No DIMMs found!" ); + break; + } + + // Test on first DIMM only + cmds++; + theTarget = dimmList[0]; + + // Check presence + err = deviceRead( theTarget, + &present, + presentSize, + DEVICE_PRESENT_ADDRESS() ); + + if( !err ) + { + fails++; + TS_FAIL( "testDimmPresInvalidSize() - Error not flagged for " + "invalid size!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + else + { + // Delete the error and continue + delete err; + err = NULL; + continue; + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testDimmPresInvalidSize() - %d/%d fails", + fails, cmds ); + } + + +}; + +#endif diff --git a/src/usr/vpd/test/makefile b/src/usr/vpd/test/makefile new file mode 100644 index 000000000..2ef83c69c --- /dev/null +++ b/src/usr/vpd/test/makefile @@ -0,0 +1,28 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/vpd/test/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2012,2013 +# +# 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 otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG +ROOTPATH = ../../../.. + +MODULE = testvpd +TESTS = *.H + +include ${ROOTPATH}/config.mk diff --git a/src/usr/vpd/test/mvpdtest.H b/src/usr/vpd/test/mvpdtest.H new file mode 100755 index 000000000..9480f2881 --- /dev/null +++ b/src/usr/vpd/test/mvpdtest.H @@ -0,0 +1,930 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/vpd/test/mvpdtest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __MVPDTEST_H +#define __MVPDTEST_H + +/** + * @file mvpdtest.H + * + * @brief Test cases for MVPD code + */ +#include <sys/time.h> + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <targeting/common/predicates/predicatectm.H> + +#include <vpd/mvpdenums.H> +#include <vpd/vpdreasoncodes.H> +#include "../mvpd.H" + + +extern trace_desc_t* g_trac_mvpd; + +using namespace TARGETING; +using namespace MVPD; + +/** + * @brief Structure to define record/keyword pairs for MVPD tests. + */ +struct mvpdTestData +{ + mvpdRecord record; + mvpdKeyword keyword; +}; + +/** + * @brief Data sample to be used for MVPD testing. + * NOTE: By reading this entire list, it also validates that the records + * and keywords that we expect to be there are actually there... + */ +mvpdTestData mvpdData[] = +{ + { CRP0, VD }, + { CRP0, ED }, + { CRP0, TE }, + { CRP0, DD }, +// { CRP0, pdP }, // TODO - no #P in test data, pull for now RTC 51716 + { CRP0, ST }, +// { CRP0, DN, 0x03 }, // TODO - This doesn't match documentation, +// pulling out for now + { CP00, VD }, + { CP00, PG }, +// { CP00, PK }, // TODO - no PK in test data. pull for now RTC 51716 + { CP00, pdR }, + { CP00, pdG }, + { CP00, pdV }, + { CP00, pdH }, +// { CP00, pdP }, // TODO - no #P in test data, pull for now RTC 51716 + { CP00, SB }, + { CP00, MK }, + { CP00, PB }, +/* // TODO no LRP0,LRP1,LRP2,LRP3 in test data, pull for now RTC 51716 + { LRP0, VD }, + { LRP0, pdV }, + { LRP0, pdP }, + { LRP0, pdM }, + { LRP0, CH }, + { LRP1, VD }, + { LRP1, pdV }, + { LRP1, pdP }, + { LRP1, pdM }, + { LRP1, CH }, + { LRP2, VD }, + { LRP2, pdV }, + { LRP2, pdP }, + { LRP2, pdM }, + { LRP2, CH }, + { LRP3, VD }, + { LRP3, pdV }, + { LRP3, pdP }, + { LRP3, pdM }, + { LRP3, CH }, +*/ + { LRP4, VD }, + { LRP4, pdV }, + { LRP4, pdP }, + { LRP4, pdM }, + { LRP4, CH }, + { LRP5, VD }, + { LRP5, pdV }, + { LRP5, pdP }, + { LRP5, pdM }, + { LRP5, CH }, + { LRP6, VD }, + { LRP6, pdV }, + { LRP6, pdP }, + { LRP6, pdM }, + { LRP6, CH }, +/* // TODO no LRP7,LRP8,LRP9,LRPA,LRPB,LWPO,LWP1,LWP2,LWP3 in test data, pull for now RTC 51716 + { LRP7, VD }, + { LRP7, pdV }, + { LRP7, pdP }, + { LRP7, pdM }, + { LRP7, CH }, + { LRP8, VD }, + { LRP8, pdV }, + { LRP8, pdP }, + { LRP8, pdM }, + { LRP8, CH }, + { LRP9, VD }, + { LRP9, pdV }, + { LRP9, pdP }, + { LRP9, pdM }, + { LRP9, CH }, + { LRPA, VD }, + { LRPA, pdV }, + { LRPA, pdP }, + { LRPA, pdM }, + { LRPA, CH }, + { LRPB, VD }, + { LRPB, pdV }, + { LRPB, pdP }, + { LRPB, pdM }, + { LRPB, CH }, + { LRPC, VD }, + { LRPC, pdV }, + { LRPC, pdP }, + { LRPC, pdM }, + { LRPC, CH }, + { LRPD, VD }, + { LRPD, pdV }, + { LRPD, pdP }, + { LRPD, pdM }, + { LRPD, CH }, + { LRPE, VD }, + { LRPE, pdV }, + { LRPE, pdP }, + { LRPE, pdM }, + { LRPE, CH }, + { LWP0, VD }, + { LWP0, pd2 }, + { LWP0, pd3 }, + { LWP0, IN }, + { LWP1, VD }, + { LWP1, pd2 }, + { LWP1, pd3 }, + { LWP1, IN }, + { LWP2, VD }, + { LWP2, pd2 }, + { LWP2, pd3 }, + { LWP2, IN }, + { LWP3, VD }, + { LWP3, pd2 }, + { LWP3, pd3 }, + { LWP3, IN }, +*/ + { LWP4, VD }, + { LWP4, pd2 }, + { LWP4, pd3 }, + { LWP4, IN }, + { LWP5, VD }, + { LWP5, pd2 }, + { LWP5, pd3 }, + { LWP5, IN }, + { LWP6, VD }, + { LWP6, pd2 }, + { LWP6, pd3 }, + { LWP6, IN }, +/* // TODO no LWP7,LWP8,LWP9,LWPA,LWPB in test data, pull for now RTC 51716 + { LWP7, VD }, + { LWP7, pd2 }, + { LWP7, pd3 }, + { LWP7, IN }, + { LWP8, VD }, + { LWP8, pd2 }, + { LWP8, pd3 }, + { LWP8, IN }, + { LWP9, VD }, + { LWP9, pd2 }, + { LWP9, pd3 }, + { LWP9, IN }, + { LWPA, VD }, + { LWPA, pd2 }, + { LWPA, pd3 }, + { LWPA, IN }, + { LWPB, VD }, + { LWPB, pd2 }, + { LWPB, pd3 }, + { LWPB, IN }, + { LWPC, VD }, + { LWPC, pd2 }, + { LWPC, pd3 }, + { LWPC, IN }, + { LWPD, VD }, + { LWPD, pd2 }, + { LWPD, pd3 }, + { LWPD, IN }, + { LWPE, VD }, + { LWPE, pd2 }, + { LWPE, pd3 }, + { LWPE, IN }, +*/ + { VINI, DR }, + { VINI, VZ }, + { VINI, CC }, + { VINI, CE }, + { VINI, FN }, + { VINI, PN }, + { VINI, SN }, + { VINI, PR }, + { VINI, HE }, + { VINI, CT }, + { VINI, HW }, + // TODO - Add VWML when available. +}; + +void getProcTargets( TargetHandleList & o_procList ) +{ + // Get top level system target + TARGETING::TargetService & tS = TARGETING::targetService(); + TARGETING::Target * sysTarget = NULL; + tS.getTopLevelTarget( sysTarget ); + assert( sysTarget != NULL ); + + // Get a Proc Target + TARGETING::PredicateCTM predProc( TARGETING::CLASS_CHIP, + TARGETING::TYPE_PROC ); + tS.getAssociated( o_procList, + sysTarget, + TARGETING::TargetService::CHILD, + TARGETING::TargetService::ALL, + &predProc ); + + TRACDCOMP( g_trac_mvpd, + "getProcTargets() - found %d Processors", + o_procList.size() ); + + return; +} + +class MVPDTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief This function will test MVPD reads. + */ + void testMvpdRead ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + uint64_t theRecord = 0x0; + uint64_t theKeyword = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdRead()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + "testMvpdRead() - No Proc Targets found!" ); + + continue; // add continue because have no proc targets + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdRead() - Proc Target [0] non functional!" ); + + continue; // add continue because target is non functional + } + + uint8_t * theData = NULL; + size_t theSize = 0; + const uint32_t numCmds = sizeof(mvpdData)/sizeof(mvpdData[0]); + for( uint32_t curCmd = 0; curCmd < numCmds; curCmd++ ) + { + cmds++; + theRecord = (uint64_t)mvpdData[curCmd].record; + theKeyword = (uint64_t)mvpdData[curCmd].keyword; + err = deviceRead( theTarget, + NULL, + theSize, + DEVICE_MVPD_ADDRESS( theRecord, + theKeyword ) ); + + if( err ) + { + fails++; + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdRead() - failure reading " + "keyword size!! rec: 0x%04x, kwd: 0x%04x", + theRecord, + theKeyword ); + TS_FAIL( "testMvpdRead() - Failure reading keyword size!" ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + + theData = static_cast<uint8_t*>(malloc( theSize )); + + // Read record/keyword pair + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( theRecord, + theKeyword ) ); + + if( err ) + { + fails++; + TRACFCOMP( g_trac_mvpd, + ERR_MRK"testMvpdRead() - Failure on Record: " + "0x%04x, keyword: 0x%04x, of size: 0x%04x " + "- test %d", + theRecord, + theKeyword, + theSize, curCmd ); + TS_FAIL( "testMvpdRead() - Failure during MVPD read!" ); + errlCommit( err, + VPD_COMP_ID ); + + // Free the data + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + continue; + } + + TRACDCOMP( g_trac_mvpd, + INFO_MRK"testMvpdRead Results:" ); + for( uint32_t i = 0; i < theSize; i++ ) + { + TRACDCOMP( g_trac_mvpd, + INFO_MRK" Byte[%d]: 0x%02x", + i, theData[i] ); + } + + // Free the data + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdRead - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test MVPD writes. + */ + void testMvpdWrite ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdWrite()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + "testMvpdWrite() - No Proc Targets found!" ); + + continue; // no proc targets. + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdWrite() - Proc Target [0] non functional!" ); + + continue; // add continue because target is non functional + } + + size_t theSize = 1; + uint8_t * theData = new uint8_t[theSize]; + + cmds++; + err = deviceWrite( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( CRP0, + pdP ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testMvpdWrite - Expected error from write " + "attempt since its not supported!" ); + } + else + { + delete err; + err = NULL; + } + + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdWrite - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test that an error is generated when a record + * is passed in that cannot be found in the structure that defines the + * Records string representation. + */ + void testMvpdInvalidRecord ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdInvalidRecord()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidRecord() - No Proc Targets " + "found!" ); + + continue; + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidRecord() - Proc Target [0] non " + "functional!" ); + + continue; // add continue because target is non functional + } + + size_t theSize = 1; + uint8_t * theData = new uint8_t[theSize]; + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( MVPD_LAST_RECORD, + pdP ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testMvpdInvalidRecord() - Error expected with " + "record of type MVPD_LAST_RECORD (0x%04x), but " + "no error returned!", + MVPD_LAST_RECORD ); + } + else + { + delete err; + err = NULL; + } + + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidRecord - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test for a record which is not in the TOC of + * the MVPD area. + */ + void testMvpdMissingRecord ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdMissingRecord()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + + "testMvpdMissingRecord() - No Proc Targets found!" ); + + continue; + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdMissingRecord() - Proc Target [0] " + "non functional!" ); + + continue; // add continue because target is non functional + } + + size_t theSize = 1; + uint8_t * theData = new uint8_t[theSize]; + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( MVPD_TEST_RECORD, + pdP ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testMvpdMissingRecord() - "); + } + else + { + delete err; + err = NULL; + } + + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdMissingRecord - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test for a keyword that cannot be found + * in the expected record + */ + void testMvpdMissingKeyword ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdMissingKeyword()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + + "testMvpdMissingKeyword() - No Proc Targets found!" ); + + continue; + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdMissingKeyword() - Proc Target [0] " + "non functional!" ); + + continue; // add continue because target is non functional + } + + size_t theSize = 1; + uint8_t * theData = new uint8_t[theSize]; + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( MVPD_FIRST_RECORD, + MVPD_TEST_KEYWORD ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testMvpdMissingKeyword() - Expected error from " + "invalid Keyword missing from associated record!" ); + } + else + { + delete err; + err = NULL; + } + + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdMissingKeyword - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test that an error is generated when a keyword + * is passed in that cannot be found in the structure that defines the + * Keywords string representation. + */ + void testMvpdInvalidKeyword ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdInvalidKeyword()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + + "testMvpdInvalidKeyword() - No Proc Targets found!" ); + + continue; + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidKeyword() - Proc Target [0] " + "non functional!" ); + + continue; // add continue because target is non functional + } + + size_t theSize = 1; + uint8_t * theData = new uint8_t[theSize]; + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( CRP0, + MVPD_LAST_KEYWORD ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testMvpdInvalidKeyword() - Error expected with " + "keyword of type MVPD_LAST_KEYWORD (0x%04x), but " + "no error returned!", + MVPD_LAST_KEYWORD ); + } + else + { + delete err; + err = NULL; + } + + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidKeyword - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test that an error is generated when a buffer + * that has an insufficient size is passed in to read a record/keyword. + */ + void testMvpdInvalidBufferSize ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdInvalidBufferSize()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get the processor targets + TargetHandleList procList; + getProcTargets( procList ); + + if( ( 0 == procList.size() ) || + ( NULL == procList[0] ) ) + { + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidBufferSize() - No Proc Targets " + "found!" ); + + continue; + } + + // Use the first Proc in the list + theTarget = procList[0]; + + // check to see if the target is functional + if + (!theTarget->getAttr<TARGETING::ATTR_HWAS_STATE>().functional) + { + + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidBufferSize() - Proc Target [0] " + "non functional!" ); + + continue; // add continue because target is non functional + } + + uint8_t * theData = new uint8_t[1]; + size_t theSize = 0; + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_MVPD_ADDRESS( CRP0, + DD ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testMvpdInvalidBufferSize() - Error was expected " + "for an invalid size of 0x0 for a MVPD read!" ); + } + else + { + delete err; + err = NULL; + } + + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_mvpd, + "testMvpdInvalidBufferSize - %d/%d fails", + fails, cmds ); + } + + /** + * @brief This function will test the numerical order of the mvpdRecords + * and mvpdKeywords structures. + */ + void testMvpdCheckStructOrder ( void ) + { + uint64_t fails = 0x0; + mvpdRecord prevRecord = MVPD_FIRST_RECORD; + mvpdKeyword prevKeyword = MVPD_FIRST_KEYWORD; + + TRACFCOMP( g_trac_mvpd, + ENTER_MRK"testMvpdCheckStructOrder()" ); + + // Check the mvpdRecords structure for proper order + uint32_t entry = 0x0; + for( entry = 0; + entry < (sizeof(mvpdRecords)/sizeof(mvpdRecords[0])); + entry++ ) + { + if( !(mvpdRecords[entry].record >= prevRecord) ) + { + fails++; + TS_FAIL( "testMvpdCheckStructOrder() - Record table out of " + "order! Cur Record: 0x%04x, Prev Record: 0x%04x", + mvpdRecords[entry].record, + prevRecord ); + } + prevRecord = mvpdRecords[entry].record; + } + + // Check the mvpdKeywords structure for proper order + for( entry = 0; + entry < (sizeof(mvpdKeywords)/sizeof(mvpdKeywords[0])); + entry++ ) + { + if( !(mvpdKeywords[entry].keyword >= prevKeyword) ) + { + fails++; + TS_FAIL( "testMvpdCheckStructOrder() - Keyword table out of " + "order! Cur Keyword: 0x%04x, Prev Keyword: 0x%04x", + mvpdKeywords[entry].keyword, + prevKeyword ); + } + prevKeyword = mvpdKeywords[entry].keyword; + } + + TRACFCOMP( g_trac_mvpd, + "testMvpdCheckStructOrder - %d fails", + fails ); + } + +}; + +#endif diff --git a/src/usr/vpd/test/spdtest.H b/src/usr/vpd/test/spdtest.H new file mode 100755 index 000000000..38b53bf23 --- /dev/null +++ b/src/usr/vpd/test/spdtest.H @@ -0,0 +1,765 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/vpd/test/spdtest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __SPDTEST_H +#define __SPDTEST_H + +/** + * @file spdtest.H + * + * @brief Test cases for SPD code + */ +#include <sys/time.h> + +#include <cxxtest/TestSuite.H> +#include <errl/errlmanager.H> +#include <errl/errlentry.H> +#include <devicefw/driverif.H> +#include <targeting/common/predicates/predicates.H> +#include <targeting/common/utilFilter.H> + +#include <vpd/vpdreasoncodes.H> +#include <vpd/spdenums.H> +#include "../spdDDR3.H" +#include "../spd.H" + +extern trace_desc_t* g_trac_spd; + +using namespace TARGETING; +using namespace SPD; + +void getDIMMTargets ( TargetHandleList & o_dimmList ) +{ + // Get Dimm list. + getAllLogicalCards( o_dimmList, + TARGETING::TYPE_DIMM ); + TRACDCOMP( g_trac_spd, + "getDIMMTargets() - found %d DIMMs", + o_dimmList.size() ); + return; +} + +errlHndl_t getMemType( TARGETING::Target * i_target, + uint8_t & i_memType ) +{ + errlHndl_t err = NULL; + size_t theSize = 0x1; + err = deviceRead( i_target, + &i_memType, + theSize, + DEVICE_SPD_ADDRESS( SPD::BASIC_MEMORY_TYPE ) ); + + return err; +} + +class SPDTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief This test reads all of the keywords for all of the + * DIMMs found. + */ + void testSpdRead ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + uint8_t * theData = NULL; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdRead()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdRead - No DIMMs found!" ); + break; + } + + // Operate on first DIMM. + theTarget = dimmList[0]; + size_t theSize = 0; + uint32_t entry = 0x0; + + // Get the DDR revision + uint8_t memType = 0x0; + err = getMemType( theTarget, + memType ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdRead- Failure reading Basic memory type!" ); + errlCommit( err, + VPD_COMP_ID ); + break;; + } + + for( uint64_t keyword = SPD::SPD_FIRST_NORM_KEYWORD; + keyword < SPD::SPD_LAST_NORM_KEYWORD; keyword++ ) + { + cmds++; + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + + // Get the required size of the buffer + theSize = 0; + if( SPD_DDR3 == memType ) + { + for( entry = 0; + entry < (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + entry++ ) + { + if( keyword == ddr3Data[entry].keyword ) + { + theSize = ddr3Data[entry].length; + break; + } + } + } + else + { + // Nothing else supported yet! + // Not really a fail, just not supported + cmds--; + continue; + } + + if( 0x0 == theSize ) + { + fails++; + TS_FAIL( "testSpdRead - Keyword (0x%04x) size = 0x0", + entry ); + continue; + } + + // Allocate the buffer + theData = static_cast<uint8_t*>(malloc( theSize )); + + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( keyword ) ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdRead - Failure on keyword: %04x", + keyword ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + + // Read was successful, print out first byte of data read + TRACFCOMP( g_trac_spd, + "testSpdRead - kwd: 0x%04x, val: %02x, size: %d", + keyword, theData[0], theSize ); + + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + } + + if( err ) + { + break; + } + } while( 0 ); + + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + + TRACFCOMP( g_trac_spd, + "testSpdRead - %d/%d fails", + fails, cmds ); + } + + /** + * @brief Test a SPD Write + */ + void testSpdWrite ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + uint8_t * theData = NULL; + uint8_t * origData = NULL; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdWrite()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdWrite - No DIMMs found!" ); + break; + } + + // Operate on first DIMM + cmds++; + theTarget = dimmList[0]; + size_t theSize = 0; + + // Get Memory Type + uint8_t memType = 0x0; + err = getMemType( theTarget, + memType ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdWrite - failed to read memtype!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + // Get the size + if( SPD_DDR3 == memType ) + { + for( uint32_t entry = 0; + entry < (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + entry++ ) + { + if( SPD::DIMM_BAD_DQ_DATA == ddr3Data[entry].keyword ) + { + theSize = ddr3Data[entry].length; + break; + } + } + } + else + { + fails++; + TRACFCOMP( g_trac_spd, + "testSpdWrite - memory type: 0x%04x", + memType ); + TS_FAIL( "testSpdWrite - Unsupported Memory Type!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + // Allocate data buffer + theData = static_cast<uint8_t*>(malloc( theSize )); + + // Read the data out first + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdWrite - failed to read DIMM Bad DQ data!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + origData = static_cast<uint8_t*>(malloc( theSize )); + memcpy( origData, theData, theSize ); + + // Write the data back + err = deviceWrite( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); + + if( err ) + { + // No error returned, failure + fails++; + TS_FAIL( "testSpdWrite - Error writing data to DIMM Bad DQ " + "data" ); + break; + } + else + { + delete err; + err = NULL; + } + + // Read the data out again to check it + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( DIMM_BAD_DQ_DATA ) ); + + if( err ) + { + fails++; + TS_FAIL( "testSpdWrite - failed to read DIMM Bad DQ data! [2]" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + if( memcmp( theData, origData, theSize ) ) + { + fails++; + TS_FAIL( "testSpdWrite - DIMM Bad DQ data does not match what we wrote!" ); + TRACFBIN( g_trac_spd, "orig=", origData, theSize ); + TRACFBIN( g_trac_spd, "read=", theData, theSize ); + } + + } while( 0 ); + + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + + if( NULL != origData ) + { + free( origData ); + theData = NULL; + } + + TRACFCOMP( g_trac_spd, + "testSpdWrite - %d/%d fails", + fails, cmds ); + } + + /** + * @brief Test an invalid Keyword to a DIMM target. + */ + void testSpdInvalidKeyword ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdInvalidKeyword()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdInvalidKeyword - No DIMMs found!" ); + break; + } + + // Test on first DIMM only. + theTarget = dimmList[0]; + uint8_t * theData = NULL; + size_t theSize = 0x0; + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( SPD::INVALID_SPD_KEYWORD ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testSpdInvalidKeyword - No error returned!" ); + break; + } + else + { + delete err; + err = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testSpdInvalidKeyword - %d/%d fails", + fails, cmds ); + } + + /** + * @brief Test an invalid size for an SPD read. + */ + void testSpdInvalidSize ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdInvalidSize()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdInvalidSize - No DIMMs found!" ); + break; + } + + // Test on first DIMM only. + theTarget = dimmList[0]; + uint8_t * theData = NULL; + size_t theSize = 0x0; // Invalid size of 0x0 + + cmds++; + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( SPD::SPD_FIRST_NORM_KEYWORD ) ); + + if( NULL == err ) + { + fails++; + TS_FAIL( "testSpdInvalidSize - No error for invalid size!" ); + break; + } + else + { + delete err; + err = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testSpdInvalidSize - %d/%d fails", + fails, cmds ); + } + + /** + */ + void testSpdInvalidWrite ( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testSpdInvalidWrite()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testSpdInvalidSize - No DIMMs found!" ); + break; + } + + // Test on first DIMM only. + theTarget = dimmList[0]; + size_t theSize = 0x10; + uint8_t * theData = static_cast<uint8_t*>(malloc( theSize )); + + cmds++; + err = deviceWrite( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( SPD::SPD_FIRST_NORM_KEYWORD ) ); + + // clean up the data + if( NULL != theData ) + { + delete theData; + theData = NULL; + } + + if( NULL == err ) + { + fails++; + TS_FAIL( "No failure for Invalid Write attempt to " + "SPD_FIRST_NORM_KEYWORD" ); + break; + } + else + { + delete err; + err = NULL; + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testSpdInvalidWrite - %d/%d fails", + fails, cmds ); + } + + + /** + * @brief This test will test reading the Module specific keywords. + */ + void testspdDDR3ModSpecKwds( void ) + { + errlHndl_t err = NULL; + uint64_t cmds = 0x0; + uint64_t fails = 0x0; + uint8_t memType = 0x0; + uint8_t modType = 0x0; + uint8_t * theData = NULL; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testspdDDR3ModSpecKwds()" ); + + do + { + TARGETING::Target * theTarget = NULL; + + // Get DIMM Targets + TargetHandleList dimmList; + getDIMMTargets( dimmList ); + + if( ( 0 == dimmList.size() ) || + ( NULL == dimmList[0] ) ) + { + TRACFCOMP( g_trac_spd, + "testspdDDR3ModSpecKwds - No DIMMs found!" ); + break; + } + + // Operate on first DIMM. + theTarget = dimmList[0]; + size_t theSize = 0; + uint32_t entry = 0x0; + + // Get the DDR revision + size_t tmpSize = 0x1; + err = deviceRead( theTarget, + &memType, + tmpSize, + DEVICE_SPD_ADDRESS( SPD::BASIC_MEMORY_TYPE ) ); + + if( err ) + { + fails++; + TS_FAIL( "testspdDDR3ModSpecKwds- Failure reading Basic " + "memory type!" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + // Get the Module Type + err = deviceRead( theTarget, + &modType, + tmpSize, + DEVICE_SPD_ADDRESS( SPD::MODULE_TYPE ) ); + + if( err ) + { + fails++; + TS_FAIL( "testspdDDR3ModSpecKwds - Failure reading Module " + "type" ); + errlCommit( err, + VPD_COMP_ID ); + break; + } + + // The real Keyword read testing + for( uint64_t keyword = SPD::SPD_FIRST_MOD_SPEC; + keyword < SPD::SPD_LAST_MOD_SPEC; keyword++ ) + { + cmds++; + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + + // Get the required size of the buffer + theSize = 0; + KeywordData kwdData; + if( SPD_DDR3 == memType ) + { + for( entry = 0; + entry < (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + entry++ ) + { + if( keyword == ddr3Data[entry].keyword ) + { + kwdData = ddr3Data[entry]; + theSize = ddr3Data[entry].length; + break; + } + } + + // Check type of module. + TRACFCOMP( g_trac_spd, + INFO_MRK"SPD Error traces will follow!!! " + "Not all module specific keywords will be " + "valid for all types of modules. IGNORE!!" ); + err = checkModSpecificKeyword( kwdData, + memType, + theTarget ); + + if( err ) + { + // This keyword isn't supported with this module + // type + cmds--; + delete err; + err = NULL; + continue; + } + } + else + { + // Nothing else supported yet! + // Not really a fail, just not supported + cmds--; + continue; + } + + if( 0x0 == theSize ) + { + fails++; + TS_FAIL( "testspdDDR3ModSpecKwds - Keyword (0x%04x) " + "size = 0x0", + entry ); + continue; + } + + // Allocate the buffer + theData = static_cast<uint8_t*>(malloc( theSize )); + err = deviceRead( theTarget, + theData, + theSize, + DEVICE_SPD_ADDRESS( keyword ) ); + + if( err ) + { + fails++; + TS_FAIL( "testspdDDR3ModSpecKwds - Failure on keyword" + "d: %04x", + keyword ); + errlCommit( err, + VPD_COMP_ID ); + continue; + } + + // Read was successful, print out first 2 bytes of data read + TRACFCOMP( g_trac_spd, + "testspdDDR3ModSpecKwds - kwd: 0x%04x, val: " + "%02x, size: %d", + keyword, theData[0], theSize ); + + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + } + } while( 0 ); + + if( NULL != theData ) + { + free( theData ); + theData = NULL; + } + + TRACFCOMP( g_trac_spd, + "testspdDDR3ModSpecKwds - %d/%d fails", + fails, cmds ); + } + + + /** + * @brief This test will ensure that the DDR3 lookup table is in a sorted + * order, according to the keyword enumeration, to enable the search + * algorithm to work correctly. + */ + void testspdDDR3TableOrder ( void ) + { + uint64_t prevKeyword = 0x0; + uint64_t fails = 0x0; + + TRACFCOMP( g_trac_spd, + ENTER_MRK"testspdDDR3TableOrder()" ); + + for( uint32_t entry = 0; + entry < (sizeof(ddr3Data)/sizeof(ddr3Data[0])); + entry++ ) + { + if( !(ddr3Data[entry].keyword >= prevKeyword) ) + { + fails++; + TS_FAIL( "testspdDDR3TableOrder - DDR3 table out of order! Cur kwd: " + "0x%04x, Pre kwd: 0x%04x", + ddr3Data[entry].keyword, + prevKeyword ); + } + prevKeyword = ddr3Data[entry].keyword; + } + + TRACFCOMP( g_trac_spd, + EXIT_MRK"testspdDDR3TableOrder() - fails: %d", + fails ); + } + + +}; + +#endif |

