summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/hwp
diff options
context:
space:
mode:
authorElliott Dahle <dedahle@us.ibm.com>2013-07-22 11:07:23 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2013-07-30 14:44:28 -0500
commit9319829a92387bc15ab63a5a90710a518e43a453 (patch)
tree3d3818c368d9cc78ad77f832c7e6a8cc94176d98 /src/usr/hwpf/hwp
parentc600aad20e783024b998a52d17d9d4650b9005a0 (diff)
downloadtalos-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.C220
-rw-r--r--src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C30
-rw-r--r--src/usr/hwpf/hwp/dimm_spd_attributes.xml64
-rw-r--r--src/usr/hwpf/hwp/fapiTestHwpDq.C104
-rw-r--r--src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C210
-rw-r--r--src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk3
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
OpenPOWER on IntegriCloud