diff options
author | Elliott Dahle <dedahle@us.ibm.com> | 2013-07-22 11:07:23 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-07-30 14:44:28 -0500 |
commit | 9319829a92387bc15ab63a5a90710a518e43a453 (patch) | |
tree | 3d3818c368d9cc78ad77f832c7e6a8cc94176d98 /src/usr/hwpf/hwp | |
parent | c600aad20e783024b998a52d17d9d4650b9005a0 (diff) | |
download | talos-hostboot-9319829a92387bc15ab63a5a90710a518e43a453.tar.gz talos-hostboot-9319829a92387bc15ab63a5a90710a518e43a453.zip |
Access Bad DQ via ATTR_BAD_DQ_BITMAP and show unconnected DQs
Change-Id: Id703749de7c08aef337904a2dccac3af2e90a108
RTC: 72937
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5510
Reviewed-by: Brian H. Horton <brianh@linux.ibm.com>
Tested-by: Jenkins Server
Reviewed-by: William H. Schwartz <whs@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf/hwp')
-rw-r--r-- | src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C | 220 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C | 30 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dimm_spd_attributes.xml | 64 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/fapiTestHwpDq.C | 104 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C | 210 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk | 3 |
6 files changed, 507 insertions, 124 deletions
diff --git a/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C b/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C index 8b3f879ed..439f21ce0 100644 --- a/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C +++ b/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C @@ -33,6 +33,7 @@ * mjjones 02/17/2012 Created. * mjjones 01/30/2013 Cope with platform endian * differences + * dedahle 06/22/2013 Show unconnected DQ lines */ #include <dimmBadDqBitmapAccessHwp.H> @@ -40,6 +41,8 @@ // DQ Data format in DIMM SPD const uint32_t DIMM_BAD_DQ_MAGIC_NUMBER = 0xbadd4471; const uint8_t DIMM_BAD_DQ_VERSION = 1; +const uint8_t ECC_DQ_BYTE_NUMBER_INDEX = 8; +const uint8_t SPARE_DRAM_DQ_BYTE_NUMBER_INDEX = 9; struct dimmBadDqDataFormat { @@ -51,6 +54,83 @@ struct dimmBadDqDataFormat uint8_t iv_bitmaps[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]; }; + +extern "C" +{ + +/** + * @brief Called by dimmBadDqBitmapAccessHwp() to query ATR_VPD_DIMM_SPARE + * and set bits for unconnected spare DRAM in caller's data. + * + * + * @param[in] i_dimm Reference to DIMM Target. + * @param[o] o_data Reference to Bad DQ Bitmap set by + * the caller. Only the SPARE_DRAM_DQ_BYTE_NUMBER_INDEX + * byte is modified by this function. + * + * @return ReturnCode + */ + +fapi::ReturnCode dimmUpdateDqBitmapSpareByte( + const fapi::Target & i_dimm, + uint8_t (&o_data)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]) +{ + fapi::ReturnCode l_rc; + + do + { + // Spare DRAM Attribute + uint8_t l_dimmSpare = 0; + l_rc = FAPI_ATTR_GET(ATTR_VPD_DIMM_SPARE, &i_dimm, l_dimmSpare); + if (l_rc) + { + FAPI_ERR("dimmCheckSpareDram: " + "Error getting DRAM Spare data"); + break; + } + + // Bitmask and beginning bit shift values for decoding + // ATTR_VPD_DIMM_SPARE attribute as described in + // dimm_spd_attributes.xml. + uint8_t l_dimmMask = 0xC0; + uint8_t l_rankBitShift = 6; + + // Iterate through each rank of this DIMM + for (uint8_t i = 0; i < DIMM_DQ_MAX_DIMM_RANKS; i++) + { + // Handle spare DRAM configuration cases + switch ((l_dimmSpare & l_dimmMask) >> l_rankBitShift) + { + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE: + // Set DQ bits reflecting unconnected + // spare DRAM in caller's data + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0xFF; + break; + + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE: + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0x0F; + break; + + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_HIGH_NIBBLE: + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0xF0; + break; + + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE: + // As erroneous value will not be encountered. + default: + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0x00; + break; + } + + l_dimmMask >>= 2; + l_rankBitShift -= 2; + } + }while(0); + return l_rc; +} + +} + extern "C" { @@ -82,20 +162,26 @@ fapi::ReturnCode dimmBadDqBitmapAccessHwp( *(reinterpret_cast<uint8_t(*)[DIMM_DQ_SPD_DATA_SIZE]> (new uint8_t[DIMM_DQ_SPD_DATA_SIZE])); + // Memory Bus Width Attribute + uint8_t l_eccBits = 0; + dimmBadDqDataFormat * l_pSpdData = reinterpret_cast<dimmBadDqDataFormat *>(l_spdData); // Get the Centaur DQ to DIMM Connector DQ Wiring attribute. Note that for // C-DIMMs, this will return a simple 1:1 mapping. This code cannot tell // the difference between C-DIMMs and IS-DIMMs - l_rc = FAPI_ATTR_GET(ATTR_CEN_DQ_TO_DIMM_CONN_DQ, &i_dimm, l_wiringData); - - if (l_rc) - { - FAPI_ERR("dimmBadDqBitmapAccessHwp: Error getting wiring attribute"); - } - else + do { + l_rc = FAPI_ATTR_GET(ATTR_CEN_DQ_TO_DIMM_CONN_DQ, + &i_dimm, l_wiringData); + + if (l_rc) + { + FAPI_ERR("dimmBadDqBitmapAccessHwp: " + "Error getting wiring attribute"); + break; + } if (i_get) { // Get the SPD DQ attribute @@ -104,62 +190,96 @@ fapi::ReturnCode dimmBadDqBitmapAccessHwp( if (l_rc) { FAPI_ERR("dimmBadDqBitmapAccessHwp: Error getting SPD data"); + break; + } + // Zero caller's data + memset(io_data, 0, sizeof(io_data)); + // Check the magic number and version number. Note that the + // magic number is stored in SPD in big endian format and + // platforms of any endianness can access it + if ((FAPI_BE32TOH(l_pSpdData->iv_magicNumber) != + DIMM_BAD_DQ_MAGIC_NUMBER) || + (l_pSpdData->iv_version != DIMM_BAD_DQ_VERSION)) + { + FAPI_INF("dimmBadDqBitmapAccessHwp: SPD DQ not initialized"); } else { - // Zero caller's data - memset(io_data, 0, sizeof(io_data)); - - // Check the magic number and version number. Note that the - // magic number is stored in SPD in big endian format and - // platforms of any endianness can access it - if ((FAPI_BE32TOH(l_pSpdData->iv_magicNumber) != - DIMM_BAD_DQ_MAGIC_NUMBER) || - (l_pSpdData->iv_version != DIMM_BAD_DQ_VERSION)) - { - // SPD DQ data not initialized, return zeros - FAPI_INF("dimmBadDqBitmapAccessHwp: SPD DQ not initialized"); - } - else + // Translate bitmap from DIMM DQ to Centaur DQ point of view + // for each rank + for (uint8_t i = 0; i < DIMM_DQ_MAX_DIMM_RANKS; i++) { - // Translate bitmap from DIMM DQ to Centaur DQ point of view - // for each rank - for (uint8_t i = 0; i < DIMM_DQ_MAX_DIMM_RANKS; i++) + // Iterate through all the DQ bits in the rank + for (uint8_t j = 0; j < DIMM_DQ_NUM_DQS; j++) { - // Iterate through all the DQ bits in the rank - for (uint8_t j = 0; j < DIMM_DQ_NUM_DQS; j++) + // There is a byte for each 8 DQs, j/8 gives the + // byte number. The MSB in each byte is the lowest + // DQ, (0x80 >> (j % 8)) gives the bit mask + // corresponding to the DQ within the byte + if ((l_pSpdData->iv_bitmaps[i][j/8]) & + (0x80 >> (j % 8))) { - // There is a byte for each 8 DQs, j/8 gives the - // byte number. The MSB in each byte is the lowest - // DQ, (0x80 >> (j % 8)) gives the bit mask - // corresponding to the DQ within the byte - if ((l_pSpdData->iv_bitmaps[i][j/8]) & - (0x80 >> (j % 8))) + // DIMM DQ bit is set in SPD data. + // Set Centaur DQ bit in caller's data. + // The wiring data maps Centaur DQ to DIMM DQ + // Find the Centaur DQ that maps to this DIMM DQ + uint8_t k = 0; + for (; k < DIMM_DQ_NUM_DQS; k++) { - // DIMM DQ bit is set in SPD data. - // Set Centaur DQ bit in caller's data. - // The wiring data maps Centaur DQ to DIMM DQ - // Find the Centaur DQ that maps to this DIMM DQ - uint8_t k = 0; - for (; k < DIMM_DQ_NUM_DQS; k++) + if (l_wiringData[k] == j) { - if (l_wiringData[k] == j) - { - io_data[i][k/8] |= (0x80 >> (k % 8)); - break; - } + io_data[i][k/8] |= (0x80 >> (k % 8)); + break; } + } - if (k == DIMM_DQ_NUM_DQS) - { - FAPI_ERR("dimmBadDqBitmapAccessHwp: Centaur DQ not found for %d!", - j); - } + if (k == DIMM_DQ_NUM_DQS) + { + FAPI_INF("dimmBadDqBitmapAccessHwp: " + "Centaur DQ not found for %d!",j); } } } } } + // Set bits for any unconnected DQs. + // First, check ECC. + l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_MEMORY_BUS_WIDTH, + &i_dimm, l_eccBits); + if (l_rc) + { + FAPI_ERR("dimmBadDqBitmapAccessHwp: " + "Error getting ECC data"); + break; + } + + // The ATTR_SPD_MODULE_MEMORY_BUS_WIDTH contains ENUM values + // for bus widths of 8, 16, 32, and 64 bits both with ECC + // and without ECC. WExx ENUMS deonote the ECC extension + // is present, and all have bit 3 set. Therefore, + // it is only required to check against the WE8 = 0x08 ENUM + // value in order to determine if ECC lines are present. + + // If ECCs are disconnected + if (!(fapi::ENUM_ATTR_SPD_MODULE_MEMORY_BUS_WIDTH_WE8 & + l_eccBits)) + { + // Iterate through each rank and set DQ bits in + // caller's data. + for (uint8_t i = 0; i < DIMM_DQ_MAX_DIMM_RANKS; i++) + { + // Set DQ bits in caller's data + io_data[i][ECC_DQ_BYTE_NUMBER_INDEX] = 0xFF; + } + } + // Check spare DRAM + l_rc = dimmUpdateDqBitmapSpareByte(i_dimm, io_data); + if (l_rc) + { + FAPI_ERR("dimmBadDqBitmapAccessHwp: " + "Error getting spare DRAM data"); + break; + } } else { @@ -196,13 +316,13 @@ fapi::ReturnCode dimmBadDqBitmapAccessHwp( if (l_rc) { FAPI_ERR("dimmBadDqBitmapAccessHwp: Error setting SPD data"); + break; } } - } + }while(0); delete [] &l_wiringData; delete [] &l_spdData; - FAPI_INF("<<dimmBadDqBitmapAccessHwp"); return l_rc; } diff --git a/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C b/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C index 788ee3223..67a4f5640 100644 --- a/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C +++ b/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C @@ -31,6 +31,9 @@ * Flag Defect/Feature User Date Description * ------ -------------- ---------- ----------- ---------------------------- * mjjones 02/17/2012 Created. + * dedahle 06/20/2013 dimmGetBadDqBitmap/ + * dimmSetBadDqBitmap funcs + * get/set ATTR_BAD_DQ_BITMAP */ #include <dimmBadDqBitmapFuncs.H> @@ -39,16 +42,6 @@ extern "C" { -// TODO -// For the dimmGetBadDqBitmap and dimmSetBadDqBitmap funcs, the original plan to -// get/set the bitmap was to get/set a HWPF attribute called ATTR_BAD_DQ_BITMAP. -// This would automatically call the dimmBadDqBitmapAccessHwp HWP which would -// access the ATTR_SPD_BAD_DQ_DATA HWPF attribute and decode the data. However, -// automatically bridging an attribute request to a HWP turns out to be -// difficult due to the fact that the FAPI_ATTR_GET macro returns a ReturnCode -// and the FAPI_EXEC_HWP macro takes a ReturnCode as parameter. For now call the -// HWP directly and revisit later - //------------------------------------------------------------------------------ // Utility function to check parameters and find a DIMM target @@ -158,20 +151,21 @@ fapi::ReturnCode dimmGetBadDqBitmap(const fapi::Target & i_mba, if (!l_rc) { - // Get the Bad DQ bitmap by calling the dimmBadDqBitmapAccessHwp HWP. + // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP. // Use a heap based array to avoid large stack alloc uint8_t (&l_dqBitmap)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE] = *(reinterpret_cast<uint8_t(*)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]> (new uint8_t[DIMM_DQ_MAX_DIMM_RANKS*DIMM_DQ_RANK_BITMAP_SIZE])); - FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, l_dimm, l_dqBitmap, true); + l_rc = FAPI_ATTR_GET(ATTR_BAD_DQ_BITMAP, &l_dimm, l_dqBitmap); if (l_rc) { - FAPI_ERR("dimmGetBadDqBitmap: Error from dimmBadDqBitmapAccessHwp"); + FAPI_ERR("dimmGetBadDqBitmap: Error getting ATTR_BAD_DQ_BITMAP for dimm"); } else { + //Write contents of DQ bitmap for specific rank to o_data. memcpy(o_data, l_dqBitmap[i_rank], DIMM_DQ_RANK_BITMAP_SIZE); } @@ -200,28 +194,28 @@ fapi::ReturnCode dimmSetBadDqBitmap( if (!l_rc) { - // Get the Bad DQ bitmap by calling the dimmBadDqBitmapAccessHwp HWP. + // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP. // Use a heap based array to avoid large stack alloc uint8_t (&l_dqBitmap)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE] = *(reinterpret_cast<uint8_t(*)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]> (new uint8_t[DIMM_DQ_MAX_DIMM_RANKS*DIMM_DQ_RANK_BITMAP_SIZE])); - FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, l_dimm, l_dqBitmap, true); + l_rc = FAPI_ATTR_GET(ATTR_BAD_DQ_BITMAP, &l_dimm, l_dqBitmap); if (l_rc) { - FAPI_ERR("dimmSetBadDqBitmap: Error from dimmBadDqBitmapAccessHwp (get)"); + FAPI_ERR("dimmSetBadDqBitmap: Error getting ATTR_BAD_DQ_BITMAP for dimm"); } else { // Add the rank bitmap to the DIMM bitmap and write the bitmap memcpy(l_dqBitmap[i_rank], i_data, DIMM_DQ_RANK_BITMAP_SIZE); - FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, l_dimm, l_dqBitmap, false); + l_rc = FAPI_ATTR_SET(ATTR_BAD_DQ_BITMAP, &l_dimm, l_dqBitmap); if (l_rc) { - FAPI_ERR("dimmSetBadDqBitmap: Error from dimmBadDqBitmapAccessHwp (set)"); + FAPI_ERR("dimmSetBadDqBitmap: Error setting ATTR_BAD_DQ_BITMAP for dimm"); } } diff --git a/src/usr/hwpf/hwp/dimm_spd_attributes.xml b/src/usr/hwpf/hwp/dimm_spd_attributes.xml index 12eea1672..38d50c5f6 100644 --- a/src/usr/hwpf/hwp/dimm_spd_attributes.xml +++ b/src/usr/hwpf/hwp/dimm_spd_attributes.xml @@ -485,10 +485,11 @@ The following attributes can be queried from both DDR3 and DDR4 DIMMs <id>ATTR_SPD_BAD_DQ_DATA</id> <targetType>TARGET_TYPE_DIMM</targetType> <description> - Bad DQ pin data stored in DIMM SPD. This data is in a special format. - This must only be called by a firmware HWP that knows how to decode the data. - HWP/PLAT firmware that needs to get/set the Bad DQ Bitmap from a Centaur - DQ point of view must call the dimmBadDqBitmapAccessHwp HWP. + Bad DQ pin data stored in DIMM SPD. This data is in a special fomat. + This must only be called by a firmware HWP that knows how to + decode the data. HWP/PLAT firmware that needs to get/set the + Bad DQ Bitmap from a Centaur DQ point of view must use the + ATTR_BAD_DQ_BITMAP attribute. </description> <valueType>uint8</valueType> <array>80</array> @@ -1298,4 +1299,59 @@ file </attribute> --> + +<attribute> + <id>ATTR_BAD_DQ_BITMAP</id> + <targetType>TARGET_TYPE_DIMM</targetType> + <description> + Bad DQ bitmap from a Centaur:MBA point of view. + The data is a 10 byte bitmap for each of 4 possible ranks. + The bad DQ data is stored in DIMM SPD, it is stored in a special format + and is translated to a DIMM Connector point of view for IS-DIMMs. + All of these details are hidden from the user of this attribute. + </description> + <valueType>uint8</valueType> + <array>4 10</array> + <platInit/> + <writeable/> +</attribute> + +<attribute> + <id>ATTR_VPD_DIMM_SPARE</id> + <targetType>TARGET_TYPE_DIMM</targetType> + <description> + Spare DRAM availability for each rank on the DIMM. + There are 8 DQ lines to spare DRAMs. + - NO_SPARE: No spare DRAMs + - LOW_NIBBLE: x4 DRAMs in use, one spare DRAM connected to SP_DQ0-3 + - HIGH_NIBBLE: x4 DRAMs in use, one spare DRAM connected to SP_DQ4-7 + - FULL_BYTE: Either + 1/ x4 DRAMs in use, two spare DRAMs connected to SP_DQ0-7 + 2/ x8 DRAMs in use, one spare DRAM connected to SP_DQ0-7 + For C-DIMMs, this is in a VPD field : Record:VSPD, Keyword:AM + For IS-DIMMs, the platform should return 0 indicating + no spares for any rank. + The top 2 bits are for rank 0 e.g: + if (((val AND 0xc0) >> 6) == + ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE) {...} + The next 2 bits are for rank 1 e.g: + if (((val AND 0x30) >> 4) == + ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE) {...} + The next 2 bits are for rank 2 e.g: + if (((val AND 0x0c) >> 2) == + ENUM_ATTR_VPD_DIMM_SPARE_HIGH_NIBBLE) {...} + The bottom 2 bits are for rank 3 e.g: + if ((val AND 0x03) == + ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE) {...} + </description> + <valueType>uint8</valueType> + <enum> + NO_SPARE = 0x00, + LOW_NIBBLE = 0x01, + HIGH_NIBBLE = 0x02, + FULL_BYTE = 0x03 + </enum> + <platInit/> +</attribute> + </attributes> diff --git a/src/usr/hwpf/hwp/fapiTestHwpDq.C b/src/usr/hwpf/hwp/fapiTestHwpDq.C index 9ea23ec89..6fadbe27d 100644 --- a/src/usr/hwpf/hwp/fapiTestHwpDq.C +++ b/src/usr/hwpf/hwp/fapiTestHwpDq.C @@ -1,26 +1,25 @@ -/* IBM_PROLOG_BEGIN_TAG - * This is an automatically generated prolog. - * - * $Source: src/usr/hwpf/hwp/fapiTestHwpDq.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_TAG - */ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/fapiTestHwpDq.C $ */ +/* */ +/* 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 */ /** * @file fapiTestHwpDq.C * @@ -102,48 +101,51 @@ fapi::ReturnCode fapiTestHwpDq(const fapi::Target & i_mba) break; } - // Get the bad DQ Bitmap for the DIMM, rank 3 - l_rc = dimmGetBadDqBitmap(i_mba, l_port, l_dimm, 3, l_dqBitmap); - - if (l_rc) + // Get the bad DQ Bitmap for all ranks and print any non-zero data + uint8_t l_rank = 0; + for (l_rank = 0; l_rank < 3; l_rank++) { - FAPI_ERR("fapiTestHwpDq: Error from dimmGetBadDqBitmap"); - break; - } - - // If the data is not all zeroes then skip the rest of the test, do not - // want to modify any real Bad DQ records - bool l_nonZeroData = false; + // Get the bad DQ Bitmap for the rank + l_rc = dimmGetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, + l_dqBitmap); - for (uint8_t i = 0; i < DIMM_DQ_RANK_BITMAP_SIZE; i++) - { - if (l_dqBitmap[i] != 0) + if (l_rc) { - FAPI_INF("fapiTestHwpDq: Non-zero DQ data, skipping test"); - l_nonZeroData = true; + FAPI_ERR("fapiTestHwpDq: Error from dimmGetBadDqBitmap"); break; } + + // Trace any bad DQs + for (uint8_t i = 0; i < DIMM_DQ_RANK_BITMAP_SIZE; i++) + { + if (l_dqBitmap[i] != 0) + { + FAPI_INF("fapiTestHwpDq: Non-zero DQ data. Rank:%d, Byte:%d, Val:0x02%x", + l_rank, i, l_dqBitmap[i]); + } + } } - if (l_nonZeroData) + if (l_rc) { break; } + // Record the two bytes of the bad DQ bitmap that this function + // will change so that it can be restored + uint8_t l_origDq2 = l_dqBitmap[2]; + uint8_t l_origDq6 = l_dqBitmap[6]; + // Set 2 bad DQ bits l_dqBitmap[2] = 0x40; l_dqBitmap[6] = 0x20; - // Set the bad DQ Bitmap - l_rc = dimmSetBadDqBitmap(i_mba, 1, 0, 3, l_dqBitmap); + // Set the bad DQ Bitmap for the last rank + l_rc = dimmSetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, l_dqBitmap); if (l_rc) { FAPI_ERR("fapiTestHwpDq: Error from dimmSetBadDqBitmap"); - - // TODO - FAPI_ERR("fapiTestHwpDq: Waiting for SPD DD support for writes (story 35766)"); - l_rc = fapi::FAPI_RC_SUCCESS; break; } @@ -151,7 +153,7 @@ fapi::ReturnCode fapiTestHwpDq(const fapi::Target & i_mba) l_dqBitmap[2] = 0; l_dqBitmap[6] = 0; - l_rc = dimmGetBadDqBitmap(i_mba, 1, 0, 3, l_dqBitmap); + l_rc = dimmGetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, l_dqBitmap); if (l_rc) { @@ -169,11 +171,11 @@ fapi::ReturnCode fapiTestHwpDq(const fapi::Target & i_mba) break; } - // Write the data back to zero - l_dqBitmap[2] = 0; - l_dqBitmap[6] = 0; + // Write the original data back + l_dqBitmap[2] = l_origDq2; + l_dqBitmap[6] = l_origDq6; - l_rc = dimmSetBadDqBitmap(i_mba, 1, 0, 3, l_dqBitmap); + l_rc = dimmSetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, l_dqBitmap); if (l_rc) { diff --git a/src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C b/src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C new file mode 100644 index 000000000..665a9e76c --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C @@ -0,0 +1,210 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 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 */ +#include <stdint.h> + +// fapi support +#include <fapi.H> +#include <dimmConsts.H> +#include <getMBvpdSpareDramData.H> + +extern "C" +{ +using namespace fapi; + +fapi::ReturnCode getMBvpdSpareDramData(const fapi::Target &i_mba, + const fapi::Target &i_dimm, + uint8_t &o_data) + +{ + // AM keyword layout + const uint8_t NUM_MBAS = 2; // Two MBAs per Centaur + const uint8_t NUM_PORTS = 2; // Two ports per MBA + const uint8_t NUM_DIMMS = 2; // Two DIMMS per port + const uint8_t NUM_MIRR_BYTES = 4; // Size of address mirror data + + // Struct for AM Keyword buffer + // Contains a simple array for the address mirror data and + // a 2D array for the spare DRAM data. + struct MirrorData + { + uint8_t iv_mirrorData[NUM_MIRR_BYTES]; + }; + struct DimmSpareData + { + // This contains information for all ranks and is returned in o_data + uint8_t iv_dimmSpareData; + }; + struct PortSpareData + { + DimmSpareData iv_dimmSpareData[NUM_DIMMS]; + }; + struct MbaSpareData + { + PortSpareData iv_portSpareData[NUM_PORTS]; + }; + struct AmKeyword + { + MirrorData mirrorData; + MbaSpareData iv_mbaSpareData[NUM_MBAS]; + }; + + // Old VPD without the Spare Data + const uint8_t VPD_WITHOUT_SPARE_DATA_SIZE = sizeof(MirrorData); + + // Current VPD AM keyword size + const uint32_t AM_KEYWORD_SIZE = sizeof(AmKeyword); + fapi::ReturnCode l_rc; + // Centaur target + fapi::Target l_mbTarget; + // MBvpd AM keyword buffer + AmKeyword * l_pAmBuffer = NULL; + uint32_t l_AmBufSize = sizeof(AmKeyword); + + do + { + // Check to see if IS-DIMM + uint8_t l_dimmType = 0; + l_rc = FAPI_ATTR_GET(ATTR_SPD_CUSTOM, &i_dimm, l_dimmType); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting ATTR_SPD_CUSTOM"); + break; + } + if (fapi::ENUM_ATTR_SPD_CUSTOM_NO == l_dimmType) + { + //IS-DIMM, return NO_SPARE + o_data = fapi::ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE; + break; + } + + // find the Centaur memory buffer from the passed MBA + l_rc = fapiGetParentChip (i_mba,l_mbTarget); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: Finding the parent mb failed "); + break; + } + + // Read AM keyword field + l_pAmBuffer = new AmKeyword; + l_rc = fapiGetMBvpdField(fapi::MBVPD_RECORD_VSPD, + fapi::MBVPD_KEYWORD_AM, + l_mbTarget, + reinterpret_cast<uint8_t *>(l_pAmBuffer), + l_AmBufSize); + + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: Read of AM keyword failed"); + break; + } + + // Check correct amount of data returned + if (l_AmBufSize < AM_KEYWORD_SIZE) + { + + // If Old VPD + if (VPD_WITHOUT_SPARE_DATA_SIZE == l_AmBufSize) + { + // Because prior VPD AM keyword does not contain + // spare DRAM data, the ATTR_SPD_DRAM_WIDTH + // attribute is used to determine spare DRAM availability. + // If x4 configuration, assume LOW_NIBBLE. + // Otherwise, FULL_BYTE. + uint8_t l_dramWidth = 0; + l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_WIDTH, &i_dimm, l_dramWidth); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting DRAM spare data"); + break; + } + // If x4 configuration, low nibble. + if (fapi::ENUM_ATTR_SPD_DRAM_WIDTH_W4 == l_dramWidth) + { + o_data = fapi::ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE; + break; + } + // Else, full spare. + else + { + o_data = fapi::ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE; + break; + } + } + + else + { + FAPI_ERR("getMBvpdSpareDramData: " + "Insufficient amount of data returned:" + " %u < %u", l_AmBufSize, AM_KEYWORD_SIZE); + const uint32_t & KEYWORD = fapi::MBVPD_KEYWORD_AM; + const uint32_t & RETURNED_SIZE = l_AmBufSize; + FAPI_SET_HWP_ERROR(l_rc, + RC_MBVPD_INSUFFICIENT_VPD_RETURNED); + break; + } + } + + + // Return the spare DRAM availability for particular dimm + // Find the position of the passed mba on the centuar + uint8_t l_mba = 0; + l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_mba, l_mba); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: Get MBA position failed "); + break; + } + // Find the mba port this dimm is connected to + uint8_t l_mbaPort = 0; + l_rc = FAPI_ATTR_GET(ATTR_MBA_PORT, &i_dimm, l_mbaPort); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting MBA port number"); + break; + } + // Find the dimm number associated with this dimm + uint8_t l_dimm = 0; + l_rc = FAPI_ATTR_GET(ATTR_MBA_DIMM, &i_dimm, l_dimm); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting dimm number"); + break; + } + + o_data = l_pAmBuffer->iv_mbaSpareData[l_mba].\ + iv_portSpareData[l_mbaPort].\ + iv_dimmSpareData[l_dimm].iv_dimmSpareData; + + }while(0); + + delete l_pAmBuffer; + l_pAmBuffer = NULL; + return l_rc; +} + +} // extern "C" diff --git a/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk b/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk index 19ea33724..0f598f554 100644 --- a/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk +++ b/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk @@ -32,5 +32,6 @@ OBJS += getMvpdRing.o \ getMBvpdPhaseRotatorData.o \ getMBvpdAddrMirrorData.o \ getMBvpdTermData.o \ - getMBvpdSlopeInterceptData.o + getMBvpdSlopeInterceptData.o \ + getMBvpdSpareDramData.o |