diff options
author | Terry J. Opie <opiet@us.ibm.com> | 2012-01-03 15:06:17 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-02-16 13:41:54 -0600 |
commit | 4690f9cb99f289dd88b1f1047145841d8386b0d3 (patch) | |
tree | 6a08e8c640ace271b0019bef5a542646d0969807 | |
parent | 5f6568a59e35570f149d148f0cb24e068e70efcf (diff) | |
download | talos-hostboot-4690f9cb99f289dd88b1f1047145841d8386b0d3.tar.gz talos-hostboot-4690f9cb99f289dd88b1f1047145841d8386b0d3.zip |
DIMM Presence Detect
- Detect DIMMs by reading BASIC_MEMORY_TYPE
- Testcases to test DIMM Presence Detect
- Added new SPD Keyword Enumeration
- Modified table lookup for DRAM_MANUFACTURER_ID
- New DIMM SPD data from Hardware team
Change-Id: I11a0b8ad4b13d6200a58efc7459396f0a12695f2
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/646
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/include/usr/spd/spdenums.H | 1 | ||||
-rw-r--r-- | src/include/usr/spd/spdreasoncodes.H | 1 | ||||
-rwxr-xr-x | src/usr/spd/dimmPres.C | 158 | ||||
-rw-r--r-- | src/usr/spd/dimmspd.dat | bin | 256 -> 257 bytes | |||
-rw-r--r-- | src/usr/spd/makefile | 2 | ||||
-rwxr-xr-x | src/usr/spd/spd.C | 63 | ||||
-rwxr-xr-x | src/usr/spd/spd.H | 30 | ||||
-rwxr-xr-x | src/usr/spd/spdDDR3.H | 3 | ||||
-rwxr-xr-x | src/usr/spd/test/dimmPrestest.H | 202 | ||||
-rwxr-xr-x | src/usr/spd/test/spdtest.H | 2 |
10 files changed, 436 insertions, 26 deletions
diff --git a/src/include/usr/spd/spdenums.H b/src/include/usr/spd/spdenums.H index 8ca1cd39f..c685fa99e 100644 --- a/src/include/usr/spd/spdenums.H +++ b/src/include/usr/spd/spdenums.H @@ -101,6 +101,7 @@ enum MODULE_THERMAL_SENSOR = 0x3c, SDRAM_OPTIONAL_FEATURES = 0x3d, SDRAM_THERMAL_REFRESH_OPTIONS = 0x3e, + DIMM_BAD_DQ_DATA = 0x3f, // This keyword should be last in the list SPD_LAST_KEYWORD, diff --git a/src/include/usr/spd/spdreasoncodes.H b/src/include/usr/spd/spdreasoncodes.H index d1c128100..9fb5515e4 100644 --- a/src/include/usr/spd/spdreasoncodes.H +++ b/src/include/usr/spd/spdreasoncodes.H @@ -52,6 +52,7 @@ enum spdModuleId SPD_READ_BINARY_FILE = 0x04, SPD_WRITE_KEYWORD_VALUE = 0x05, SPD_SPECIAL_CASES = 0x06, + SPD_PRESENCE_DETECT = 0x07, }; /** diff --git a/src/usr/spd/dimmPres.C b/src/usr/spd/dimmPres.C new file mode 100755 index 000000000..57183f650 --- /dev/null +++ b/src/usr/spd/dimmPres.C @@ -0,0 +1,158 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/spd/dimmPres.C $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2012 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +/** + * @file dimmPres.C + * + * @brief Implementation of the DIMM Presence detect. + * + */ + +// ---------------------------------------------- +// Includes +// ---------------------------------------------- +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <targeting/targetservice.H> +#include <devicefw/driverif.H> +#include <spd/spdreasoncodes.H> +#include <spd/spdenums.H> + +#include "spd.H" + +// ---------------------------------------------- +// Globals +// ---------------------------------------------- + +// ---------------------------------------------- +// Trace definitions +// ---------------------------------------------- +extern trace_desc_t * g_trac_spd; + +// ------------------------ +// Macros for unit testing +//#define TRACUCOMP(args...) TRACFCOMP(args) +#define TRACUCOMP(args...) +//#define TRACSSCOMP(args...) TRACFCOMP(args) +#define TRACSSCOMP(args...) + +// ---------------------------------------------- +// Defines +// ---------------------------------------------- + + +namespace SPD +{ + +// Register the Presence detect code with the framework. +DEVICE_REGISTER_ROUTE( DeviceFW::READ, + DeviceFW::PRESENT, + TARGETING::TYPE_DIMM, + dimmPresenceDetect ); + +// ------------------------------------------------------------------ +// dimmPresenceDetect +// ------------------------------------------------------------------ +errlHndl_t dimmPresenceDetect( 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 err = NULL; + bool present = false; + size_t presentSz = sizeof(present); + + TRACSSCOMP( g_trac_spd, + ENTER_MRK"spdPresenceDetect()" ); + + do + { + // Check to be sure that the buffer is big enough. + if( !(io_buflen >= sizeof(bool)) ) + { + TRACFCOMP( g_trac_spd, + ERR_MRK"spdPresenceDetect() - Invalid Data Length: %d", + io_buflen ); + + /*@ + * @errortype + * @reasoncode SPD_INSUFFICIENT_BUFFER_SIZE + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid SPD_PRESENCE_DETECT + * @userdata1 Buffer Length + * @userdata2 <UNUSED> + * @devdesc Buffer for checking Presence Detect was not the correct size. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + SPD_PRESENCE_DETECT, + SPD_INSUFFICIENT_BUFFER_SIZE, + TO_UINT64(io_buflen), + 0x0 ); + + break; + } + + // Read Byte 2 (BASIC_MEMORY_TYPE) for the target passed in. + uint16_t data = 0x0; + size_t dataSz = sizeof(data); + err = spdGetKeywordValue( BASIC_MEMORY_TYPE, + &data, + dataSz, + i_target ); + + if( err ) + { + // If an error is returned, the DIMM is not present. + present = false; + TRACUCOMP( g_trac_spd, + INFO_MRK"Dimm was found to be NOT present." ); + + memcpy( io_buffer, &present, presentSz ); + io_buflen = 0; + + // Delete the error + delete err; + err = NULL; + } + else + { + // DIMM is present... + present = true; + TRACUCOMP( g_trac_spd, + INFO_MRK"Dimm was found to be present." ); + + memcpy( io_buffer, &present, presentSz ); + io_buflen = presentSz; + } + } while( 0 ); + + TRACSSCOMP( g_trac_spd, + EXIT_MRK"spdPresenceDetect()" ); + + return err; +} // end dimmPresenceDetect + + +}; // end namespace SPD diff --git a/src/usr/spd/dimmspd.dat b/src/usr/spd/dimmspd.dat Binary files differindex 8abf344bd..cb4f85c83 100644 --- a/src/usr/spd/dimmspd.dat +++ b/src/usr/spd/dimmspd.dat diff --git a/src/usr/spd/makefile b/src/usr/spd/makefile index dc71eb1c8..9cb0b14cb 100644 --- a/src/usr/spd/makefile +++ b/src/usr/spd/makefile @@ -23,7 +23,7 @@ ROOTPATH = ../../.. MODULE = spd -OBJS = spd.o +OBJS = spd.o dimmPres.o SUBDIRS = test.d diff --git a/src/usr/spd/spd.C b/src/usr/spd/spd.C index 0a1dc5bae..1286385cd 100755 --- a/src/usr/spd/spd.C +++ b/src/usr/spd/spd.C @@ -144,18 +144,18 @@ errlHndl_t spdGetKeywordValue ( uint64_t i_keyword, INFO_MRK"Mem Type: %04x", memType ); - // If the user wanted the Basic Memory Type, return this now - if( BASIC_MEMORY_TYPE == i_keyword ) - { - io_buflen = MEM_TYPE_ADDR_SZ; - memcpy( io_buffer, &memType, io_buflen ); - break; - } - // Check the Basic Memory Type to be sure its valid before // continuing. if( SPD_DDR3 == memType ) { + // If the user wanted the Basic memory type, return this now. + if( BASIC_MEMORY_TYPE == i_keyword ) + { + io_buflen = MEM_TYPE_ADDR_SZ; + memcpy( io_buffer, &memType, io_buflen ); + break; + } + // Read the keyword value err = spdGetValue( i_keyword, io_buffer, @@ -596,13 +596,6 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword, if( err ) break; - // Mask and shift if needed - if( ddr3Data[i_entry].useBitMask ) - { - tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; - tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; - } - // Get LSB err = spdFetchData( 0x18, 1, /* Read 1 byte at a time */ @@ -659,7 +652,6 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword, // Byte 0x75 [7:0] // Byte 0x76 [7:0] - MSB - // Check size of buffer err = spdCheckSize( io_buflen, 2, @@ -675,13 +667,6 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword, if( err ) break; - // Mask and shift if needed - if( ddr3Data[i_entry].useBitMask ) - { - tmpBuffer[0] = tmpBuffer[0] & ddr3Data[i_entry].bitMask; - tmpBuffer[0] = tmpBuffer[0] >> ddr3Data[i_entry].shift; - } - // Get LSB err = spdFetchData( 0x75, 1, /* Read 1 byte at a time */ @@ -694,6 +679,38 @@ errlHndl_t spdSpecialCases ( uint64_t i_keyword, io_buflen = 2; break; + case DRAM_MANUFACTURER_ID: + // Length 2 bytes + // Byte 0x94 [7:0] + // Byte 0x95 [7:0] - MSB + + // Check size of buffer + err = spdCheckSize( io_buflen, + 2, + i_keyword ); + + if( err ) break; + + // Get MSB + err = spdFetchData( ddr3Data[i_entry].offset, + 1, /*Read 1 byte at a time */ + &tmpBuffer[0], + i_target ); + + if( err ) break; + + // Get LSB + err = spdFetchData( 0x94, + 1, /* Read 1 byte at a time */ + &tmpBuffer[1], + i_target ); + + if( err ) break; + + // Set number of bytes read + io_buflen = 2; + break; + default: TRACFCOMP( g_trac_spd, ERR_MRK"Unknown keyword (0x%04x) for DDR3 special cases!", diff --git a/src/usr/spd/spd.H b/src/usr/spd/spd.H index 81da52888..087d3353e 100755 --- a/src/usr/spd/spd.H +++ b/src/usr/spd/spd.H @@ -256,6 +256,36 @@ errlHndl_t spdReadBinaryFile ( uint64_t i_byteAddr, size_t i_numBytes, void * o_data ); +/** + * @brief This function performs the presence detect for all DIMMs. + * + * @param[in] i_opType - Operation type, see DeviceFW::OperationType + * in driverif.H + * + * @param[in] i_target - The target to query. + * + * @param[in/out] io_buffer - Buffer to contain the boolean for presence + * detect. + * + * @param[in/out] io_buflen - Size of buffer provided for doing the presence + * detect. Will always be 1. If size returned equals 0, the request + * failed. + * + * @param[in] i_accessType - DeviceFW::AccessType enum. + * + * @param[in] i_args - An arguement for the Device Driver framework. There + * are no args for this function. + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ +errlHndl_t dimmPresenceDetect( DeviceFW::OperationType i_opType, + TARGETING::Target * i_target, + void * io_buffer, + size_t & io_buflen, + int64_t i_accessType, + va_list i_args ); + }; // end SPD namespace #endif // __SPD_H diff --git a/src/usr/spd/spdDDR3.H b/src/usr/spd/spdDDR3.H index 4b36b40a9..57e66eabc 100755 --- a/src/usr/spd/spdDDR3.H +++ b/src/usr/spd/spdDDR3.H @@ -114,8 +114,9 @@ KeywordData ddr3Data[] = { MODULE_CRC, 0x7e, 0x02, false, 0x00, 0x00, false }, { MODULE_PART_NUMBER, 0x80, 0x12, false, 0x00, 0x00, false }, { MODULE_REVISION_CODE, 0x92, 0x02, false, 0x00, 0x00, false }, - { DRAM_MANUFACTURER_ID, 0x94, 0x02, false, 0x00, 0x00, false }, + { DRAM_MANUFACTURER_ID, 0x95, 0x02, false, 0x00, 0x00, true }, { MANUFACTURER_SPECIFIC_DATA, 0x96, 0x1a, false, 0x00, 0x00, false }, + { DIMM_BAD_DQ_DATA, 0xb0, 0x50, false, 0x00, 0x00, false }, // ---------------------------------------------------------------------------------- }; diff --git a/src/usr/spd/test/dimmPrestest.H b/src/usr/spd/test/dimmPrestest.H new file mode 100755 index 000000000..46dad62c5 --- /dev/null +++ b/src/usr/spd/test/dimmPrestest.H @@ -0,0 +1,202 @@ +// IBM_PROLOG_BEGIN_TAG +// This is an automatically generated prolog. +// +// $Source: src/usr/spd/test/dimmPrestest.H $ +// +// IBM CONFIDENTIAL +// +// COPYRIGHT International Business Machines Corp. 2012 +// +// p1 +// +// Object Code Only (OCO) source materials +// Licensed Internal Code Source Materials +// IBM HostBoot Licensed Internal Code +// +// The source code for this program is not published or other- +// wise divested of its trade secrets, irrespective of what has +// been deposited with the U.S. Copyright Office. +// +// Origin: 30 +// +// IBM_PROLOG_END +#ifndef __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/predicates/predicatectm.H> + +#include <spd/spdreasoncodes.H> +#include <spd/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; + } + + for( uint32_t dimm = 0; dimm < dimmList.size(); dimm++ ) + { + cmds++; + theTarget = dimmList[dimm]; + + // 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, + SPD_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. + } + } + + if( err ) + { + break; + } + } 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; + } + + for( uint32_t dimm = 0; dimm < dimmList.size(); dimm++ ) + { + cmds++; + theTarget = dimmList[dimm]; + + // Check presence + err = deviceRead( theTarget, + &present, + presentSize, + DEVICE_PRESENT_ADDRESS() ); + + if( !err ) + { + fails++; + TS_FAIL( "testDimmPresInvalidSize() - Error not flagged for " + "invalid size!" ); + errlCommit( err, + SPD_COMP_ID ); + continue; + } + else + { + // Delete the error and continue + delete err; + err = NULL; + continue; + } + } + + if( err ) + { + break; + } + } while( 0 ); + + TRACFCOMP( g_trac_spd, + "testDimmPresInvalidSize() - %d/%d fails", + fails, cmds ); + } + + +}; + +#endif diff --git a/src/usr/spd/test/spdtest.H b/src/usr/spd/test/spdtest.H index 3fdf86da7..351e3d846 100755 --- a/src/usr/spd/test/spdtest.H +++ b/src/usr/spd/test/spdtest.H @@ -62,7 +62,7 @@ void getDIMMTargets ( TargetHandleList & o_dimmList ) TARGETING::TargetService::CHILD, TARGETING::TargetService::ALL, &predDimm ); - TRACFCOMP( g_trac_spd, + TRACDCOMP( g_trac_spd, "getDIMMTargets() - found %d DIMMs", o_dimmList.size() ); return; |