/* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ /* $Source: src/usr/hwpf/hwp/utility_procedures/mss_maint_cmds.C $ */ /* */ /* IBM CONFIDENTIAL */ /* */ /* COPYRIGHT International Business Machines Corp. 2013,2014 */ /* */ /* 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 */ // $Id: mss_maint_cmds.C,v 1.35 2014/04/07 18:58:03 gollub Exp $ //------------------------------------------------------------------------------ // Don't forget to create CVS comments when you check in your changes! //------------------------------------------------------------------------------ // CHANGE HISTORY: //------------------------------------------------------------------------------ // Version:| Date: | Author: | Comment: //---------|----------|---------|----------------------------------------------- // | 11/02/11 | gollub | Created // | 12/01/11 | gollub | Fixed problem with end address // | 03/30/12 | gollub | Made stop condition parm into a mask. // | | | Added support for both MBAs // | | | Calculate real start/end address, but run on 2 // | | | addresses if sim // | 04/25/12 | gollub | Updated error paths // | 05/23/12 | gollub | Updates from review. // | 07/13/12 | gollub | Updates from review. // 1.8 | 07/16/12 | bellows | added in Id tag // 1.9 | 07/18/12 | gollub | Updates from review. // | | | Updates for timebase scrub. // 1.10 | 07/24/12 | gollub | Fix UE/SUE status bit swap in MBMACA // | | | Added stop condition enums // | | | STOP_IMMEDIATE // | | | ENABLE_CMD_COMPLETE_ATTENTION_ON_CLEAN_AND_ERROR // | | | Now require cleanupCmd() for super fast read // | | | to disable rrq fifo mode when done. // 1.11 | 09/07/12 | gollub | Updates from review. // | | | Support for more patterns. // 1.12 | 09/29/12 | gollub | Added mss_restore_DRAM_repairs // 1.13 | 10/08/12 | gollub | Updated with 12h scrub rate calculation // 1.14 | 11/02/12 | gollub | Updates from review. // 1.15 | 11/08/12 | gollub | Added timebase steer cleanup // | | | Updates to traces. // 1.16 | 11/21/12 | gollub | Updates from review. // 1.17 | 12/19/12 | gollub | Added UE isolation // 1.18 | 01/15/13 | gollub | Added check for valid dimm before calling // | | | dimmGetBadDqBitmap // 1.19 | 01/31/13 | gollub | Updated MDI bits for random pattern so // | | | don't get SUEs // | | | Added mss_check_steering // | | | Added mss_do_steering // | | | Added mss_stopCmd // | | | Removed cleanupCmd for cmds that didn't use it // 1.20 | 03/08/13 | gollub | Mask MBSPA[0][8] during increment cmd // 1.21 | 04/19/13 | gollub | Fix: Slow down fast scrub rate. // | | | Fix: Was skippng reg update for slow scrub rate // | | | Fix: Clear MBMCC[1] stop bit after forcing a stop // | | | Add: Added target to FAPI_ERR traces // 1.22 | 04/30/13 | mjjones | Removed unused variable // 1.23 | 05/03/13 | gollub | Clear cmd complete attention in mss_stopCmd // 1.24 | 05/20/13 | gollub | Updates from review. // 1.25 | 05/24/13 | gollub | Added DDR4 support to mss_get_address_range // | | | Disabled superfast increment mode if DDR4 - due to DD1 bug // 1.26 | 08/23/13 | gollub | Added x4 ECC mode support // | | | Clear inject type: MBECTLQ after atomic inject // | | | Updated random data seed // | | | Ordered display output by beat 0-7 // 1.27 | 09/03/13 | gollub | Removed unused variables // 1.28 | 10/31/13 | gollub | Removed support for stop condition enum // | | | ENABLE_CMD_COMPLETE_ATTENTION_ON_CLEAN_AND_ERROR // | | | DD2: enable (fixed) // | | | DD1: disable (broken) // 1.29 | 11/19/13 | bellows | Swapped to use ATTR_VPD_DIMM_SPARE // 1.30 | 02/07/14 |adityamd | Added support to mss_restore_DRAM_repairs to be accessed at Standby // 1.31 |12-FEB-14 | bellows | Workaround for ENABLE_RCE_WITH_OTHER_ERRORS_HW246685 // 1.32 |20-FEB-14 | bellows | RAS review updates // 1.33 |07-MAR-14 | gollub | Code review updates for: // | | | mss_restore_DRAM_repairs // | | | mss_restore_DRAM_repairs_asm // | | | mss_get_dummy_mark_store // | | | mss_put_dummy_mark_store // | | | mss_get_dummy_steer_mux // | | | mss_put_dummy_steer_mux // | | | SW249600: Adding 1ms delay to allow cmd to stop properly in mss_stopCmd() // 1.34 |11-MAR-14 | gollub | SW250519: More options for enum TimeBaseSpeed // 1.35 |07-APR-14 | gollub | Added enable/disable exit point 1 to get/put markstore functions // | | | Added official x4 and x8 patterns // | | | Implemented correct scrub interval settings for: // | | | FAST_MIN_BW_IMPACT // | | | FAST_MED_BW_IMPACT // | | | FAST_MAX_BW_IMPACT //------------------------------------------------------------------------------ // Includes //------------------------------------------------------------------------------ #include #include #include using namespace fapi; //------------------------------------------------------------------------------ // Constants and enums //------------------------------------------------------------------------------ /** * @brief Max 8 master ranks per MB */ const uint8_t MSS_MAX_RANKS = 8; /** * @brief The number of symbols per rank */ const uint8_t MSS_SYMBOLS_PER_RANK = 72; /** * @brief The used for symbol ranges on port 0: Symbols 71-40, 7-4 */ const uint8_t MSS_PORT_0_SYMBOL_71 = 71; const uint8_t MSS_PORT_0_SYMBOL_40 = 40; const uint8_t MSS_PORT_0_SYMBOL_7 = 7; const uint8_t MSS_PORT_0_SYMBOL_4 = 4; /** * @brief The used for symbol ranges on port 1: Symbols 39-8, 3-0 */ const uint8_t MSS_PORT_1_SYMBOL_39 = 39; const uint8_t MSS_PORT_1_SYMBOL_8 = 8; const uint8_t MSS_PORT_1_SYMBOL_3 = 3; const uint8_t MSS_PORT_1_SYMBOL_0 = 0; /** * @brief 9 x8 DRAMs we can steer, plus one for no steer option */ const uint8_t MSS_X8_STEER_OPTIONS_PER_PORT = 10; /** * @brief 18 x4 DRAMs we can steer on port0, plus one for no steer option */ const uint8_t MSS_X4_STEER_OPTIONS_PER_PORT0 = 19; /** * @brief 17 x4 DRAMs we can steer on port1, plus one no steer option * NOTE: Only 17 DRAMs we can steer since one DRAM is used for the * ECC spare. */ const uint8_t MSS_X4_STEER_OPTIONS_PER_PORT1 = 18; /** * @brief 18 on port0, 17 on port1, plus one no steer option * NOTE: Can's use ECC spare to fix bad spare DRAMs */ const uint8_t MSS_X4_ECC_STEER_OPTIONS = 36; /** * @brief Max 8 patterns */ const uint8_t MSS_MAX_PATTERNS = 9; namespace mss_MemConfig { /** * @brief DRAM size in gigabits, used to determine address range for maint cmds */ enum DramSize { GBIT_2 = 0, GBIT_4 = 1, GBIT_8 = 2, }; /** * @brief DRAM width, used to determine address range for maint cmds */ enum DramWidth { X4 = fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X4, X8 = fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8, }; /** * @brief DRAM row, column, and bank bits, used to determine address range * for maint cmds */ enum MemOrg { ROW_14 = 0x00003FFF, ROW_15 = 0x00007FFF, ROW_16 = 0x0000FFFF, ROW_17 = 0x0001FFFF, COL_10 = 0x000003F8, // c2, c1, c0 always 0 COL_11 = 0x000007F8, // c2, c1, c0 always 0 COL_12 = 0x00000FF8, // c2, c1, c0 always 0 BANK_3 = 0x00000007, BANK_4 = 0x0000000F, }; /** * @brief Spare DRAM config, used to identify what spares exist */ enum SpareDramConfig { NO_SPARE = 0, LOW_NIBBLE = 1, // x4 spare (low nibble: default) HIGH_NIBBLE = 2, // x4 spare (high nibble: no plan to use) FULL_BYTE = 3 // x8 dpare }; }; static const uint32_t mss_mbaxcr[2]={ // port0/1 port2/3 MBAXCR01Q_0x0201140B, MBAXCR23Q_0x0201140C}; static const uint32_t mss_mbeccfir[2]={ // port0/1 port2/3 MBS_ECC0_MBECCFIR_0x02011440, MBS_ECC1_MBECCFIR_0x02011480}; static const uint32_t mss_mbsecc[2]={ // port0/1 port2/3 MBS_ECC0_MBSECCQ_0x0201144A, MBS_ECC1_MBSECCQ_0x0201148A}; static const uint32_t mss_markStoreRegs[8][2]={ // port0/1 port2/3 {MBS_ECC0_MBMS0_0x0201144B, MBS_ECC1_MBMS0_0x0201148B}, {MBS_ECC0_MBMS1_0x0201144C, MBS_ECC1_MBMS1_0x0201148C}, {MBS_ECC0_MBMS2_0x0201144D, MBS_ECC1_MBMS2_0x0201148D}, {MBS_ECC0_MBMS3_0x0201144E, MBS_ECC1_MBMS3_0x0201148E}, {MBS_ECC0_MBMS4_0x0201144F, MBS_ECC1_MBMS4_0x0201148F}, {MBS_ECC0_MBMS5_0x02011450, MBS_ECC1_MBMS5_0x02011490}, {MBS_ECC0_MBMS6_0x02011451, MBS_ECC1_MBMS6_0x02011491}, {MBS_ECC0_MBMS7_0x02011452, MBS_ECC1_MBMS7_0x02011492}}; static const uint32_t mss_mbstr[2]={ // port0/1 port2/3 MBS01_MBSTRQ_0x02011655, MBS23_MBSTRQ_0x02011755}; static const uint32_t mss_mbmmr[2]={ // port0/1 port2/3 MBS_ECC0_MBMMRQ_0x0201145B, MBS_ECC1_MBMMRQ_0x0201149B}; static const uint32_t mss_readMuxRegs[8][2]={ // port0/1 port2/3 {MBS_ECC0_MBSBS0_0x0201145E, MBS_ECC1_MBSBS0_0x0201149E}, {MBS_ECC0_MBSBS1_0x0201145F, MBS_ECC1_MBSBS1_0x0201149F}, {MBS_ECC0_MBSBS2_0x02011460, MBS_ECC1_MBSBS2_0x020114A0}, {MBS_ECC0_MBSBS3_0x02011461, MBS_ECC1_MBSBS3_0x020114A1}, {MBS_ECC0_MBSBS4_0x02011462, MBS_ECC1_MBSBS4_0x020114A2}, {MBS_ECC0_MBSBS5_0x02011463, MBS_ECC1_MBSBS5_0x020114A3}, {MBS_ECC0_MBSBS6_0x02011464, MBS_ECC1_MBSBS6_0x020114A4}, {MBS_ECC0_MBSBS7_0x02011465, MBS_ECC1_MBSBS7_0x020114A5}}; static const uint32_t mss_writeMuxRegs[8]={ MBA01_MBABS0_0x03010440, MBA01_MBABS1_0x03010441, MBA01_MBABS2_0x03010442, MBA01_MBABS3_0x03010443, MBA01_MBABS4_0x03010444, MBA01_MBABS5_0x03010445, MBA01_MBABS6_0x03010446, MBA01_MBABS7_0x03010447}; //------------------------------------------------------------------------------ // Conversion from symbol index to galois field stored in markstore //------------------------------------------------------------------------------ static const uint8_t mss_symbol2Galois[MSS_SYMBOLS_PER_RANK] = { 0x80, 0xa0, 0x90, 0xf0, 0x08, 0x0a, 0x09, 0x0f, // symbols 0- 7 0x98, 0xda, 0xb9, 0x7f, 0x91, 0xd7, 0xb2, 0x78, // symbols 8-15 0x28, 0xea, 0x49, 0x9f, 0x9a, 0xd4, 0xbd, 0x76, // symbols 16-23 0x60, 0xb0, 0xc0, 0x20, 0x06, 0x0b, 0x0c, 0x02, // symbols 24-31 0xc6, 0xfb, 0x1c, 0x42, 0xca, 0xf4, 0x1d, 0x46, // symbols 32-39 0xd6, 0x8b, 0x3c, 0xc2, 0xcb, 0xf3, 0x1f, 0x4e, // symbols 40-47 0xe0, 0x10, 0x50, 0xd0, 0x0e, 0x01, 0x05, 0x0d, // symbols 48-55 0x5e, 0x21, 0xa5, 0x3d, 0x5b, 0x23, 0xaf, 0x3e, // symbols 56-63 0xfe, 0x61, 0x75, 0x5d, 0x51, 0x27, 0xa2, 0x38, // symbols 64-71 }; static const uint8_t mss_x8dramSparePort0Index_to_symbol[MSS_X8_STEER_OPTIONS_PER_PORT]={ // symbol MSS_INVALID_SYMBOL, // Port0 DRAM spare not used 68, // DRAM 17 (x8) 64, // DRAM 16 (x8) 60, // DRAM 15 (x8) 56, // DRAM 14 (x8) 52, // DRAM 13 (x8) 48, // DRAM 12 (x8) 44, // DRAM 11 (x8) 40, // DRAM 10 (x8) 4}; // DRAM 1 (x8) static const uint8_t mss_x4dramSparePort0Index_to_symbol[MSS_X4_STEER_OPTIONS_PER_PORT0]={ // symbol MSS_INVALID_SYMBOL, // Port0 DRAM spare not used 70, // DRAM 35 (x4) 68, // DRAM 34 (x4) 66, // DRAM 33 (x4) 64, // DRAM 32 (x4) 62, // DRAM 31 (x4) 60, // DRAM 30 (x4) 58, // DRAM 29 (x4) 56, // DRAM 28 (x4) 54, // DRAM 27 (x4) 52, // DRAM 26 (x4) 50, // DRAM 25 (x4) 48, // DRAM 24 (x4) 46, // DRAM 23 (x4) 44, // DRAM 22 (x4) 42, // DRAM 21 (x4) 40, // DRAM 20 (x4) 6, // DRAM 3 (x4) 4}; // DRAM 2 (x4) static const uint8_t mss_x8dramSparePort1Index_to_symbol[MSS_X8_STEER_OPTIONS_PER_PORT]={ // symbol MSS_INVALID_SYMBOL, // Port1 DRAM spare not used 36, // DRAM 9 (x8) 32, // DRAM 8 (x8) 28, // DRAM 7 (x8) 24, // DRAM 6 (x8) 20, // DRAM 5 (x8) 16, // DRAM 4 (x8) 12, // DRAM 3 (x8) 8, // DRAM 2 (x8) 0}; // DRAM 0 (x8) static const uint8_t mss_x4dramSparePort1Index_to_symbol[MSS_X4_STEER_OPTIONS_PER_PORT1]={ // symbol MSS_INVALID_SYMBOL, // Port1 DRAM spare not used 38, // DRAM 19 (x4) 36, // DRAM 18 (x4) 34, // DRAM 17 (x4) 32, // DRAM 16 (x4) 30, // DRAM 15 (x4) 28, // DRAM 14 (x4) 26, // DRAM 13 (x4) 24, // DRAM 12 (x4) 22, // DRAM 11 (x4) 20, // DRAM 10 (x4) 18, // DRAM 9 (x4) 16, // DRAM 8 (x4) 14, // DRAM 7 (x4) 12, // DRAM 6 (x4) 10, // DRAM 5 (x4) 8, // DRAM 4 (x4) 2}; // DRAM 1 (x4) // NOTE: DRAM 0 (x4) (symbols 0,1) on Port1 is used for the ECC spare, // so can't use DRAM spare to fix DRAM 0. static const uint8_t mss_eccSpareIndex_to_symbol[MSS_X4_ECC_STEER_OPTIONS]={ // symbol MSS_INVALID_SYMBOL, // ECC spare not used 70, // DRAM 35 (x4) 68, // DRAM 34 (x4) 66, // DRAM 33 (x4) 64, // DRAM 32 (x4) 62, // DRAM 31 (x4) 60, // DRAM 30 (x4) 58, // DRAM 29 (x4) 56, // DRAM 28 (x4) 54, // DRAM 27 (x4) 52, // DRAM 26 (x4) 50, // DRAM 25 (x4) 48, // DRAM 24 (x4) 46, // DRAM 23 (x4) 44, // DRAM 22 (x4) 42, // DRAM 21 (x4) 40, // DRAM 20 (x4) 38, // DRAM 19 (x4) 36, // DRAM 18 (x4) 34, // DRAM 17 (x4) 32, // DRAM 16 (x4) 30, // DRAM 15 (x4) 28, // DRAM 14 (x4) 26, // DRAM 13 (x4) 24, // DRAM 12 (x4) 22, // DRAM 11 (x4) 20, // DRAM 10 (x4) 18, // DRAM 9 (x4) 16, // DRAM 8 (x4) 14, // DRAM 7 (x4) 12, // DRAM 6 (x4) 10, // DRAM 5 (x4) 8, // DRAM 4 (x4) 6, // DRAM 3 (x4) 4, // DRAM 2 (x4) 2}; // DRAM 1 (x4) // NOTE: DRAM 0 (x4) (symbols 0,1) used for the ECC spare. // NOTE: Can't use ECC spare to fix bad spare DRAMs on Port0 or Port1 static const uint32_t mss_maintBufferData[2][MSS_MAX_PATTERNS][16][2]={ /* ---Pattern 00 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 0000000000000000 0000000000000000 t1 0000000000000000 0000000000000000 t2 0000000000000000 0000000000000000 t3 0000000000000000 0000000000000000 MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) t4 0000000000000000 0000000000000000 t5 0000000000000000 0000000000000000 t6 0000000000000000 0000000000000000 t7 0000000000000000 0000000000000000 MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) */ // PATTERN_0 // port0,2 {{{0x00000000, 0x00000000}, // DW0 {0x00000000, 0x00000000}, // DW2 {0x00000000, 0x00000000}, // DW4 {0x00000000, 0x00000000}, // DW6 {0x00000000, 0x00000000}, // DW8 {0x00000000, 0x00000000}, // DW10 {0x00000000, 0x00000000}, // DW12 {0x00000000, 0x00000000}, // DW14 // port1,3 {0x00000000, 0x00000000}, // DW1 {0x00000000, 0x00000000}, // DW3 {0x00000000, 0x00000000}, // DW5 {0x00000000, 0x00000000}, // DW7 {0x00000000, 0x00000000}, // DW9 {0x00000000, 0x00000000}, // DW11 {0x00000000, 0x00000000}, // DW13 {0x00000000, 0x00000000}},// DW15 /* ---Pattern 1 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 ffffffffffffffff ffffffffffffffff t1 ffffffffffffffff ffffffffffffffff t2 ffffffffffffffff ffffffffffffffff t3 ffffffffffffffff ffffffffffffffff MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) t4 ffffffffffffffff ffffffffffffffff t5 ffffffffffffffff ffffffffffffffff t6 ffffffffffffffff ffffffffffffffff t7 ffffffffffffffff ffffffffffffffff MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) */ // PATTERN_1 // port0,2 {{0xffffffff, 0xffffffff}, // DW0 {0xffffffff, 0xffffffff}, // DW2 {0xffffffff, 0xffffffff}, // DW4 {0xffffffff, 0xffffffff}, // DW6 {0xffffffff, 0xffffffff}, // DW8 {0xffffffff, 0xffffffff}, // DW10 {0xffffffff, 0xffffffff}, // DW12 {0xffffffff, 0xffffffff}, // DW14 // port1,3 {0xffffffff, 0xffffffff}, // DW1 {0xffffffff, 0xffffffff}, // DW3 {0xffffffff, 0xffffffff}, // DW5 {0xffffffff, 0xffffffff}, // DW7 {0xffffffff, 0xffffffff}, // DW9 {0xffffffff, 0xffffffff}, // DW11 {0xffffffff, 0xffffffff}, // DW13 {0xffffffff, 0xffffffff}},// DW15 /*---Pattern 2 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 6789555555555555 5555555555555555 t1 6f2eaaaaaaaaaaaa aaaaaaaaaaaaaaaa t2 ae79555555555555 5555555555555555 t3 84edaaaaaaaaaaaa aaaaaaaaaaaaaaaa MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) t4 545eaaaaaaaaaaaa aaaaaaaaaaaaaaaa t5 a791555555555555 5555555555555555 t6 6622aaaaaaaaaaaa aaaaaaaaaaaaaaaa t7 f7f8555555555555 5555555555555555 MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) */ // PATTERN_2 // port0,2 {{0x67895555, 0x55555555}, // DW0 {0x6f2eaaaa, 0xaaaaaaaa}, // DW2 {0xae795555, 0x55555555}, // DW4 {0x84edaaaa, 0xaaaaaaaa}, // DW6 {0x545eaaaa, 0xaaaaaaaa}, // DW8 {0xa7915555, 0x55555555}, // DW10 {0x6622aaaa, 0xaaaaaaaa}, // DW12 {0xf7f85555, 0x55555555}, // DW14 // port1,3 {0x55555555, 0x55555555}, // DW1 {0xaaaaaaaa, 0xaaaaaaaa}, // DW3 {0x55555555, 0x55555555}, // DW5 {0xaaaaaaaa, 0xaaaaaaaa}, // DW7 {0xaaaaaaaa, 0xaaaaaaaa}, // DW9 {0x55555555, 0x55555555}, // DW11 {0xaaaaaaaa, 0xaaaaaaaa}, // DW13 {0x55555555, 0x55555555}},// DW15 /* ---Pattern 3 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 aaaaaac47aaaaaaa aaaaaaaaaaaaaaaa t1 555555abf1555555 5555555555555555 t2 aaaaaa01aeaaaaaa aaaaaaaaaaaaaaaa t3 5555550c81555555 5555555555555555 MDI= (0,0), tag(0,1,2,3) = (1,1,1,1) t4 5555557a7f555555 5555555555555555 t5 aaaaaaccafaaaaaa aaaaaaaaaaaaaaaa t6 555555456d555555 5555555555555555 t7 aaaaaa21deaaaaaa aaaaaaaaaaaaaaaa MDI= (1,1), tag(0,1,2,3) = (0,0,0,0) */ // PATTERN_3 // port0,2 {{0xaaaaaac4, 0x7aaaaaaa}, // DW0 {0x555555ab, 0xf1555555}, // DW2 {0xaaaaaa01, 0xaeaaaaaa}, // DW4 {0x5555550c, 0x81555555}, // DW6 {0x5555557a, 0x7f555555}, // DW8 {0xaaaaaacc, 0xafaaaaaa}, // DW10 {0x55555545, 0x6d555555}, // DW12 {0xaaaaaa21, 0xdeaaaaaa}, // DW14 // port1,3 {0xaaaaaaaa, 0xaaaaaaaa}, // DW1 {0x55555555, 0x55555555}, // DW3 {0xaaaaaaaa, 0xaaaaaaaa}, // DW5 {0x55555555, 0x55555555}, // DW7 {0x55555555, 0x55555555}, // DW9 {0xaaaaaaaa, 0xaaaaaaaa}, // DW11 {0x55555555, 0x55555555}, // DW13 {0xaaaaaaaa, 0xaaaaaaaa}},// DW15 /* ---Pattern 4 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 ffffffffffff8403 ffffffffffffffff t1 ffffffffffff83d3 ffffffffffffffff t2 ffffffffffffbf89 ffffffffffffffff t3 ffffffffffff1133 ffffffffffffffff MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) t4 000000000000006c 0000000000000000 t5 000000000000468a 0000000000000000 t6 000000000000cf7e 0000000000000000 t7 ffffffffffff6d37 ffffffffffffffff MDI= (1,0), tag(0,1,2,3) = (1,1,1,0) */ // PATTERN_4 // port0,2 {{0xffffffff, 0xffff8403}, // DW0 {0xffffffff, 0xffff83d3}, // DW2 {0xffffffff, 0xffffbf89}, // DW4 {0xffffffff, 0xffff1133}, // DW6 {0x00000000, 0x0000006c}, // DW8 {0x00000000, 0x0000468a}, // DW10 {0x00000000, 0x0000cf7e}, // DW12 {0xffffffff, 0xffff6d37}, // DW14 // port1,3 {0xffffffff, 0xffffffff}, // DW1 {0xffffffff, 0xffffffff}, // DW3 {0xffffffff, 0xffffffff}, // DW5 {0xffffffff, 0xffffffff}, // DW7 {0x00000000, 0x00000000}, // DW9 {0x00000000, 0x00000000}, // DW11 {0x00000000, 0x00000000}, // DW13 {0xffffffff, 0xffffffff}},// DW15 /* ---Pattern 5 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 0000000000000000 0000000006c00000 t1 0000000000000000 0000000068f40000 t2 0000000000000000 00000000701c0000 t3 0000000000000000 00000000f7640000 MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) t4 ffffffffffffffff ffffffffe523ffff t5 ffffffffffffffff ffffffff5603ffff t6 ffffffffffffffff fffffffffeb5ffff t7 0000000000000000 0000000098a40000 MDI= (0,1), tag(0,1,2,3) = (0,0,0,1) */ // PATTERN_5 // port0,2 {{0x00000000, 0x00000000}, // DW0 {0x00000000, 0x00000000}, // DW2 {0x00000000, 0x00000000}, // DW4 {0x00000000, 0x00000000}, // DW6 {0xffffffff, 0xffffffff}, // DW8 {0xffffffff, 0xffffffff}, // DW10 {0xffffffff, 0xffffffff}, // DW12 {0x00000000, 0x00000000}, // DW14 // port1,3 {0x00000000, 0x06c00000}, // DW1 {0x00000000, 0x68f40000}, // DW3 {0x00000000, 0x701c0000}, // DW5 {0x00000000, 0xf7640000}, // DW7 {0xffffffff, 0xe523ffff}, // DW9 {0xffffffff, 0x5603ffff}, // DW11 {0xffffffff, 0xfeb5ffff}, // DW13 {0x00000000, 0x98a40000}},// DW15 /* ---Pattern 6 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 ffffffffffffffff ffffffffceb3ffff t1 0000000000000000 0000000034460000 t2 ffffffffffffffff ffffffffb1afffff t3 0000000000000000 00000000fd080000 MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) t4 0000000000000000 0000000037540000 t5 ffffffffffffffff ffffffff3443ffff t6 0000000000000000 000000001a260000 t7 ffffffffffffffff ffffffff3f3fffff MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) */ // PATTERN_6 // port0,2 {{0xffffffff, 0xffffffff}, // DW0 {0x00000000, 0x00000000}, // DW2 {0xffffffff, 0xffffffff}, // DW4 {0x00000000, 0x00000000}, // DW6 {0x00000000, 0x00000000}, // DW8 {0xffffffff, 0xffffffff}, // DW10 {0x00000000, 0x00000000}, // DW12 {0xffffffff, 0xffffffff}, // DW14 // port1,3 {0xffffffff, 0xceb3ffff}, // DW1 {0x00000000, 0x34460000}, // DW3 {0xffffffff, 0xb1afffff}, // DW5 {0x00000000, 0xfd080000}, // DW7 {0x00000000, 0x37540000}, // DW9 {0xffffffff, 0x3443ffff}, // DW11 {0x00000000, 0x1a260000}, // DW13 {0xffffffff, 0x3f3fffff}},// DW15 /* ---Pattern 7 Pattern sent to encoder (x8 mode): port0,2 port1,3 t0 83dc000000000000 0000000000000000 t1 d4b7ffffffffffff ffffffffffffffff t2 8c2c000000000000 0000000000000000 t3 5d8affffffffffff ffffffffffffffff MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) t4 ec57ffffffffffff ffffffffffffffff t5 a9d4000000000000 0000000000000000 t6 8447ffffffffffff ffffffffffffffff t7 eafe000000000000 0000000000000000 MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) */ // PATTERN_7 // port0,2 {{0x83dc0000, 0x00000000}, // DW0 {0xd4b7ffff, 0xffffffff}, // DW2 {0x8c2c0000, 0x00000000}, // DW4 {0x5d8affff, 0xffffffff}, // DW6 {0xec57ffff, 0xffffffff}, // DW8 {0xa9d40000, 0x00000000}, // DW10 {0x8447ffff, 0xffffffff}, // DW12 {0xeafe0000, 0x00000000}, // DW14 // port1,3 {0x00000000, 0x00000000}, // DW1 {0xffffffff, 0xffffffff}, // DW3 {0x00000000, 0x00000000}, // DW5 {0xffffffff, 0xffffffff}, // DW7 {0xffffffff, 0xffffffff}, // DW9 {0x00000000, 0x00000000}, // DW11 {0xffffffff, 0xffffffff}, // DW13 {0x00000000, 0x00000000}},// DW15 // PATTERN_8: random seed {{0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}}}, /* ---Pattern 00 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 0000000000000000 0000000000000000 t1 0000000000000000 0000000000000000 t2 0000000000000000 0000000000000000 t3 0000000000000000 0000000000000000 MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) t4 0000000000000000 0000000000000000 t5 0000000000000000 0000000000000000 t6 0000000000000000 0000000000000000 t7 0000000000000000 0000000000000000 MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) */ // PATTERN_0 // port0,2 {{{0x00000000, 0x00000000}, // DW0 {0x00000000, 0x00000000}, // DW2 {0x00000000, 0x00000000}, // DW4 {0x00000000, 0x00000000}, // DW6 {0x00000000, 0x00000000}, // DW8 {0x00000000, 0x00000000}, // DW10 {0x00000000, 0x00000000}, // DW12 {0x00000000, 0x00000000}, // DW14 // port1,3 {0x00000000, 0x00000000}, // DW1 {0x00000000, 0x00000000}, // DW3 {0x00000000, 0x00000000}, // DW5 {0x00000000, 0x00000000}, // DW7 {0x00000000, 0x00000000}, // DW9 {0x00000000, 0x00000000}, // DW11 {0x00000000, 0x00000000}, // DW13 {0x00000000, 0x00000000}},// DW15 /* ---Pattern 1 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 ffffffffffffffff ffffffffffffffff t1 ffffffffffffffff ffffffffffffffff t2 ffffffffffffffff ffffffffffffffff t3 ffffffffffffffff ffffffffffffffff MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) t4 ffffffffffffffff ffffffffffffffff t5 ffffffffffffffff ffffffffffffffff t6 ffffffffffffffff ffffffffffffffff t7 ffffffffffffffff ffffffffffffffff MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) */ // PATTERN_1 // port0,2 {{0xffffffff, 0xffffffff}, // DW0 {0xffffffff, 0xffffffff}, // DW2 {0xffffffff, 0xffffffff}, // DW4 {0xffffffff, 0xffffffff}, // DW6 {0xffffffff, 0xffffffff}, // DW8 {0xffffffff, 0xffffffff}, // DW10 {0xffffffff, 0xffffffff}, // DW12 {0xffffffff, 0xffffffff}, // DW14 // port1,3 {0xffffffff, 0xffffffff}, // DW1 {0xffffffff, 0xffffffff}, // DW3 {0xffffffff, 0xffffffff}, // DW5 {0xffffffff, 0xffffffff}, // DW7 {0xffffffff, 0xffffffff}, // DW9 {0xffffffff, 0xffffffff}, // DW11 {0xffffffff, 0xffffffff}, // DW13 {0xffffffff, 0xffffffff}},// DW15 /*---Pattern 2 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 5055555555555555 5555555555555555 t1 a96aaaaaaaaaaaaa aaaaaaaaaaaaaaaa t2 6215555555555555 5555555555555555 t3 dd5aaaaaaaaaaaaa aaaaaaaaaaaaaaaa MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) t4 89eaaaaaaaaaaaaa aaaaaaaaaaaaaaaa t5 7fd5555555555555 5555555555555555 t6 b32aaaaaaaaaaaaa aaaaaaaaaaaaaaaa t7 acc5555555555555 5555555555555555 MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) */ // PATTERN_2 // port0,2 {{0x50555555, 0x55555555}, // DW0 {0xa96aaaaa, 0xaaaaaaaa}, // DW2 {0x62155555, 0x55555555}, // DW4 {0xdd5aaaaa, 0xaaaaaaaa}, // DW6 {0x89eaaaaa, 0xaaaaaaaa}, // DW8 {0x7fd55555, 0x55555555}, // DW10 {0xb32aaaaa, 0xaaaaaaaa}, // DW12 {0xacc55555, 0x55555555}, // DW14 // port1,3 {0x55555555, 0x55555555}, // DW1 {0xaaaaaaaa, 0xaaaaaaaa}, // DW3 {0x55555555, 0x55555555}, // DW5 {0xaaaaaaaa, 0xaaaaaaaa}, // DW7 {0xaaaaaaaa, 0xaaaaaaaa}, // DW9 {0x55555555, 0x55555555}, // DW11 {0xaaaaaaaa, 0xaaaaaaaa}, // DW13 {0x55555555, 0x55555555}},// DW15 /* ---Pattern 3 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 aaaaaab7caaaaaaa aaaaaaaaaaaaaaaa t1 555555f2d5555555 5555555555555555 t2 aaaaaad8aaaaaaaa aaaaaaaaaaaaaaaa t3 5555552495555555 5555555555555555 MDI= (0,0), tag(0,1,2,3) = (1,1,1,1) t4 55555540b5555555 5555555555555555 t5 aaaaaa04baaaaaaa aaaaaaaaaaaaaaaa t6 555555c095555555 5555555555555555 t7 aaaaaa956aaaaaaa aaaaaaaaaaaaaaaa MDI= (1,1), tag(0,1,2,3) = (0,0,0,0) */ // PATTERN_3 // port0,2 {{0xaaaaaab7, 0xcaaaaaaa}, // DW0 {0x555555f2, 0xd5555555}, // DW2 {0xaaaaaad8, 0xaaaaaaaa}, // DW4 {0x55555524, 0x95555555}, // DW6 {0x55555540, 0xb5555555}, // DW8 {0xaaaaaa04, 0xbaaaaaaa}, // DW10 {0x555555c0, 0x95555555}, // DW12 {0xaaaaaa95, 0x6aaaaaaa}, // DW14 // port1,3 {0xaaaaaaaa, 0xaaaaaaaa}, // DW1 {0x55555555, 0x55555555}, // DW3 {0xaaaaaaaa, 0xaaaaaaaa}, // DW5 {0x55555555, 0x55555555}, // DW7 {0x55555555, 0x55555555}, // DW9 {0xaaaaaaaa, 0xaaaaaaaa}, // DW11 {0x55555555, 0x55555555}, // DW13 {0xaaaaaaaa, 0xaaaaaaaa}},// DW15 /* ---Pattern 4 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 ffffffffffff93ff ffffffffffffffff t1 ffffffffffffb5bf ffffffffffffffff t2 ffffffffffff207f ffffffffffffffff t3 ffffffffffffb37f ffffffffffffffff MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) t4 0000000000002340 0000000000000000 t5 00000000000062e0 0000000000000000 t6 0000000000006740 0000000000000000 t7 ffffffffffff6a3f ffffffffffffffff MDI= (1,0), tag(0,1,2,3) = (1,1,1,0) */ // PATTERN_4 // port0,2 {{0xffffffff, 0xffff93ff}, // DW0 {0xffffffff, 0xffffb5bf}, // DW2 {0xffffffff, 0xffff207f}, // DW4 {0xffffffff, 0xffffb37f}, // DW6 {0x00000000, 0x00002340}, // DW8 {0x00000000, 0x000062e0}, // DW10 {0x00000000, 0x00006740}, // DW12 {0xffffffff, 0xffff6a3f}, // DW14 // port1,3 {0xffffffff, 0xffffffff}, // DW1 {0xffffffff, 0xffffffff}, // DW3 {0xffffffff, 0xffffffff}, // DW5 {0xffffffff, 0xffffffff}, // DW7 {0x00000000, 0x00000000}, // DW9 {0x00000000, 0x00000000}, // DW11 {0x00000000, 0x00000000}, // DW13 {0xffffffff, 0xffffffff}},// DW15 /* ---Pattern 5 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 0000000000000000 0000000090c00000 t1 0000000000000000 00000000b0400000 t2 0000000000000000 0000000087a00000 t3 0000000000000000 0000000033000000 MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) t4 ffffffffffffffff ffffffff9dbfffff t5 ffffffffffffffff ffffffffa69fffff t6 ffffffffffffffff ffffffff257fffff t7 0000000000000000 00000000c7400000 MDI= (0,1), tag(0,1,2,3) = (0,0,0,1) */ // PATTERN_5 // port0,2 {{0x00000000, 0x00000000}, // DW0 {0x00000000, 0x00000000}, // DW2 {0x00000000, 0x00000000}, // DW4 {0x00000000, 0x00000000}, // DW6 {0xffffffff, 0xffffffff}, // DW8 {0xffffffff, 0xffffffff}, // DW10 {0xffffffff, 0xffffffff}, // DW12 {0x00000000, 0x00000000}, // DW14 // port1,3 {0x00000000, 0x90c00000}, // DW1 {0x00000000, 0xb0400000}, // DW3 {0x00000000, 0x87a00000}, // DW5 {0x00000000, 0x33000000}, // DW7 {0xffffffff, 0x9dbfffff}, // DW9 {0xffffffff, 0xa69fffff}, // DW11 {0xffffffff, 0x257fffff}, // DW13 {0x00000000, 0xc7400000}},// DW15 /* ---Pattern 6 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 ffffffffffffffff ffffffff7e3fffff t1 0000000000000000 0000000018c00000 t2 ffffffffffffffff ffffffffc8bfffff t3 0000000000000000 000000006b800000 MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) t4 0000000000000000 00000000f2800000 t5 ffffffffffffffff ffffffff659fffff t6 0000000000000000 00000000c5c00000 t7 ffffffffffffffff ffffffff473fffff MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) */ // PATTERN_6 // port0,2 {{0xffffffff, 0xffffffff}, // DW0 {0x00000000, 0x00000000}, // DW2 {0xffffffff, 0xffffffff}, // DW4 {0x00000000, 0x00000000}, // DW6 {0x00000000, 0x00000000}, // DW8 {0xffffffff, 0xffffffff}, // DW10 {0x00000000, 0x00000000}, // DW12 {0xffffffff, 0xffffffff}, // DW14 // port1,3 {0xffffffff, 0x7e3fffff}, // DW1 {0x00000000, 0x18c00000}, // DW3 {0xffffffff, 0xc8bfffff}, // DW5 {0x00000000, 0x6b800000}, // DW7 {0x00000000, 0xf2800000}, // DW9 {0xffffffff, 0x659fffff}, // DW11 {0x00000000, 0xc5c00000}, // DW13 {0xffffffff, 0x473fffff}},// DW15 /* ---Pattern 7 Pattern sent to encoder (x4 mode): port0,2 port1,3 t0 8200000000000000 0000000000000000 t1 d3bfffffffffffff ffffffffffffffff t2 d080000000000000 0000000000000000 t3 539fffffffffffff ffffffffffffffff MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) t4 63ffffffffffffff ffffffffffffffff t5 d640000000000000 0000000000000000 t6 5c3fffffffffffff ffffffffffffffff t7 dcb0000000000000 0000000000000000 MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) */ // PATTERN_7 // port0,2 {{0x82000000, 0x00000000}, // DW0 {0xd3bfffff, 0xffffffff}, // DW2 {0xd0800000, 0x00000000}, // DW4 {0x539fffff, 0xffffffff}, // DW6 {0x63ffffff, 0xffffffff}, // DW8 {0xd6400000, 0x00000000}, // DW10 {0x5c3fffff, 0xffffffff}, // DW12 {0xdcb00000, 0x00000000}, // DW14 // port1,3 {0x00000000, 0x00000000}, // DW1 {0xffffffff, 0xffffffff}, // DW3 {0x00000000, 0x00000000}, // DW5 {0xffffffff, 0xffffffff}, // DW7 {0xffffffff, 0xffffffff}, // DW9 {0x00000000, 0x00000000}, // DW11 {0xffffffff, 0xffffffff}, // DW13 {0x00000000, 0x00000000}},// DW15 // PATTERN_8: random seed {{0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}, {0x12345678, 0x87654321}, {0x87654321, 0x12345678}}}}; static const uint8_t mss_65thByte[2][MSS_MAX_PATTERNS][4]={ // bit1=tag0_2, bit2=tag1_3, bit3=MDI // PATTERN_0 (x8 mode) // MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) {{0x00, // 1st 64B of cachline: tag0=0, tag1=0, MDI=0 0x00, // 1st 64B of cachline: tag2=0, tag3=0, MDI=0 // MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) 0x00, // 2nd 64B of cachline: tag0=0, tag1=0, MDI=0 0x00}, // 2nd 64B of cachline: tag2=0, tag3=0, MDI=0 // PATTERN_1 (x8 mode) // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) {0xF0, // 1st 64B of cachline: tag0=1, tag1=1, MDI=1 0x70, // 1st 64B of cachline: tag2=1, tag3=1, MDI=1 // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) 0x70, // 2nd 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0}, // 2nd 64B of cachline: tag2=1, tag3=1, MDI=1 // PATTERN_2 (x8 mode) // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) {0xF0, // 1st 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0, // 1st 64B of cachline: tag2=1, tag3=1, MDI=1 // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) 0xF0, // 2nd 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0}, // 2nd 64B of cachline: tag2=1, tag3=1, MDI=1 // PATTERN_3 (x8 mode) // MDI= (0,0), tag(0,1,2,3) = (1,1,1,1) {0x60, // 1st 64B of cachline: tag0=1, tag1=1, MDI=0 0x60, // 1st 64B of cachline: tag2=1, tag3=1, MDI=0 // MDI= (1,1), tag(0,1,2,3) = (0,0,0,0) 0x90, // 2nd 64B of cachline: tag0=0, tag1=0, MDI=1 0x90}, // 2nd 64B of cachline: tag2=0, tag3=0, MDI=1 // PATTERN_4 (x8 mode) // MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) {0x00, // 1st 64B of cachline: tag0=0, tag1=0, MDI=0 0x00, // 1st 64B of cachline: tag2=0, tag3=0, MDI=0 // MDI= (1,0), tag(0,1,2,3) = (1,1,1,0) 0xF0, // 2nd 64B of cachline: tag0=1, tag1=1, MDI=1 0xC0}, // 2nd 64B of cachline: tag2=1, tag3=0, MDI=0 // PATTERN_5 (x8 mode) // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) {0xF0, // 1st 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0, // 1st 64B of cachline: tag2=1, tag3=1, MDI=1 // MDI= (0,1), tag(0,1,2,3) = (0,0,0,1) 0x00, // 2nd 64B of cachline: tag0=0, tag1=0, MDI=0 0x10}, // 2nd 64B of cachline: tag2=0, tag3=1, MDI=1 // PATTERN_6 (x8 mode) // MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) {0x30, // 1st 64B of cachline: tag0=0, tag1=1, MDI=1 0x30, // 1st 64B of cachline: tag2=0, tag3=1, MDI=1 // MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) 0xC0, // 2nd 64B of cachline: tag0=1, tag1=0, MDI=0 0xC0}, // 2nd 64B of cachline: tag2=1, tag3=0, MDI=0 // PATTERN_7 (x8 mode) // MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) {0xC0, // 1st 64B of cachline: tag0=1, tag1=0, MDI=0 0xC0, // 1st 64B of cachline: tag2=1, tag3=0, MDI=0 // MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) 0x30, // 2nd 64B of cachline: tag0=0, tag1=1, MDI=1 0x30}, // 2nd 64B of cachline: tag2=0, tag3=1, MDI=1 // PATTERN_8: random seed (x8 mode) {0x20, // 1st 64B of cachline: tag0=0, tag1=1, MDI=0 0x60, // 1st 64B of cachline: tag2=1, tag3=1, MDI=0 0x30, // 2nd 64B of cachline: tag0=0, tag1=1, MDI=1 0x70}}, // 2nd 64B of cachline: tag2=1, tag3=1, MDI=1 // bit1=tag0_2, bit2=tag1_3, bit3=MDI // PATTERN_0 (x4 mode) // MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) {{0x00, // 1st 64B of cachline: tag0=0, tag1=0, MDI=0 0x00, // 1st 64B of cachline: tag2=0, tag3=0, MDI=0 // MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) 0x00, // 2nd 64B of cachline: tag0=0, tag1=0, MDI=0 0x00}, // 2nd 64B of cachline: tag2=0, tag3=0, MDI=0 // PATTERN_1 (x4 mode) // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) {0xF0, // 1st 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0, // 1st 64B of cachline: tag2=1, tag3=1, MDI=1 // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) 0xF0, // 2nd 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0}, // 2nd 64B of cachline: tag2=1, tag3=1, MDI=1 // PATTERN_2 (x4 mode) // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) {0xF0, // 1st 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0, // 1st 64B of cachline: tag2=1, tag3=1, MDI=1 // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) 0xF0, // 2nd 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0}, // 2nd 64B of cachline: tag2=1, tag3=1, MDI=1 // PATTERN_3 (x4 mode) // MDI= (0,0), tag(0,1,2,3) = (1,1,1,1) {0x60, // 1st 64B of cachline: tag0=1, tag1=1, MDI=0 0x60, // 1st 64B of cachline: tag2=1, tag3=1, MDI=0 // MDI= (1,1), tag(0,1,2,3) = (0,0,0,0) 0x90, // 2nd 64B of cachline: tag0=0, tag1=0, MDI=1 0x90}, // 2nd 64B of cachline: tag2=0, tag3=0, MDI=1 // PATTERN_4 (x4 mode) // MDI= (0,0), tag(0,1,2,3) = (0,0,0,0) {0x00, // 1st 64B of cachline: tag0=0, tag1=0, MDI=0 0x00, // 1st 64B of cachline: tag2=0, tag3=0, MDI=0 // MDI= (1,0), tag(0,1,2,3) = (1,1,1,0) 0xF0, // 2nd 64B of cachline: tag0=1, tag1=1, MDI=1 0xC0}, // 2nd 64B of cachline: tag2=1, tag3=0, MDI=0 // PATTERN_5 (x4 mode) // MDI= (1,1), tag(0,1,2,3) = (1,1,1,1) {0xF0, // 1st 64B of cachline: tag0=1, tag1=1, MDI=1 0xF0, // 1st 64B of cachline: tag2=1, tag3=1, MDI=1 // MDI= (0,1), tag(0,1,2,3) = (0,0,0,1) 0x80, // 2nd 64B of cachline: tag0=0, tag1=0, MDI=0 0x10}, // 2nd 64B of cachline: tag2=0, tag3=1, MDI=1 // PATTERN_6 (x4 mode) // MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) {0x30, // 1st 64B of cachline: tag0=0, tag1=1, MDI=1 0x30, // 1st 64B of cachline: tag2=0, tag3=1, MDI=1 // MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) 0xC0, // 2nd 64B of cachline: tag0=1, tag1=0, MDI=0 0xC0}, // 2nd 64B of cachline: tag2=1, tag3=0, MDI=0 // PATTERN_7 (x4 mode) // MDI= (0,0), tag(0,1,2,3) = (1,0,1,0) {0xC0, // 1st 64B of cachline: tag0=1, tag1=0, MDI=0 0xC0, // 1st 64B of cachline: tag2=1, tag3=0, MDI=0 // MDI= (1,1), tag(0,1,2,3) = (0,1,0,1) 0x30, // 2nd 64B of cachline: tag0=0, tag1=1, MDI=1 0x30}, // 2nd 64B of cachline: tag2=0, tag3=1, MDI=1 // PATTERN_8: random seed (x8 mode) {0x20, // 1st 64B of cachline: tag0=0, tag1=1, MDI=0 0x60, // 1st 64B of cachline: tag2=1, tag3=1, MDI=0 0x30, // 2nd 64B of cachline: tag0=0, tag1=1, MDI=1 0x70}}};// 2nd 64B of cachline: tag2=1, tag3=1, MDI=1 static const uint32_t mss_ECC[2][MSS_MAX_PATTERNS][4]={ // bit 4:15 ECC_c6_c5_c4, bit 16:31 ECC_c3_c2_c1_c0 // PATTERN_0 (x8 mode) {{0x00000000, // 1st 64B of cachline 0x00000000, // 1st 64B of cachline 0x00000000, // 2nd 64B of cachline 0x00000000}, // 2nd 64B of cachline // PATTERN_1 (x8 mode) {0x0DA49500, // 1st 64B of cachline 0x0234A60E, // 1st 64B of cachline 0x0DA49500, // 2nd 64B of cachline 0x0234A60E}, // 2nd 64B of cachline // PATTERN_2 (x8 mode) {0x0FFFFFFF, // 1st 64B of cachline 0x0FFFFFFF, // 1st 64B of cachline 0x0FFFFFFF, // 2nd 64B of cachline 0x0FFFFFFF}, // 2nd 64B of cachline // PATTERN_3 (x8 mode) {0x056A55AA, // 1st 64B of cachline 0x056A55AA, // 1st 64B of cachline 0x0A95AA55, // 2nd 64B of cachline 0x0A95AA55}, // 2nd 64B of cachline // PATTERN_4 (x8 mode) {0x00000000, // 1st 64B of cachline 0x00000000, // 1st 64B of cachline 0x0FFFFFFF, // 2nd 64B of cachline 0x0FC0FF00}, // 2nd 64B of cachline // PATTERN_5 (x8 mode) {0x0FFFFFFF, // 1st 64B of cachline 0x0FFFFFFF, // 1st 64B of cachline 0x0ED81C6A, // 2nd 64B of cachline 0x0D970552}, // 2nd 64B of cachline // PATTERN_6 (x8 mode) {0x003F00FF, // 1st 64B of cachline 0x003F00FF, // 1st 64B of cachline 0x0FC0FF00, // 2nd 64B of cachline 0x0FC0FF00}, // 2nd 64B of cachline // PATTERN_7 (x8 mode) {0x0FC0FF00, // 1st 64B of cachline 0x0FC0FF00, // 1st 64B of cachline 0x003F00FF, // 2nd 64B of cachline 0x003F00FF}, // 2nd 64B of cachline // PATTERN_8: random {0x00000000, // 1st 64B of cachline 0x00000000, // 1st 64B of cachline 0x00000000, // 2nd 64B of cachline 0x00000000}}, // 2nd 64B of cachline // bit 4:15 ECC_c6_c5_c4, bit 16:31 ECC_c3_c2_c1_c0 // PATTERN_0 (x4 mode) {{0x00000000, // 1st 64B of cachline 0x00000000, // 1st 64B of cachline 0x00000000, // 2nd 64B of cachline 0x00000000}, // 2nd 64B of cachline // PATTERN_1 (x4 mode) {0x09978000, // 1st 64B of cachline 0x03DBC0C0, // 1st 64B of cachline 0x09978000, // 2nd 64B of cachline 0x03DBC0C0}, // 2nd 64B of cachline // PATTERN_2 (x4 mode) {0x0FFFF0F0, // 1st 64B of cachline 0x0FFFF0F0, // 1st 64B of cachline 0x0FFFF0F0, // 2nd 64B of cachline 0x0FFFF0F0}, // 2nd 64B of cachline // PATTERN_3 (x4 mode) {0x056A50A0, // 1st 64B of cachline 0x056A50A0, // 1st 64B of cachline 0x0A95A050, // 2nd 64B of cachline 0x0A95A050}, // 2nd 64B of cachline // PATTERN_4 (x4 mode) {0x00000000, // 1st 64B of cachline 0x00000000, // 1st 64B of cachline 0x0FFFF0F0, // 2nd 64B of cachline 0x0FC0F000}, // 2nd 64B of cachline // PATTERN_5 (x4 mode) {0x0FFFF0F0, // 1st 64B of cachline 0x0FFFF0F0, // 1st 64B of cachline 0x07BB8020, // 2nd 64B of cachline 0x07A4A0D0}, // 2nd 64B of cachline // PATTERN_6 (x4 mode) {0x003F00F0, // 1st 64B of cachline 0x003F00F0, // 1st 64B of cachline 0x0FC0F000, // 2nd 64B of cachline 0x0FC0F000}, // 2nd 64B of cachline // PATTERN_7 (x4 mode) {0x0FC0F000, // 1st 64B of cachline 0x0FC0F000, // 1st 64B of cachline 0x003F00F0, // 2nd 64B of cachline 0x003F00F0}, // 2nd 64B of cachline // PATTERN_8: random {0x00000000, // 1st 64B of cachline 0x00000000, // 1st 64B of cachline 0x00000000, // 2nd 64B of cachline 0x00000000}}};// 2nd 64B of cachline //------------------------------------------------------------------------------ // Function Prototypes - These are not externally called, so per RAS review, they // go in here //------------------------------------------------------------------------------ void mss_get_dummy_mark_store( const fapi::Target & i_target, uint8_t i_rank, uint8_t & o_symbolMark, uint8_t & o_chipMark, uint8_t mark_store[8][2]); void mss_put_dummy_mark_store( const fapi::Target & i_target, uint8_t i_rank, uint8_t i_symbolMark, uint8_t i_chipMark, uint8_t mark_store[8][2]); void mss_get_dummy_steer_mux( const fapi::Target & i_target, uint8_t i_rank, mss_SteerMux::muxType i_muxType, uint8_t & o_dramSparePort0Symbol, uint8_t & o_dramSparePort1Symbol, uint8_t & o_eccSpareSymbol, uint8_t steer[8][3]); void mss_put_dummy_steer_mux( const fapi::Target & i_target, uint8_t i_rank, mss_SteerMux::muxType i_muxType, uint8_t i_steerType, uint8_t i_symbol, uint8_t steer[8][3]); void mss_check_dummy_steering(const fapi::Target & i_target, uint8_t i_rank, uint8_t & o_dramSparePort0Symbol, uint8_t & o_dramSparePort1Symbol, uint8_t & o_eccSpareSymbol, uint8_t steer[8][3]); //------------------------------------------------------------------------------ // Parent class //------------------------------------------------------------------------------ //--------------------------------------------------------- // mss_MaintCmd Constructor //--------------------------------------------------------- mss_MaintCmd::mss_MaintCmd(const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, const ecmdDataBufferBase & i_endAddr, uint32_t i_stopCondition, bool i_poll, CmdType i_cmdType ) : iv_target( i_target ), iv_startAddr( i_startAddr ), iv_endAddr( i_endAddr ), iv_stopCondition( i_stopCondition), iv_poll (i_poll), iv_cmdType(i_cmdType){} //--------------------------------------------------------- // mss_stopCmd //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::stopCmd() { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_mbmsrq(64); ecmdDataBufferBase l_mbmccq(64); ecmdDataBufferBase l_mbmacaq(64); ecmdDataBufferBase l_mbspa_mask(64); ecmdDataBufferBase l_mbspa_mask_original(64); ecmdDataBufferBase l_mbspa_and(64); // 1 ms delay for HW mode const uint64_t HW_MODE_DELAY = 100000000; // 200000 sim cycle delay for SIM mode const uint64_t SIM_MODE_DELAY = 200000; uint32_t l_count = 0; uint32_t l_loop_limit = 10; FAPI_INF("ENTER mss_MaintCmd::stopCmd()"); // Read MBSPA MASK l_rc = fapiGetScom(iv_target, MBA01_MBSPAMSKQ_0x03010614, l_mbspa_mask); if(l_rc) return l_rc; // Save original mask value so we can restore it when done l_ecmd_rc |= l_mbspa_mask_original.insert(l_mbspa_mask, 0, 64, 0); // Mask bits 0 and 8, to hide the special attentions when the cmd completes l_ecmd_rc |= l_mbspa_mask.setBit(0); l_ecmd_rc |= l_mbspa_mask.setBit(8); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MBSPA MASK l_rc = fapiPutScom(iv_target, MBA01_MBSPAMSKQ_0x03010614, l_mbspa_mask); if(l_rc) return l_rc; // Read MBMSRQ l_rc = fapiGetScom(iv_target, MBA01_MBMSRQ_0x0301060C, l_mbmsrq); if(l_rc) return l_rc; // If MBMSRQ[0], maint_cmd_in_progress, stop the cmd if (l_mbmsrq.isBitSet(0)) { // Read MBMCCQ l_rc = fapiGetScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_mbmccq); if(l_rc) return l_rc; // Set bit 1 to force the cmd to stop l_ecmd_rc |= l_mbmccq.setBit(1); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MBMCCQ l_rc = fapiPutScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_mbmccq); if(l_rc) return l_rc; // Loop to check for cmd in progress bit to turn off do { // Wait 1ms fapiDelay(HW_MODE_DELAY, SIM_MODE_DELAY); // Read MBMSRQ l_rc = fapiGetScom(iv_target, MBA01_MBMSRQ_0x0301060C, l_mbmsrq); if(l_rc) return l_rc; l_count++; } while (l_mbmsrq.isBitSet(0) && (l_count < l_loop_limit)); // If cmd didn't stop as expected if (l_mbmsrq.isBitSet(0)) { FAPI_ERR("MBMSRQ[0] = 1, unsuccessful forced maint cmd stop on %s.",iv_target.toEcmdString()); // Calling out MBA target high, deconfig, gard const fapi::Target & MBA = iv_target; // FFDC: Capture register we used to stop cmd ecmdDataBufferBase & MBMCC = l_mbmccq; // FFDC: Capture register we are checking ecmdDataBufferBase & MBMSR = l_mbmsrq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_UNSUCCESSFUL_FORCED_MAINT_CMD_STOP); return l_rc; } // Else cmd is stopped else { // Clear MCMCC bit 1, just in case cmd was already stopped // before we set it, in which case, bit 1 would not have self cleared. l_ecmd_rc |= l_mbmccq.clearBit(1); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MBMCCQ l_rc = fapiPutScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_mbmccq); if(l_rc) return l_rc; } } // Store the address we stopped at in iv_startAddr l_rc = fapiGetScom(iv_target, MBA01_MBMACAQ_0x0301060D, iv_startAddr); if(l_rc) return l_rc; // Only 0-36 are valid address bits so clear the rest, 37-63 l_ecmd_rc |= iv_startAddr.clearBit(37,27); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Clear bits 0 and 8 in MBSPA AND register l_ecmd_rc |= l_mbspa_and.flushTo1(); l_ecmd_rc |= l_mbspa_and.clearBit(0); l_ecmd_rc |= l_mbspa_and.clearBit(8); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MPSPA AND register l_rc = fapiPutScom(iv_target, MBA01_MBSPAQ_AND_0x03010612, l_mbspa_and); if(l_rc) return l_rc; // Restore MBSPA MASK l_rc = fapiPutScom(iv_target, MBA01_MBSPAMSKQ_0x03010614, l_mbspa_mask_original); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::stopCmd()"); return l_rc; } //--------------------------------------------------------- // mss_cleanupCmd //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::cleanupCmd() { fapi::ReturnCode l_rc; FAPI_INF("ENTER mss_MaintCmd::cleanupCmd()"); FAPI_INF("EXIT mss_MaintCmd::cleanupCmd()"); return l_rc; } //--------------------------------------------------------- // mss_preConditionCheck //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::preConditionCheck() { fapi::ReturnCode l_rc; ecmdDataBufferBase l_mbmccq(64); ecmdDataBufferBase l_mbmsrq(64); ecmdDataBufferBase l_mbaxcr(64); ecmdDataBufferBase l_ccs_modeq(64); ecmdDataBufferBase l_mbsecc(64); ecmdDataBufferBase l_mbmct(64); FAPI_INF("ENTER mss_MaintCmd::preConditionCheck()"); // Get Centaur target for the given MBA l_rc = fapiGetParentChip(iv_target, iv_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA on %s.",iv_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &iv_target, iv_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",iv_target.toEcmdString()); return l_rc; } // Read MBMCCQ l_rc = fapiGetScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_mbmccq); if(l_rc) return l_rc; // Read MBMSRQ l_rc = fapiGetScom(iv_target, MBA01_MBMSRQ_0x0301060C, l_mbmsrq); if(l_rc) return l_rc; // Read MBAXCRn l_rc = fapiGetScom(iv_targetCentaur, mss_mbaxcr[iv_mbaPosition], l_mbaxcr); if(l_rc) return l_rc; // Read CCS_MODEQ l_rc = fapiGetScom(iv_target, MEM_MBA01_CCS_MODEQ_0x030106A7, l_ccs_modeq); if(l_rc) return l_rc; // Read MBSECC l_rc = fapiGetScom(iv_targetCentaur, mss_mbsecc[iv_mbaPosition], l_mbsecc); if(l_rc) return l_rc; // Read MBMCT[0:4], cmd type, for FFDC l_rc = fapiGetScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_mbmct); if(l_rc) return l_rc; // Check for MBMCCQ[0], maint_cmd_start, to be reset by hw. if (l_mbmccq.isBitSet(0)) { FAPI_ERR("MBMCCQ[0]: maint_cmd_start not reset by hw on %s.",iv_target.toEcmdString()); // Calling out MBA target high, deconfig, gard const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBMCC = l_mbmccq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // FFDC: MBMCT[0:4] contains the cmd type previously run ecmdDataBufferBase & MBMCT = l_mbmct; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_START_NOT_RESET); } // Check for MBMCCQ[1], maint_cmd_stop, to be reset by hw. if (l_mbmccq.isBitSet(1)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("MBMCCQ[1]: maint_cmd_stop not reset by hw on %s.",iv_target.toEcmdString()); // Calling out MBA target high, deconfig, gard const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBMCC = l_mbmccq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // FFDC: MBMCT[0:4] contains the cmd type previously run ecmdDataBufferBase & MBMCT = l_mbmct; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_STOP_NOT_RESET); } // Check for MBMSRQ[0], maint_cmd_in_progress, to be reset. if (l_mbmsrq.isBitSet(0)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("MBMSRQ[0]: Can't start new cmd if previous cmd still in progress on %s.",iv_target.toEcmdString()); // Calling out FW high // Calling out MBA target low, deconfig, gard const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBMSR = l_mbmsrq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // FFDC: MBMCT[0:4] contains the cmd type previously run ecmdDataBufferBase & MBMCT = l_mbmct; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_CMD_IN_PROGRESS); } // Check MBAXCRn, to show memory configured behind this MBA if (l_mbaxcr.isBitClear(0,4)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("MBAXCRn[0:3] = 0, meaning no memory configured behind this MBA on %s.",iv_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBAXCR = l_mbaxcr; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_NO_MEM_CNFG); } // Check CCS_MODEQ[29] to make sure mux switched from CCS to mainline if (l_ccs_modeq.isBitSet(29)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("CCS_MODEQ[29] = 1, meaning mux set for CCS instead of mainline on %s.",iv_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & CCS_MODE = l_ccs_modeq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_CCS_MUX_NOT_MAINLINE); } // Check MBSECC[0] = 0, to make sure ECC check/correct is enabled if (l_mbsecc.isBitSet(0)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("MBSECC[0] = 1, meaning ECC check/correct disabled on %s.",iv_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBSECC = l_mbsecc; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_ECC_DISABLED); } FAPI_INF("EXIT mss_MaintCmd::preConditionCheck()"); return l_rc; } //--------------------------------------------------------- // mss_loadCmdType //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::loadCmdType() { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); uint8_t l_dram_gen; FAPI_INF("ENTER mss_MaintCmd::loadCmdType()"); // Get DDR3/DDR4: ATTR_EFF_DRAM_GEN // 0x01 = ENUM_ATTR_EFF_DRAM_GEN_DDR3 // 0x02 = ENUM_ATTR_EFF_DRAM_GEN_DDR4 l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &iv_target, l_dram_gen); if(l_rc) { FAPI_ERR("Error getting DDR3/DDR4 on %s.", iv_target.toEcmdString()); return l_rc; } l_rc = fapiGetScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_data); if(l_rc) return l_rc; l_ecmd_rc |= l_data.insert( (uint32_t)iv_cmdType, 0, 5, 32-5 ); // Setting super fast address increment mode for DDR3, where COL bits are LSB. Valid for all cmds. // NOTE: Super fast address increment mode is broken for DDR4 due to DD1 bug if (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3) { l_ecmd_rc |= l_data.setBit(5); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } } l_rc = fapiPutScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_data); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::loadCmdType()"); return l_rc; } //--------------------------------------------------------- // mss_loadStartAddress //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::loadStartAddress() { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); FAPI_INF("ENTER mss_MaintCmd::loadStartAddress()"); l_rc = fapiGetScom(iv_target, MBA01_MBMACAQ_0x0301060D, l_data); if(l_rc) return l_rc; // Load address bits 0:39 l_ecmd_rc |= l_data.insert( iv_startAddr, 0, 40, 0 ); // Clear error status bits 40:46 l_ecmd_rc |= l_data.clearBit(40,7); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBMACAQ_0x0301060D, l_data); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::loadStartAddress()"); return l_rc; } //--------------------------------------------------------- // mss_loadEndAddress //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::loadEndAddress() { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); FAPI_INF("ENTER mss_MaintCmd::loadEndAddress()"); l_rc = fapiGetScom(iv_target, MBA01_MBMEAQ_0x0301060E, l_data); if(l_rc) return l_rc; l_ecmd_rc |= l_data.insert( iv_endAddr, 0, 40, 0 ); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBMEAQ_0x0301060E, l_data); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::loadEndAddress()"); return l_rc; } //--------------------------------------------------------- // mss_loadStopCondMask //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::loadStopCondMask() { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_mbasctlq(64); uint8_t l_mbspa_0_fixed_for_dd2 = 0; FAPI_INF("ENTER mss_MaintCmd::loadStopCondMask()"); // Get attribute that tells us if mbspa 0 cmd complete attention is fixed for dd2 l_rc = FAPI_ATTR_GET(ATTR_CENTAUR_EC_HW217608_MBSPA_0_CMD_COMPLETE_ATTN_FIXED, &iv_targetCentaur, l_mbspa_0_fixed_for_dd2); if(l_rc) { FAPI_ERR("Error getting ATTR_CENTAUR_EC_HW217608_MBSPA_0_CMD_COMPLETE_ATTN_FIXED"); return l_rc; } // Get stop conditions from MBASCTLQ l_rc = fapiGetScom(iv_target, MBA01_MBASCTLQ_0x0301060F, l_mbasctlq); if(l_rc) return l_rc; // Start by clearing all bits 0:12 and bit 16 l_ecmd_rc |= l_mbasctlq.clearBit(0,13); l_ecmd_rc |= l_mbasctlq.clearBit(16); // Enable stop immediate if ( 0 != (iv_stopCondition & STOP_IMMEDIATE) ) l_ecmd_rc |= l_mbasctlq.setBit(0); // Enable stop end of rank if ( 0 != (iv_stopCondition & STOP_END_OF_RANK) ) l_ecmd_rc |= l_mbasctlq.setBit(1); // Stop on hard NCE ETE if ( 0 != (iv_stopCondition & STOP_ON_HARD_NCE_ETE) ) l_ecmd_rc |= l_mbasctlq.setBit(2); // Stop on intermittent NCE ETE if ( 0 != (iv_stopCondition & STOP_ON_INT_NCE_ETE) ) l_ecmd_rc |= l_mbasctlq.setBit(3); // Stop on soft NCE ETE if ( 0 != (iv_stopCondition & STOP_ON_SOFT_NCE_ETE) ) l_ecmd_rc |= l_mbasctlq.setBit(4); // Stop on SCE if ( 0 != (iv_stopCondition & STOP_ON_SCE) ) l_ecmd_rc |= l_mbasctlq.setBit(5); // Stop on MCE if ( 0 != (iv_stopCondition & STOP_ON_MCE) ) l_ecmd_rc |= l_mbasctlq.setBit(6); // Stop on retry CE ETE if ( 0 != (iv_stopCondition & STOP_ON_RETRY_CE_ETE) ) l_ecmd_rc |= l_mbasctlq.setBit(7); // Stop on MPE if ( 0 != (iv_stopCondition & STOP_ON_MPE) ) l_ecmd_rc |= l_mbasctlq.setBit(8); // Stop on UE if ( 0 != (iv_stopCondition & STOP_ON_UE) ) l_ecmd_rc |= l_mbasctlq.setBit(9); // Stop on end address if ( 0 != (iv_stopCondition & STOP_ON_END_ADDRESS) ) l_ecmd_rc |= l_mbasctlq.setBit(10); // Enable command complete attention if ( 0 != (iv_stopCondition & ENABLE_CMD_COMPLETE_ATTENTION) ) l_ecmd_rc |= l_mbasctlq.setBit(11); // Stop on SUE if ( 0 != (iv_stopCondition & STOP_ON_SUE) ) l_ecmd_rc |= l_mbasctlq.setBit(12); // Command complete attention on clean and error // DD2: enable (fixed) // DD1: disable (broken) if (l_mbspa_0_fixed_for_dd2) { l_ecmd_rc |= l_mbasctlq.setBit(16); } if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write stop conditions to MBASCTLQ l_rc = fapiPutScom(iv_target, MBA01_MBASCTLQ_0x0301060F, l_mbasctlq); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::loadStopCondMask()"); return l_rc; } //--------------------------------------------------------- // mss_startMaintCmd //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::startMaintCmd() { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); FAPI_INF("ENTER mss_MaintCmd::startMaintCmd()"); l_rc = fapiGetScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_data); if(l_rc) return l_rc; l_ecmd_rc |= l_data.setBit(0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_data); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::startMaintCmd()"); return l_rc; } //--------------------------------------------------------- // mss_postConditionCheck //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::postConditionCheck() { fapi::ReturnCode l_rc; ecmdDataBufferBase l_mbmccq(64); ecmdDataBufferBase l_mbafirq(64); ecmdDataBufferBase l_mbmct(64); FAPI_INF("ENTER mss_MaintCmd::postConditionCheck()"); // Read MBMCCQ l_rc = fapiGetScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_mbmccq); if(l_rc) return l_rc; // Read MBAFIRQ l_rc = fapiGetScom(iv_target, MBA01_MBAFIRQ_0x03010600, l_mbafirq); if(l_rc) return l_rc; // Read MBMCT[0:4], cmd type, for FFDC l_rc = fapiGetScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_mbmct); if(l_rc) return l_rc; // Check for MBMCCQ[0], maint_cmd_start, to be reset by hw. if (l_mbmccq.isBitSet(0)) { FAPI_ERR("MBMCCQ[0]: maint_cmd_start not reset by hw on %s.",iv_target.toEcmdString()); // Calling out MBA target high, deconfig, gard const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBMCC = l_mbmccq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // FFDC: MBMCT[0:4] contains the cmd type set in hw ecmdDataBufferBase & MBMCT = l_mbmct; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_START_NOT_RESET); } // Check for MBAFIRQ[0], invalid_maint_cmd. if (l_mbafirq.isBitSet(0)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("MBAFIRQ[0], invalid_maint_cmd on %s.",iv_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBAFIR = l_mbafirq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // FFDC: MBMCT[0:4] contains the cmd type set in hw ecmdDataBufferBase & MBMCT = l_mbmct; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_CMD); } // Check for MBAFIRQ[1], invalid_maint_address. if (l_mbafirq.isBitSet(1)) { // Log previous error before creating new log if (l_rc) fapiLogError(l_rc); FAPI_ERR("MBAFIRQ[1], cmd started with invalid_maint_address on %s.",iv_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = iv_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBAFIR = l_mbafirq; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // FFDC: MBMCT[0:4] contains the cmd type set in hw ecmdDataBufferBase & MBMCT = l_mbmct; // NOTE: List of additional FFDC regs specified in memory_errors.xml // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_ADDR); } FAPI_INF("EXIT mss_MaintCmd::postConditionCheck()"); return l_rc; } //--------------------------------------------------------- // mss_pollForMaintCmdComplete //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::pollForMaintCmdComplete() { fapi::ReturnCode l_rc; ecmdDataBufferBase l_data(64); FAPI_INF("ENTER mss_MaintCmd::pollForMaintCmdComplete()"); uint32_t count = 0; // 1 ms delay for HW mode const uint64_t HW_MODE_DELAY = 100000000; // 200000 sim cycle delay for SIM mode const uint64_t SIM_MODE_DELAY = 200000; uint32_t loop_limit = 50000; do { fapiDelay(HW_MODE_DELAY, SIM_MODE_DELAY); // Want to see cmd complete attention l_rc = fapiGetScom(iv_target, MBA01_MBSPAQ_0x03010611, l_data); if(l_rc) return l_rc; FAPI_DBG("MBSPAQ = 0x%.8X 0x%.8X",l_data.getWord(0), l_data.getWord(1)); // Read MBMACAQ just to see if it's incrementing l_rc = fapiGetScom(iv_target, MBA01_MBMACAQ_0x0301060D, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMACAQ = 0x%.8X 0x%.8X",l_data.getWord(0), l_data.getWord(1)); // Waiting for MBMSRQ[0] maint cmd in progress bit to turn off l_rc = fapiGetScom(iv_target, MBA01_MBMSRQ_0x0301060C, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMSRQ = 0x%.8X 0x%.8X",l_data.getWord(0), l_data.getWord(1)); count++; } // Poll until cmd in progress bit goes off while (l_data.isBitSet(0) && (count < loop_limit)); if (count == loop_limit) { FAPI_ERR("Maint cmd timeout on %s.",iv_target.toEcmdString()); // Calling out FW high // Calling out MBA target low, deconfig, gard const fapi::Target & MBA = iv_target; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // Specify CENTAUR target so we can read some FFDC regs from MBS const fapi::Target & CENTAUR = iv_targetCentaur; // NOTE: List of additional FFDC regs specified in memory_errors.xml // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_CMD_TIMEOUT); } else { FAPI_INF("Maint cmd complete. "); } FAPI_INF("EXIT mss_MaintCmd::pollForMaintCmdComplete()"); return l_rc; } //--------------------------------------------------------- // mss_collectFFDC //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::collectFFDC() { fapi::ReturnCode l_rc; ecmdDataBufferBase l_data(64); uint8_t l_dramSparePort0Symbol = MSS_INVALID_SYMBOL; uint8_t l_dramSparePort1Symbol = MSS_INVALID_SYMBOL; uint8_t l_eccSpareSymbol = MSS_INVALID_SYMBOL; uint8_t l_symbol_mark = MSS_INVALID_SYMBOL; uint8_t l_chip_mark = MSS_INVALID_SYMBOL; FAPI_INF("ENTER mss_MaintCmd::collectFFDC()"); l_rc = fapiGetScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMCTQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBMACAQ_0x0301060D, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMACAQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); // Print out error status bits from MBMACAQ if (l_data.isBitSet(40)) FAPI_DBG("MBMACAQ error status: 40:NCE"); if (l_data.isBitSet(41)) FAPI_DBG("MBMACAQ error status: 41:SCE"); if (l_data.isBitSet(42)) FAPI_DBG("MBMACAQ error status: 42:MCE"); if (l_data.isBitSet(43)) FAPI_DBG("MBMACAQ error status: 43:RCE"); if (l_data.isBitSet(44)) FAPI_DBG("MBMACAQ error status: 44:MPE"); if (l_data.isBitSet(45)) FAPI_DBG("MBMACAQ error status: 45:UE"); if (l_data.isBitSet(46)) FAPI_DBG("MBMACAQ error status: 46:SUE"); l_rc = fapiGetScom(iv_target, MBA01_MBMEAQ_0x0301060E, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMEAQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBASCTLQ_0x0301060F, l_data); if(l_rc) return l_rc; FAPI_DBG("MBASCTLQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBMCCQ_0x0301060B, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMCCQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBMSRQ_0x0301060C, l_data); if(l_rc) return l_rc; FAPI_DBG("MBMSRQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBAFIRQ_0x03010600, l_data); if(l_rc) return l_rc; FAPI_DBG("MBAFIRQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBSPAQ_0x03010611, l_data); if(l_rc) return l_rc; FAPI_DBG("MBSPAQ = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_target, MBA01_MBACALFIR_0x03010400, l_data); if(l_rc) return l_rc; FAPI_DBG("MBACALFIR = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); l_rc = fapiGetScom(iv_targetCentaur, mss_mbeccfir[iv_mbaPosition], l_data); if(l_rc) return l_rc; FAPI_DBG("MBECCFIR = 0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); // Print out maint ECC FIR bits from MBECCFIR if (l_data.isBitSet(20)) FAPI_DBG("20:Maint MPE, rank0"); if (l_data.isBitSet(21)) FAPI_DBG("21:Maint MPE, rank1"); if (l_data.isBitSet(22)) FAPI_DBG("22:Maint MPE, rank2"); if (l_data.isBitSet(23)) FAPI_DBG("23:Maint MPE, rank3"); if (l_data.isBitSet(24)) FAPI_DBG("24:Maint MPE, rank4"); if (l_data.isBitSet(25)) FAPI_DBG("25:Maint MPE, rank5"); if (l_data.isBitSet(26)) FAPI_DBG("26:Maint MPE, rank6"); if (l_data.isBitSet(27)) FAPI_DBG("27:Maint MPE, rank7"); if (l_data.isBitSet(36)) FAPI_DBG("36: Maint NCE"); if (l_data.isBitSet(37)) FAPI_DBG("37: Maint SCE"); if (l_data.isBitSet(38)) FAPI_DBG("38: Maint MCE"); if (l_data.isBitSet(39)) FAPI_DBG("39: Maint RCE"); if (l_data.isBitSet(40)) FAPI_DBG("40: Maint SUE"); if (l_data.isBitSet(41)) FAPI_DBG("41: Maint UE"); FAPI_DBG("Markstore"); for ( uint8_t i = 0; i < MSS_MAX_RANKS; i++ ) { l_rc = fapiGetScom(iv_targetCentaur, mss_markStoreRegs[i][iv_mbaPosition], l_data); if(l_rc) return l_rc; FAPI_DBG("MBMS%d = 0x%.8X 0x%.8X",i, l_data.getWord(0), l_data.getWord(1)); } for ( uint8_t i = 0; i < MSS_MAX_RANKS; i++ ) { l_rc = mss_get_mark_store(iv_target, i, l_symbol_mark, l_chip_mark ); if (l_rc) { FAPI_ERR("Error reading markstore on %s.",iv_target.toEcmdString()); return l_rc; } } FAPI_DBG("Steer MUXES"); for ( uint8_t i = 0; i < MSS_MAX_RANKS; i++ ) { l_rc = mss_check_steering(iv_target, i, l_dramSparePort0Symbol, l_dramSparePort1Symbol, l_eccSpareSymbol); if(l_rc) return l_rc; } FAPI_INF("EXIT mss_MaintCmd::collectFFDC()"); return l_rc; } //--------------------------------------------------------- // mss_loadPattern //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::loadPattern(PatternIndex i_initPattern) { FAPI_INF("ENTER mss_MaintCmd::loadPattern()"); static const uint32_t maintBufferDataRegs[2][16][2]={ // port0 {{MAINT0_MBS_MAINT_BUFF0_DATA0_0x0201160A, MAINT0_MBS_MAINT_BUFF0_DATA_ECC0_0x02011612},// DW0 {MAINT0_MBS_MAINT_BUFF2_DATA0_0x0201162A, MAINT0_MBS_MAINT_BUFF2_DATA_ECC0_0x02011632}, // DW2 {MAINT0_MBS_MAINT_BUFF0_DATA1_0x0201160B, MAINT0_MBS_MAINT_BUFF0_DATA_ECC1_0x02011613}, // DW4 {MAINT0_MBS_MAINT_BUFF2_DATA1_0x0201162B, MAINT0_MBS_MAINT_BUFF2_DATA_ECC1_0x02011633}, // DW6 {MAINT0_MBS_MAINT_BUFF0_DATA2_0x0201160C, MAINT0_MBS_MAINT_BUFF0_DATA_ECC2_0x02011614}, // DW8 {MAINT0_MBS_MAINT_BUFF2_DATA2_0x0201162C, MAINT0_MBS_MAINT_BUFF2_DATA_ECC2_0x02011634}, // DW10 {MAINT0_MBS_MAINT_BUFF0_DATA3_0x0201160D, MAINT0_MBS_MAINT_BUFF0_DATA_ECC3_0x02011615}, // DW12 {MAINT0_MBS_MAINT_BUFF2_DATA3_0x0201162D, MAINT0_MBS_MAINT_BUFF2_DATA_ECC3_0x02011635}, // DW14 // port1 {MAINT0_MBS_MAINT_BUFF1_DATA0_0x0201161A, MAINT0_MBS_MAINT_BUFF1_DATA_ECC0_0x02011622}, // DW1 {MAINT0_MBS_MAINT_BUFF3_DATA0_0x0201163A, MAINT0_MBS_MAINT_BUFF3_DATA_ECC0_0x02011642}, // DW3 {MAINT0_MBS_MAINT_BUFF1_DATA1_0x0201161B, MAINT0_MBS_MAINT_BUFF1_DATA_ECC1_0x02011623}, // DW5 {MAINT0_MBS_MAINT_BUFF3_DATA1_0x0201163B, MAINT0_MBS_MAINT_BUFF3_DATA_ECC1_0x02011643}, // DW7 {MAINT0_MBS_MAINT_BUFF1_DATA2_0x0201161C, MAINT0_MBS_MAINT_BUFF1_DATA_ECC2_0x02011624}, // DW9 {MAINT0_MBS_MAINT_BUFF3_DATA2_0x0201163C, MAINT0_MBS_MAINT_BUFF3_DATA_ECC2_0x02011644}, // DW11 {MAINT0_MBS_MAINT_BUFF1_DATA3_0x0201161D, MAINT0_MBS_MAINT_BUFF1_DATA_ECC3_0x02011625}, // DW13 {MAINT0_MBS_MAINT_BUFF3_DATA3_0x0201163D, MAINT0_MBS_MAINT_BUFF3_DATA_ECC3_0x02011645}},// DW15 // port2 {{MAINT1_MBS_MAINT_BUFF0_DATA0_0x0201170A, MAINT1_MBS_MAINT_BUFF0_DATA_ECC0_0x02011712},// DW0 {MAINT1_MBS_MAINT_BUFF2_DATA0_0x0201172A, MAINT1_MBS_MAINT_BUFF2_DATA_ECC0_0x02011732}, // DW2 {MAINT1_MBS_MAINT_BUFF0_DATA1_0x0201170B, MAINT1_MBS_MAINT_BUFF0_DATA_ECC1_0x02011713}, // DW4 {MAINT1_MBS_MAINT_BUFF2_DATA1_0x0201172B, MAINT1_MBS_MAINT_BUFF2_DATA_ECC1_0x02011733}, // DW6 {MAINT1_MBS_MAINT_BUFF0_DATA2_0x0201170C, MAINT1_MBS_MAINT_BUFF0_DATA_ECC2_0x02011714}, // DW8 {MAINT1_MBS_MAINT_BUFF2_DATA2_0x0201172C, MAINT1_MBS_MAINT_BUFF2_DATA_ECC2_0x02011734}, // DW10 {MAINT1_MBS_MAINT_BUFF0_DATA3_0x0201170D, MAINT1_MBS_MAINT_BUFF0_DATA_ECC3_0x02011715}, // DW12 {MAINT1_MBS_MAINT_BUFF2_DATA3_0x0201172D, MAINT1_MBS_MAINT_BUFF2_DATA_ECC3_0x02011735}, // DW14 // port3 {MAINT1_MBS_MAINT_BUFF1_DATA0_0x0201171A, MAINT1_MBS_MAINT_BUFF1_DATA_ECC0_0x02011722}, // DW1 {MAINT1_MBS_MAINT_BUFF3_DATA0_0x0201173A, MAINT1_MBS_MAINT_BUFF3_DATA_ECC0_0x02011742}, // DW3 {MAINT1_MBS_MAINT_BUFF1_DATA1_0x0201171B, MAINT1_MBS_MAINT_BUFF1_DATA_ECC1_0x02011723}, // DW5 {MAINT1_MBS_MAINT_BUFF3_DATA1_0x0201173B, MAINT1_MBS_MAINT_BUFF3_DATA_ECC1_0x02011743}, // DW6 {MAINT1_MBS_MAINT_BUFF1_DATA2_0x0201171C, MAINT1_MBS_MAINT_BUFF1_DATA_ECC2_0x02011724}, // DW9 {MAINT1_MBS_MAINT_BUFF3_DATA2_0x0201173C, MAINT1_MBS_MAINT_BUFF3_DATA_ECC2_0x02011744}, // DW11 {MAINT1_MBS_MAINT_BUFF1_DATA3_0x0201171D, MAINT1_MBS_MAINT_BUFF1_DATA_ECC3_0x02011725}, // DW13 {MAINT1_MBS_MAINT_BUFF3_DATA3_0x0201173D, MAINT1_MBS_MAINT_BUFF3_DATA_ECC3_0x02011745}}};// DW15 static const uint32_t maintBuffer65thRegs[4][2]={ // MBA01 MBA23 {MAINT0_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC0_0x0201164A, MAINT1_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC0_0x0201174A}, // 1st 64B of cacheline {MAINT0_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC1_0x0201164B, MAINT1_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC1_0x0201174B}, // 1st 64B of cacheline {MAINT0_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC2_0x0201164C, MAINT1_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC2_0x0201174C}, // 2nd 64B of cacheline {MAINT0_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC3_0x0201164D, MAINT1_MBS_MAINT_BUFF_65TH_BYTE_64B_ECC3_0x0201174D}};// 2nd 64B of cacheline fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); ecmdDataBufferBase l_ecc(64); ecmdDataBufferBase l_65th(64); ecmdDataBufferBase l_mbmmr(64); ecmdDataBufferBase l_mbsecc(64); uint32_t loop = 0; uint8_t l_dramWidth = 0; FAPI_INF("pattern = 0x%.8X 0x%.8X", mss_maintBufferData[l_dramWidth][i_initPattern][0][0], mss_maintBufferData[l_dramWidth][i_initPattern][0][1]); //---------------------------------------------------- // Get l_dramWidth //---------------------------------------------------- l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &iv_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",iv_target.toEcmdString()); return l_rc; } // Convert from attribute enum values: 8,4 to index values: 0,1 if(l_dramWidth == mss_MemConfig::X8) { l_dramWidth = 0; } else { l_dramWidth = 1; } //---------------------------------------------------- // Load the data: 16 loops x 64bits = 128B cacheline //---------------------------------------------------- FAPI_INF("Load the data: 16 loops x 64bits = 128B cacheline"); // Set bit 9 so that hw will generate the fabric ECC. // This is an 8B ECC protecting the data moving on internal buses in // the Centaur. l_ecmd_rc |= l_ecc.flushTo0(); l_ecmd_rc |= l_ecc.setBit(9); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } for(loop=0; loop<16; loop++ ) { // A write to MAINT_BUFFx_DATAy will not update until the corresponding // MAINT_BUFFx_DATA_ECCy is written to. l_ecmd_rc |= l_data.insert(mss_maintBufferData[l_dramWidth][i_initPattern][loop][0], 0, 32, 0); l_ecmd_rc |= l_data.insert(mss_maintBufferData[l_dramWidth][i_initPattern][loop][1], 32, 32, 0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_targetCentaur, maintBufferDataRegs[iv_mbaPosition][loop][0], l_data); if(l_rc) return l_rc; l_rc = fapiPutScom(iv_targetCentaur, maintBufferDataRegs[iv_mbaPosition][loop][1], l_ecc); if(l_rc) return l_rc; } //---------------------------------------------------- // Load the 65th byte: 4 loops to fill in the two 65th bytes in cacheline //---------------------------------------------------- FAPI_INF("Load the 65th byte: 4 loops to fill in the two 65th bytes in the cacheline"); l_ecmd_rc |= l_65th.flushTo0(); // Set bit 56 so that hw will generate the fabric ECC. // This is an 8B ECC protecting the data moving on internal buses in Centaur. l_ecmd_rc |= l_65th.setBit(56); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } for(loop=0; loop<4; loop++ ) { l_ecmd_rc |= l_65th.insert(mss_65thByte[l_dramWidth][i_initPattern][loop], 1, 3, 1); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_targetCentaur, maintBuffer65thRegs[loop][iv_mbaPosition], l_65th); if(l_rc) return l_rc; } //---------------------------------------------------- // Save i_initPattern in unused maint mark reg // so we know what pattern was used when we do // UE isolation //---------------------------------------------------- // No plans to use maint mark, but make sure it's disabled to be safe l_rc = fapiGetScom(iv_targetCentaur, mss_mbsecc[iv_mbaPosition], l_mbsecc); if(l_rc) return l_rc; l_ecmd_rc |= l_mbsecc.clearBit(4); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } uint8_t l_attr_centaur_ec_enable_rce_with_other_errors_hw246685; l_rc = FAPI_ATTR_GET(ATTR_CENTAUR_EC_ENABLE_RCE_WITH_OTHER_ERRORS_HW246685, &iv_targetCentaur, l_attr_centaur_ec_enable_rce_with_other_errors_hw246685); if(l_rc) return l_rc; if(l_attr_centaur_ec_enable_rce_with_other_errors_hw246685) { l_ecmd_rc = l_ecmd_rc | l_mbsecc.setBit(16); } if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_targetCentaur, mss_mbsecc[iv_mbaPosition], l_mbsecc); if(l_rc) return l_rc; l_ecmd_rc |= l_mbmmr.flushTo0(); // Store i_initPattern, with range 0-8, in MBMMR bits 4-7 l_ecmd_rc |= l_mbmmr.insert((uint8_t)i_initPattern, 4, 4, 8-4); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_targetCentaur, mss_mbmmr[iv_mbaPosition] , l_mbmmr); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::loadPattern()"); return l_rc; } //--------------------------------------------------------- // mss_loadSpeed //--------------------------------------------------------- fapi::ReturnCode mss_MaintCmd::loadSpeed(TimeBaseSpeed i_speed) { FAPI_INF("ENTER mss_MaintCmd::loadSpeed()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); uint32_t l_ddr_freq = 0; uint64_t l_step_size = 0; uint64_t l_num_address_bits = 0; uint64_t l_num_addresses = 0; uint64_t l_address_bit = 0; ecmdDataBufferBase l_start_address(64); ecmdDataBufferBase l_end_address(64); uint64_t l_cmd_interval = 0; // burst_window_sel // MBMCTQ[6]: 0 = 512 Maint Clks // 1 = 536870912 Maint Clks uint8_t l_burst_window_sel = 0; // timebase_sel // MBMCTQ[9:10]: 00 = 1 Maint Clk // 01 = 8192 Maint clks uint8_t l_timebase_sel = 0; // timebase_burst_sel // MBMCTQ[11]: 0 = disable burst mode // 1 = enable burst mode uint8_t l_timebase_burst_sel = 0; // timebase_interval // MBMCTQ[12:23]: The operation interval for timebase operations // equals the timebase_sel x MBMCTQ[12:23]. // NOTE: Should never be 0, or will hang mainline traffic. uint32_t l_timebase_interval = 1; // burst_window // MBMCTQ[24:31]: The burst window for timebase operations with burst mode // enabled equals burst_window_sel x MBMCTQ[24:31] uint8_t l_burst_window = 0; // burst_interval // MBMCTQ[32:39]: The burst interval for timebase operations with burst mode // enabled equals the number of burst windows that will have // no operations occurring in them. uint8_t l_burst_interval = 0; l_rc = fapiGetScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_data); if(l_rc) return l_rc; if (FAST_MAX_BW_IMPACT == i_speed) { l_timebase_sel = 0; l_timebase_interval = 1; } else if (FAST_MED_BW_IMPACT == i_speed) { l_timebase_sel = 0; l_timebase_interval = 512; } else if (FAST_MIN_BW_IMPACT == i_speed) { l_timebase_sel = 1; l_timebase_interval = 12; } else // BG_SCRUB { // Get l_ddr_freq from ATTR_MSS_FREQ // Possible frequencies are 800, 1066, 1333, 1600, 1866, and 2133 MHz // NOTE: Max 32 address bits using 800 and 1066 result in scrub // taking longer than 12h, but these is no plan to actually use // those frequencies. l_rc = FAPI_ATTR_GET( ATTR_MSS_FREQ, &iv_targetCentaur, l_ddr_freq); if (l_rc) { FAPI_ERR("Failed to get attribute: ATTR_MSS_FREQ on %s.",iv_target.toEcmdString()); return l_rc; } // Make sure it's non-zero, to avoid divide by 0 if (l_ddr_freq == 0) { FAPI_ERR("ATTR_MSS_FREQ set to zero so can't calculate scrub rate on %s.",iv_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = iv_target; // FFDC: Capture command type we are trying to run const mss_MaintCmd::CmdType & CMD_TYPE = iv_cmdType; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_ZERO_DDR_FREQ); return l_rc; } // l_timebase_sel // MBMCTQ[9:10]: 00 = 1 * Maint Clk // 01 = 8192 * Maint Clk // Where Maint Clk = 2/1_ddr_freq l_timebase_sel = 1; // Get l_step_size in nSec l_step_size = 8192*2*1000/l_ddr_freq; FAPI_DBG("l_ddr_freq = %d MHz, l_step_size = %d nSec", (uint32_t)l_ddr_freq, (uint32_t)l_step_size); // Get l_end_address l_rc = mss_get_address_range( iv_target, MSS_ALL_RANKS, l_start_address, l_end_address ); if (l_rc) { FAPI_ERR("mss_get_address_range failed on %s.",iv_target.toEcmdString()); return l_rc; } // Get l_num_address_bits by counting bits set to 1 in l_end_address. for(l_address_bit=0; l_address_bit<37; l_address_bit++ ) { if(l_end_address.isBitSet(l_address_bit)) { l_num_address_bits++; } } // NOTE: Assumption is max 32 address bits, which can be done // in 12h (+/- 2h). More than 32 address bits would // double scrub time for every extra address bit. if (l_num_address_bits > 32) { FAPI_INF("WARNING: l_num_address_bits: %d, is greater than 32, so scrub will take longer than 12h.",(uint32_t)l_num_address_bits); } // NOTE: Smallest number of address bits is supposed to be 25. // So if for some reason it's less (like in VBU), // use 25 anyway so the scrub rate calculation still works. if (l_num_address_bits < 25) { FAPI_INF("WARNING: l_num_address_bits: %d, is less than 25, but using 25 in calculation anyway.",(uint32_t)l_num_address_bits); l_num_address_bits = 25; } // Get l_num_addresses l_num_addresses = 1; for(uint32_t i=0; i= l_step_size/2) ? 1:0; // Make sure smallest is 1 if (l_timebase_interval == 0) l_timebase_interval = 1; FAPI_DBG("l_num_address_bits = %d, l_num_addresses = %d (M), l_cmd_interval = %d nSec, l_timebase_interval = %d", (uint32_t)l_num_address_bits, (uint32_t)l_num_addresses, (uint32_t)l_cmd_interval, (uint32_t)l_timebase_interval); } // End BG_SCRUB // burst_window_sel // MBMCTQ[6] l_ecmd_rc |= l_data.insert( l_burst_window_sel, 6, 1, 8-1 ); // timebase_sel // MBMCTQ[9:10] l_ecmd_rc |= l_data.insert( l_timebase_sel, 9, 2, 8-2 ); // timebase_burst_sel // MBMCTQ[11] l_ecmd_rc |= l_data.insert( l_timebase_burst_sel, 11, 1, 8-1 ); // timebase_interval // MBMCTQ[12:23] l_ecmd_rc |= l_data.insert( l_timebase_interval, 12, 12, 32-12 ); // burst_window // MBMCTQ[24:31] l_ecmd_rc |= l_data.insert( l_burst_window, 24, 8, 8-8 ); // burst_interval // MBMCTQ[32:39] l_ecmd_rc |= l_data.insert( l_burst_interval, 32, 8, 8-8 ); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBMCTQ_0x0301060A, l_data); if(l_rc) return l_rc; FAPI_INF("EXIT mss_MaintCmd::loadSpeed()"); return l_rc; } //------------------------------------------------------------------------------ // Child classes //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // SuperFastInit //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_SuperFastInit::cv_cmdType = SUPERFAST_INIT; //--------------------------------------------------------- // mss_SuperFastInit Constructor //--------------------------------------------------------- mss_SuperFastInit::mss_SuperFastInit( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, const ecmdDataBufferBase & i_endAddr, PatternIndex i_initPattern, uint32_t i_stopCondition, bool i_poll ) : mss_MaintCmd( i_target, i_startAddr, i_endAddr, i_stopCondition, i_poll, cv_cmdType), iv_initPattern( i_initPattern ) // NOTE: iv_initPattern is instance // variable of SuperFastInit, since not // needed in parent class {} //--------------------------------------------------------- // mss_SuperFastInit setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_SuperFastInit::setupAndExecuteCmd() { FAPI_INF("ENTER mss_SuperFastInit::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; ecmdDataBufferBase l_data(64); // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load pattern l_rc = loadPattern(iv_initPattern); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load end address: MBMEAQ l_rc = loadEndAddress(); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; if(iv_poll == false) { FAPI_INF("Cmd has started. Use attentions to detect cmd complete."); FAPI_INF("EXIT mss_SuperFastInit::setupAndExecuteCmd()"); return l_rc; } // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT mss_SuperFastInit::setupAndExecuteCmd()"); return l_rc; } //------------------------------------------------------------------------------ // mss_SuperFastRandomInit //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_SuperFastRandomInit::cv_cmdType = SUPERFAST_RANDOM_INIT; //--------------------------------------------------------- // mss_SuperFastInit Constructor //--------------------------------------------------------- mss_SuperFastRandomInit::mss_SuperFastRandomInit( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, const ecmdDataBufferBase & i_endAddr, PatternIndex i_initPattern, uint32_t i_stopCondition, bool i_poll ) : mss_MaintCmd( i_target, i_startAddr, i_endAddr, i_stopCondition, i_poll, cv_cmdType), iv_initPattern( i_initPattern ) {} //--------------------------------------------------------- // mss_SuperFastRandomInit setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_SuperFastRandomInit::setupAndExecuteCmd() { FAPI_INF("ENTER mss_SuperFastRandomInit::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load pattern l_rc = loadPattern(iv_initPattern); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load end address: MBMEAQ l_rc = loadEndAddress(); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Disable 8B ECC check/correct on WRD data bus: MBA_WRD_MODE(0:1) = 11 // before a SuperFastRandomInit command is issued l_rc = fapiGetScom(iv_target, MBA01_MBA_WRD_MODE_0x03010449, iv_saved_MBA_WRD_MODE); if(l_rc) return l_rc; ecmdDataBufferBase l_data(64); l_ecmd_rc |= l_data.insert(iv_saved_MBA_WRD_MODE, 0, 64, 0); l_ecmd_rc |= l_data.setBit(0); l_ecmd_rc |= l_data.setBit(1); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBA_WRD_MODE_0x03010449, l_data); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for //cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; if(iv_poll == false) { FAPI_INF("Cmd has started. Use attentions to detect cmd complete."); FAPI_INF("EXIT mss_SuperFastRandomInit::setupAndExecuteCmd()"); return l_rc; } // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT mss_SuperFastRandomInit::setupAndExecuteCmd()"); return l_rc; } fapi::ReturnCode mss_SuperFastRandomInit::cleanupCmd() { FAPI_INF("ENTER mss_SuperFastRandomInit::cleanupCmd()"); fapi::ReturnCode l_rc; // Clear maintenance command complete attention, scrub stats, etc... // Restore MBA_WRD_MODE l_rc = fapiPutScom(iv_target, MBA01_MBA_WRD_MODE_0x03010449, iv_saved_MBA_WRD_MODE); if(l_rc) return l_rc; FAPI_INF("EXIT mss_SuperFastRandomInit::cleanupCmd()"); return l_rc; } //------------------------------------------------------------------------------ // mss_SuperFastRead //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_SuperFastRead::cv_cmdType = SUPERFAST_READ; //--------------------------------------------------------- // mss_SuperFastRead Constructor //--------------------------------------------------------- mss_SuperFastRead::mss_SuperFastRead( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, const ecmdDataBufferBase & i_endAddr, uint32_t i_stopCondition, bool i_poll ) : mss_MaintCmd( i_target, i_startAddr, i_endAddr, i_stopCondition, i_poll, cv_cmdType){} //--------------------------------------------------------- // mss_SuperReadInit setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_SuperFastRead::setupAndExecuteCmd() { FAPI_INF("ENTER mss_SuperFastRead::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Setup required to trap UE actual data needed for IPL UE isolation l_rc = ueTrappingSetup(); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load end address: MBMEAQ l_rc = loadEndAddress(); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Need to set RRQ to fifo mode to ensure super fast read commands // are done on order. Otherwise, if cmds get out of order we can't be sure // the trapped address in MBMACA will be correct when we stop // on error. That means we could unintentionally skip addresses if we just // try to increment MBMACA and continue. // NOTE: Cleanup needs to be done to restore settings done. l_rc = fapiGetScom(iv_target, MBA01_MBA_RRQ0Q_0x0301040E, iv_saved_MBA_RRQ0); if(l_rc) return l_rc; ecmdDataBufferBase l_data(64); l_ecmd_rc |= l_data.insert(iv_saved_MBA_RRQ0, 0, 64, 0); l_ecmd_rc |= l_data.clearBit(6,5); // Set 6:10 = 00000 (fifo mode) l_ecmd_rc |= l_data.setBit(12); // Disable MBA RRQ fastpath if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBA_RRQ0Q_0x0301040E, l_data); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; if(iv_poll == false) { FAPI_INF("Cmd has started. Use attentions to detect cmd complete."); FAPI_INF("EXIT mss_SuperFastRead::setupAndExecuteCmd()"); return l_rc; } // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT mss_SuperFastRead::setupAndExecuteCmd()"); return l_rc; } fapi::ReturnCode mss_SuperFastRead::ueTrappingSetup() { FAPI_INF("ENTER mss_SuperFastRead::ueTrappingSetup()"); fapi::ReturnCode l_rc; static const uint32_t maintBufferDataRegs[2][2][2]={ // port0/1 {{MAINT0_MBS_MAINT_BUFF0_DATA0_0x0201160A, MAINT0_MBS_MAINT_BUFF0_DATA_ECC0_0x02011612}, {MAINT0_MBS_MAINT_BUFF0_DATA4_0x0201160E, MAINT0_MBS_MAINT_BUFF0_DATA_ECC4_0x02011616}}, // port2/3 {{MAINT1_MBS_MAINT_BUFF0_DATA0_0x0201170A, MAINT1_MBS_MAINT_BUFF0_DATA_ECC0_0x02011712}, {MAINT1_MBS_MAINT_BUFF0_DATA4_0x0201170E, MAINT1_MBS_MAINT_BUFF0_DATA_ECC4_0x02011716}}}; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); ecmdDataBufferBase l_ecc(64); ecmdDataBufferBase l_mbstr(64); uint32_t loop = 0; // Set bit 9 so that hw will generate the fabric ECC. // This is an 8B ECC protecting the data moving on internal buses in // the Centaur. l_ecmd_rc |= l_ecc.setBit(9); // Load unique pattern into both halves of the maint buffer, // so we can tell which half contains a trapped UE. l_ecmd_rc |= l_data.insert(0xFACEB00C, 0, 32, 0); l_ecmd_rc |= l_data.insert(0xD15C0DAD, 32, 32, 0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } for(loop=0; loop<2; loop++ ) { l_rc = fapiPutScom(iv_targetCentaur, maintBufferDataRegs[iv_mbaPosition][loop][0], l_data); if(l_rc) return l_rc; // A write to MAINT_BUFFx_DATAy will not update until the corresponding // MAINT_BUFFx_DATA_ECCy is written to. l_rc = fapiPutScom(iv_targetCentaur, maintBufferDataRegs[iv_mbaPosition][loop][1], l_ecc); if(l_rc) return l_rc; } // Enable UE trapping l_rc = fapiGetScom(iv_targetCentaur, mss_mbstr[iv_mbaPosition], l_mbstr); if(l_rc) return l_rc; l_mbstr.setBit(59); l_rc = fapiPutScom(iv_targetCentaur, mss_mbstr[iv_mbaPosition], l_mbstr); if(l_rc) return l_rc; FAPI_INF("EXIT mss_SuperFastRead::ueTrappingSetup()"); return l_rc; } fapi::ReturnCode mss_SuperFastRead::cleanupCmd() { FAPI_INF("ENTER mss_SuperFastRead::cleanupCmd()"); fapi::ReturnCode l_rc; ecmdDataBufferBase l_mbstr(64); // Clear maintenance command complete attention, scrub stats, etc... // Restore the saved data. //printf( "Saved data: 0x%08x\n", getSavedData() ); // Undo rrq fifo mode l_rc = fapiPutScom(iv_target, MBA01_MBA_RRQ0Q_0x0301040E, iv_saved_MBA_RRQ0); if(l_rc) return l_rc; // Disable UE trapping l_rc = fapiGetScom(iv_targetCentaur, mss_mbstr[iv_mbaPosition], l_mbstr); if(l_rc) return l_rc; l_mbstr.clearBit(59); l_rc = fapiPutScom(iv_targetCentaur, mss_mbstr[iv_mbaPosition], l_mbstr); if(l_rc) return l_rc; FAPI_INF("EXIT mss_SuperFastRead::cleanupCmd()"); return l_rc; } //------------------------------------------------------------------------------ // AtomicInject //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_AtomicInject::cv_cmdType = ATOMIC_ALTER_ERROR_INJECT; //--------------------------------------------------------- // AtomicInject Constructor //--------------------------------------------------------- mss_AtomicInject::mss_AtomicInject( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, InjectType i_injectType ) : mss_MaintCmd( i_target, i_startAddr, ecmdDataBufferBase(64), // i_endAddr not used for this cmd NO_STOP_CONDITIONS, // i_stopCondition not used for this cmd true, // i_poll always true for this cmd cv_cmdType), iv_injectType( i_injectType ) // NOTE: iv_injectType is instance variable // of AtomicInject, since not needed // in parent class {} //--------------------------------------------------------- // mss_AtomicInject setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_AtomicInject::setupAndExecuteCmd() { FAPI_INF("ENTER mss_AtomicInject::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Load inject type: MBECTLQ ecmdDataBufferBase l_mbectl(64); l_rc = fapiGetScom(iv_target, MBA01_MBECTLQ_0x03010610, l_mbectl); if(l_rc) return l_rc; l_ecmd_rc |= l_mbectl.flushTo0(); l_ecmd_rc |= l_mbectl.setBit(iv_injectType); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBECTLQ_0x03010610, l_mbectl); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Clear inject type: MBECTLQ l_ecmd_rc |= l_mbectl.flushTo0(); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_rc = fapiPutScom(iv_target, MBA01_MBECTLQ_0x03010610, l_mbectl); if(l_rc) return l_rc; // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT mss_AtomicInject::setupAndExecuteCmd()"); return l_rc; } //------------------------------------------------------------------------------ // Display //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_Display::cv_cmdType = MEMORY_DISPLAY; //--------------------------------------------------------- // Display Constructor //--------------------------------------------------------- mss_Display::mss_Display( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr) : mss_MaintCmd( i_target, i_startAddr, ecmdDataBufferBase(64), // i_endAddr not used for this cmd NO_STOP_CONDITIONS, // i_stopCondition not used for this cmd true, // i_poll always true for this cmd cv_cmdType){} //--------------------------------------------------------- // mss_Display setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_Display::setupAndExecuteCmd() { FAPI_INF("ENTER mss_Display::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; if(iv_poll == false) { FAPI_INF("Cmd has started. Use attentions to detect cmd complete."); FAPI_INF("EXIT Display::setupAndExecuteCmd()"); return l_rc; } // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Read the data from the display cmd: MBMSRQ static const uint32_t maintBufferReadDataRegs[16]={ // Port0 beat double word MAINT0_MBA_MAINT_BUFF0_DATA0_0x03010655, // 0 DW0 MAINT0_MBA_MAINT_BUFF2_DATA0_0x03010675, // 1 DW2 MAINT0_MBA_MAINT_BUFF0_DATA1_0x03010656, // 2 DW4 MAINT0_MBA_MAINT_BUFF2_DATA1_0x03010676, // 3 DW6 MAINT0_MBA_MAINT_BUFF0_DATA2_0x03010657, // 4 DW8 MAINT0_MBA_MAINT_BUFF2_DATA2_0x03010677, // 5 DW10 MAINT0_MBA_MAINT_BUFF0_DATA3_0x03010658, // 6 DW12 MAINT0_MBA_MAINT_BUFF2_DATA3_0x03010678, // 7 DW14 // Port1 MAINT0_MBA_MAINT_BUFF1_DATA0_0x03010665, // 0 DW1 MAINT0_MBA_MAINT_BUFF3_DATA0_0x03010685, // 1 DW3 MAINT0_MBA_MAINT_BUFF1_DATA1_0x03010666, // 2 DW5 MAINT0_MBA_MAINT_BUFF3_DATA1_0x03010686, // 3 DW7 MAINT0_MBA_MAINT_BUFF1_DATA2_0x03010667, // 4 DW9 MAINT0_MBA_MAINT_BUFF3_DATA2_0x03010687, // 5 DW11 MAINT0_MBA_MAINT_BUFF1_DATA3_0x03010668, // 6 DW13 MAINT0_MBA_MAINT_BUFF3_DATA3_0x03010688};// 7 DW15 static const uint32_t maintBufferRead65thByteRegs[4]={ MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC0_0x03010695, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC1_0x03010696, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC2_0x03010697, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC3_0x03010698}; uint32_t loop = 0; ecmdDataBufferBase l_data(64); //---------------------------------------------------- // Read the data: 16 loops x 64bits = 128B cacheline //---------------------------------------------------- FAPI_ERR("Read the data: 16 loops x 64bits = 128B cacheline"); for(loop=0; loop<16; loop++ ) { l_rc = fapiGetScom(iv_target, maintBufferReadDataRegs[loop], l_data); if(l_rc) return l_rc; FAPI_ERR("0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); } //---------------------------------------------------- // Read the 65th byte: 4 loops //---------------------------------------------------- FAPI_ERR("Read the 65th byte and ECC bits: 4 loops"); for(loop=0; loop<4; loop++ ) { l_rc = fapiGetScom(iv_target, maintBufferRead65thByteRegs[loop], l_data); if(l_rc) return l_rc; FAPI_ERR("0x%.8X 0x%.8X", l_data.getWord(0), l_data.getWord(1)); } // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT Display::setupAndExecuteCmd()"); return l_rc; } //------------------------------------------------------------------------------ // Increment MBMACA Address //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_IncrementAddress::cv_cmdType = INCREMENT_MBMACA_ADDRESS; //--------------------------------------------------------- // IncrementAddress Constructor //--------------------------------------------------------- mss_IncrementAddress::mss_IncrementAddress( const fapi::Target & i_target ): mss_MaintCmd( i_target, ecmdDataBufferBase(64), // i_startAddr not used for this cmd ecmdDataBufferBase(64), // i_endAddr not used for this cmd NO_STOP_CONDITIONS, // i_stopCondition not used for this cmd true, // i_poll always true for this cmd cv_cmdType){} //--------------------------------------------------------- // mss_IncrementAddress setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_IncrementAddress::setupAndExecuteCmd() { FAPI_INF("ENTER mss_IncrementAddress::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_mbspa_mask(64); ecmdDataBufferBase l_mbspa_mask_original(64); ecmdDataBufferBase l_mbspa_and(64); // Read MBSPA MASK l_rc = fapiGetScom(iv_target, MBA01_MBSPAMSKQ_0x03010614, l_mbspa_mask); if(l_rc) return l_rc; // Save original mask value so we can restore it when done l_ecmd_rc |= l_mbspa_mask_original.insert(l_mbspa_mask, 0, 64, 0); // Mask bits 0 and 8, to hide the special attentions when the cmd completes l_ecmd_rc |= l_mbspa_mask.setBit(0); l_ecmd_rc |= l_mbspa_mask.setBit(8); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MBSPA MASK l_rc = fapiPutScom(iv_target, MBA01_MBSPAMSKQ_0x03010614, l_mbspa_mask); if(l_rc) return l_rc; // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Read start address: MBMACAQ ecmdDataBufferBase l_mbmacaq(64); l_rc = fapiGetScom(iv_target, MBA01_MBMACAQ_0x0301060D, l_mbmacaq); if(l_rc) return l_rc; FAPI_INF("MBMACAQ = 0x%.8X 0x%.8X", l_mbmacaq.getWord(0), l_mbmacaq.getWord(1)); // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Read incremented start address: MBMACAQ l_rc = fapiGetScom(iv_target, MBA01_MBMACAQ_0x0301060D, l_mbmacaq); if(l_rc) return l_rc; // Clear bits 0 and 8 in MBSPA AND register l_ecmd_rc |= l_mbspa_and.flushTo1(); l_ecmd_rc |= l_mbspa_and.clearBit(0); l_ecmd_rc |= l_mbspa_and.clearBit(8); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MPSPA AND register l_rc = fapiPutScom(iv_target, MBA01_MBSPAQ_AND_0x03010612, l_mbspa_and); if(l_rc) return l_rc; // Restore MBSPA MASK l_rc = fapiPutScom(iv_target, MBA01_MBSPAMSKQ_0x03010614, l_mbspa_mask_original); if(l_rc) return l_rc; FAPI_INF("EXIT mss_IncrementAddress::setupAndExecuteCmd()"); return l_rc; } //------------------------------------------------------------------------------ // mss_TimeBaseScrub //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_TimeBaseScrub::cv_cmdType = TIMEBASE_SCRUB; //--------------------------------------------------------- // mss_TimeBaseScrub Constructor //--------------------------------------------------------- mss_TimeBaseScrub::mss_TimeBaseScrub( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, const ecmdDataBufferBase & i_endAddr, TimeBaseSpeed i_speed, uint32_t i_stopCondition, bool i_poll ) : mss_MaintCmd( i_target, i_startAddr, i_endAddr, i_stopCondition, i_poll, cv_cmdType), // NOTE: iv_speed is instance variable of TimeBaseScrub, since not // needed in parent class iv_speed( i_speed ) {} //--------------------------------------------------------- // mss_TimeBaseScrub setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_TimeBaseScrub::setupAndExecuteCmd() { FAPI_INF("ENTER mss_TimeBaseScrub::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load end address: MBMEAQ l_rc = loadEndAddress(); if(l_rc) return l_rc; // Load speed: MBMCTQ l_rc = loadSpeed(iv_speed); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; if(iv_poll == false) { FAPI_INF("Cmd has started. Use attentions to detect cmd complete."); FAPI_INF("EXIT mss_TimeBaseScrub::setupAndExecuteCmd()"); return l_rc; } // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT mss_TimeBaseScrub::setupAndExecuteCmd()"); return l_rc; } //------------------------------------------------------------------------------ // mss_TimeBaseSteerCleanup //------------------------------------------------------------------------------ const mss_MaintCmd::CmdType mss_TimeBaseSteerCleanup::cv_cmdType = TIMEBASE_STEER_CLEANUP; //--------------------------------------------------------- // mss_TimeBaseSteerCleanup Constructor //--------------------------------------------------------- mss_TimeBaseSteerCleanup::mss_TimeBaseSteerCleanup( const fapi::Target & i_target, const ecmdDataBufferBase & i_startAddr, const ecmdDataBufferBase & i_endAddr, TimeBaseSpeed i_speed, uint32_t i_stopCondition, bool i_poll ) : mss_MaintCmd( i_target, i_startAddr, i_endAddr, i_stopCondition, i_poll, cv_cmdType), // NOTE: iv_speed is instance variable of TimeBaseSteerCleanup, since not // needed in parent class iv_speed( i_speed ) {} //--------------------------------------------------------- // mss_TimeBaseSteerCleanup setupAndExecuteCmd //--------------------------------------------------------- fapi::ReturnCode mss_TimeBaseSteerCleanup::setupAndExecuteCmd() { FAPI_INF("ENTER mss_TimeBaseSteerCleanup::setupAndExecuteCmd()"); fapi::ReturnCode l_rc; // Gather data that needs to be stored. For testing purposes we will just // set an abitrary number. //l_rc = setSavedData( 0xdeadbeef ); if(l_rc) return l_rc; //printf( "Saved data: 0x%08x\n", getSavedData() ); // Make sure maint logic in valid state to run new cmd l_rc = preConditionCheck(); if(l_rc) return l_rc; // Load cmd type: MBMCTQ l_rc = loadCmdType(); if(l_rc) return l_rc; // Load start address: MBMACAQ l_rc = loadStartAddress(); if(l_rc) return l_rc; // Load end address: MBMEAQ l_rc = loadEndAddress(); if(l_rc) return l_rc; // Load speed: MBMCTQ l_rc = loadSpeed(iv_speed); if(l_rc) return l_rc; // Load stop conditions: MBASCTLQ l_rc = loadStopCondMask(); if(l_rc) return l_rc; // Start the command: MBMCCQ l_rc = startMaintCmd(); if(l_rc) return l_rc; // Check for early problems with maint cmd instead of waiting for // cmd timeout l_rc = postConditionCheck(); if(l_rc) return l_rc; if(iv_poll == false) { FAPI_INF("Cmd has started. Use attentions to detect cmd complete."); FAPI_INF("EXIT mss_TimeBaseSteerCleanup::setupAndExecuteCmd()"); return l_rc; } // Poll for command complete: MBMSRQ l_rc = pollForMaintCmdComplete(); if(l_rc) return l_rc; // Collect FFDC l_rc = collectFFDC(); if(l_rc) return l_rc; FAPI_INF("EXIT mss_TimeBaseSteerCleanup::setupAndExecuteCmd()"); return l_rc; } //------------------------------------------------------------------------------ // Utility funcitons //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // mss_get_address_range //------------------------------------------------------------------------------ fapi::ReturnCode mss_get_address_range( const fapi::Target & i_target, uint8_t i_rank, ecmdDataBufferBase & o_startAddr, ecmdDataBufferBase & o_endAddr ) { FAPI_INF("ENTER mss_get_address_range()"); static const uint8_t memConfigType[9][4][2]={ // Refer to Centaur Workbook: 5.2 Master and Slave Rank Usage // // SUBTYPE_A SUBTYPE_B SUBTYPE_C SUBTYPE_D // //SLOT_0_ONLY SLOT_0_AND_1 SLOT_0_ONLY SLOT_0_AND_1 SLOT_0_ONLY SLOT_0_AND_1 SLOT_0_ONLY SLOT_0_AND_1 // //master slave master slave master slave master slave master slave master slave master slave master slave // {{0xff, 0xff}, {0xff, 0xff}, {0xff, 0xff}, {0xff, 0xff}}, // TYPE_0 {{0x00, 0x40}, {0x10, 0x50}, {0x30, 0x70}, {0xff, 0xff}}, // TYPE_1 {{0x01, 0x41}, {0x03, 0x43}, {0x07, 0x47}, {0xff, 0xff}}, // TYPE_2 {{0x11, 0x51}, {0x13, 0x53}, {0x17, 0x57}, {0xff, 0xff}}, // TYPE_3 {{0x31, 0x71}, {0x33, 0x73}, {0x37, 0x77}, {0xff, 0xff}}, // TYPE_4 {{0x00, 0x40}, {0x10, 0x50}, {0x30, 0x70}, {0xff, 0xff}}, // TYPE_5 {{0x01, 0x41}, {0x03, 0x43}, {0x07, 0x47}, {0xff, 0xff}}, // TYPE_6 {{0x11, 0x51}, {0x13, 0x53}, {0x17, 0x57}, {0xff, 0xff}}, // TYPE_7 {{0x31, 0x71}, {0x33, 0x73}, {0x37, 0x77}, {0xff, 0xff}}}; // TYPE_8 fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_data(64); mss_MemConfig::MemOrg l_row; mss_MemConfig::MemOrg l_col; mss_MemConfig::MemOrg l_bank; uint32_t l_dramSize = 0; uint8_t l_dramWidth = 0; fapi::Target l_targetCentaur; uint8_t l_mbaPosition = 0; uint8_t l_isSIM = 1; uint8_t l_slotConfig = 0; uint8_t l_configType = 0; uint8_t l_configSubType = 0; uint8_t l_end_master_rank = 0; uint8_t l_end_slave_rank = 0; uint8_t l_dram_gen; // Get Centaur target for the given MBA l_rc = fapiGetParentChip(i_target, l_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA on %s.",i_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_target, l_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",i_target.toEcmdString()); return l_rc; } // Check system attribute if sim: 1 = Awan/HWSimulator. 0 = Simics/RealHW. l_rc = FAPI_ATTR_GET(ATTR_IS_SIMULATION, NULL, l_isSIM); if(l_rc) { FAPI_ERR("Error getting ATTR_IS_SIMULATION on %s.",i_target.toEcmdString()); return l_rc; } // Get l_dramWidth l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Get DDR3/DDR4: ATTR_EFF_DRAM_GEN // 0x01 = ENUM_ATTR_EFF_DRAM_GEN_DDR3 // 0x02 = ENUM_ATTR_EFF_DRAM_GEN_DDR4 l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target, l_dram_gen); if(l_rc) { FAPI_ERR("Error getting DDR3/DDR4 on %s.",i_target.toEcmdString()); return l_rc; } // Check MBAXCRn, to show memory configured behind this MBA l_rc = fapiGetScom(l_targetCentaur, mss_mbaxcr[l_mbaPosition], l_data); if(l_rc) return l_rc; if (l_data.isBitClear(0,4)) { FAPI_ERR("MBAXCRn[0:3] = 0, meaning no memory configured behind this MBA on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBAXCR = l_data; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_NO_MEM_CNFG); return l_rc; } //******************************************************************** // Find max row/col/bank, based on l_dramSize and l_dramWidth //******************************************************************** // Get l_dramSize l_ecmd_rc |= l_data.extractPreserve(&l_dramSize, 6, 2, 32-2); // (6:7) if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } if((l_dramWidth == mss_MemConfig::X8) && (l_dramSize == mss_MemConfig::GBIT_2) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3)) { // For memory part Size = 256Mbx8 (2Gb), row/col/bank = 15/10/3 FAPI_INF("For memory part Size = 256Mbx8 (2Gb), row/col/bank = 15/10/3, DDR3"); l_row = mss_MemConfig::ROW_15; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_3; } else if((l_dramWidth == mss_MemConfig::X8) && (l_dramSize == mss_MemConfig::GBIT_2) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR4)) { // For memory part Size = 256Mbx8 (2Gb), row/col/bank = 14/10/4 FAPI_INF("For memory part Size = 256Mbx8 (2Gb), row/col/bank = 14/10/4, DDR4"); l_row = mss_MemConfig::ROW_14; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_4; } else if((l_dramWidth == mss_MemConfig::X4) && (l_dramSize == mss_MemConfig::GBIT_2) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3)) { // For memory part Size = 512Mbx4 (2Gb), row/col/bank = 15/11/3 FAPI_INF("For memory part Size = 512Mbx4 (2Gb), row/col/bank = 15/11/3, DDR3"); l_row = mss_MemConfig::ROW_15; l_col = mss_MemConfig::COL_11; l_bank = mss_MemConfig::BANK_3; } else if((l_dramWidth == mss_MemConfig::X4) && (l_dramSize == mss_MemConfig::GBIT_2) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR4)) { // For memory part Size = 512Mbx4 (2Gb), row/col/bank = 15/10/4 FAPI_INF("For memory part Size = 512Mbx4 (2Gb), row/col/bank = 15/10/4, DDR4"); l_row = mss_MemConfig::ROW_15; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_4; } else if((l_dramWidth == mss_MemConfig::X8) && (l_dramSize == mss_MemConfig::GBIT_4) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3)) { // For memory part Size = 512Mbx8 (4Gb), row/col/bank = 16/10/3 FAPI_INF("For memory part Size = 512Mbx8 (4Gb), row/col/bank = 16/10/3, DDR3"); l_row = mss_MemConfig::ROW_16; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_3; } else if((l_dramWidth == mss_MemConfig::X8) && (l_dramSize == mss_MemConfig::GBIT_4) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR4)) { // For memory part Size = 512Mbx8 (4Gb), row/col/bank = 14/10/4 FAPI_INF("For memory part Size = 512Mbx8 (4Gb), row/col/bank = 14/10/4, DDR4"); l_row = mss_MemConfig::ROW_15; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_4; } else if((l_dramWidth == mss_MemConfig::X4) && (l_dramSize == mss_MemConfig::GBIT_4) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3)) { // For memory part Size = 1Gbx4 (4Gb), row/col/bank = 16/11/3 FAPI_INF("For memory part Size = 1Gbx4 (4Gb), row/col/bank = 16/11/3, DDR3"); l_row = mss_MemConfig::ROW_16; l_col = mss_MemConfig::COL_11; l_bank = mss_MemConfig::BANK_3; } else if((l_dramWidth == mss_MemConfig::X4) && (l_dramSize == mss_MemConfig::GBIT_4) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR4)) { // For memory part Size = 1Gbx4 (4Gb), row/col/bank = 16/10/4 FAPI_INF("For memory part Size = 1Gbx4 (4Gb), row/col/bank = 16/10/4, DDR4"); l_row = mss_MemConfig::ROW_16; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_4; } else if((l_dramWidth == mss_MemConfig::X8) && (l_dramSize == mss_MemConfig::GBIT_8) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3)) { // For memory part Size = 1Gbx8 (8Gb), row/col/bank = 16/11/3 FAPI_INF("For memory part Size = 1Gbx8 (8Gb), row/col/bank = 16/11/3, DDR3"); l_row = mss_MemConfig::ROW_16; l_col = mss_MemConfig::COL_11; l_bank = mss_MemConfig::BANK_3; } else if((l_dramWidth == mss_MemConfig::X8) && (l_dramSize == mss_MemConfig::GBIT_8) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR4)) { // For memory part Size = 1Gbx8 (8Gb), row/col/bank = 16/10/4 FAPI_INF("For memory part Size = 1Gbx8 (8Gb), row/col/bank = 16/10/4, DDR4"); l_row = mss_MemConfig::ROW_16; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_4; } else if((l_dramWidth == mss_MemConfig::X4) && (l_dramSize == mss_MemConfig::GBIT_8) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR3)) { // For memory part Size = 2Gbx4 (8Gb), row/col/bank = 16/12/3 FAPI_INF("For memory part Size = 2Gbx4 (8Gb), row/col/bank = 16/12/3, DDR3"); l_row = mss_MemConfig::ROW_16; l_col = mss_MemConfig::COL_12; l_bank = mss_MemConfig::BANK_3; } else if((l_dramWidth == mss_MemConfig::X4) && (l_dramSize == mss_MemConfig::GBIT_8) && (l_dram_gen == ENUM_ATTR_EFF_DRAM_GEN_DDR4)) { // For memory part Size = 2Gbx4 (8Gb), row/col/bank = 17/10/4 FAPI_INF("Forosr memory part Size = 2Gbx4 (8Gb), row/col/bank = 17/10/4, DDR4"); l_row = mss_MemConfig::ROW_17; l_col = mss_MemConfig::COL_10; l_bank = mss_MemConfig::BANK_4; } else { FAPI_ERR("Invalid l_dramSize = %d or l_dramWidth = %d in MBAXCRn, or l_dram_gen = %d on %s.", l_dramSize, l_dramWidth, l_dram_gen, i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBAXCR = l_data; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: DRAM width uint8_t DRAM_GEN = l_dram_gen; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_DRAM_SIZE_WIDTH); return l_rc; } //******************************************************************** // Find l_end_master_rank and l_end_slave_rank based on DIMM configuration //******************************************************************** // (0:3) Configuration type (1-8) l_ecmd_rc |= l_data.extractPreserve(&l_configType, 0, 4, 8-4); // (4:5) Configuration subtype (A, B, C, D) l_ecmd_rc |= l_data.extractPreserve(&l_configSubType, 4, 2, 8-2); // (8) Slot Configuration // 0 = Centaur DIMM or IS DIMM, slot0 only, 1 = IS DIMM slots 0 and 1 l_ecmd_rc |= l_data.extractPreserve(&l_slotConfig, 8, 1, 8-1); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } FAPI_INF("memConfigType[%d][%d][%d] = 0x%02x", l_configType,l_configSubType,l_slotConfig, memConfigType[l_configType][l_configSubType][l_slotConfig]); l_end_master_rank = (memConfigType[l_configType][l_configSubType][l_slotConfig] & 0xf0) >> 4; l_end_slave_rank = memConfigType[l_configType][l_configSubType][l_slotConfig] & 0x0f; FAPI_INF("end master rank = %d, end slave rank = %d", l_end_master_rank, l_end_slave_rank); if ((l_end_master_rank == 0x0f) || (l_end_slave_rank == 0x0f)) { FAPI_ERR("MBAXCRn configured with unsupported combination of l_configType, l_configSubType, l_slotConfig on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture register we are checking ecmdDataBufferBase & MBAXCR = l_data; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_DIMM_CNFG); return l_rc; } //******************************************************************** // Get address range for all ranks configured behind this MBA //******************************************************************** if (i_rank == MSS_ALL_RANKS) { FAPI_INF("Get address range for rank = ALL_RANKS"); // Start address is just rank 0 with row/col/bank all 0's o_startAddr.flushTo0(); // If Awan/HWSimulator, end address is just start address +3 if (l_isSIM) { FAPI_INF("ATTR_IS_SIMULATION = 1, Awan/HWSimulator, so use smaller address range."); // Do only rank0, row0, all banks all cols l_end_master_rank = 0; l_end_slave_rank = 0; uint32_t l_row_zero = 0; l_ecmd_rc |= o_endAddr.flushTo0(); // MASTER RANK = 0:3 l_ecmd_rc |= o_endAddr.insert( l_end_master_rank, 0, 4, 8-4 ); // SLAVE RANK = 4:6 l_ecmd_rc |= o_endAddr.insert( l_end_slave_rank, 4, 3, 8-3 ); // BANK = 7:10 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_bank, 7, 4, 32-4 ); // ROW = 11:27 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_row_zero, 11, 17, 32-17 ); // COL = 28:39, note: c2, c1, c0 always 0 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_col, 28, 12, 32-12 ); } // Else, set end address to be last address of l_end_master_rank else { l_ecmd_rc |= o_endAddr.flushTo0(); // MASTER RANK = 0:3 l_ecmd_rc |= o_endAddr.insert( l_end_master_rank, 0, 4, 8-4 ); // SLAVE RANK = 4:6 l_ecmd_rc |= o_endAddr.insert( l_end_slave_rank, 4, 3, 8-3 ); // BANK = 7:10 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_bank, 7, 4, 32-4 ); // ROW = 11:27 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_row, 11, 17, 32-17 ); // COL = 28:39, note: c2, c1, c0 always 0 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_col, 28, 12, 32-12 ); } } //******************************************************************** // Get address range for single rank configured behind this MBA //******************************************************************** else { FAPI_INF("Get address range for master rank = %d\n", i_rank ); // Check for i_rank out of range if (i_rank>=8) { FAPI_ERR("i_rank input to mss_get_address_range out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture i_rank; uint8_t RANK = i_rank; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_GET_ADDRESS_RANGE_BAD_INPUT); return l_rc; } // NOTE: If this rank is not valid, we should see MBAFIR[1]: invalid // maint address, when cmd started // Start address is just i_rank with row/col/bank all 0's l_ecmd_rc |= o_startAddr.flushTo0(); // MASTER RANK = 0:3 l_ecmd_rc |= o_startAddr.insert( i_rank, 0, 4, 8-4 ); // If Awan/HWSimulator, end address is just start address +3 if (l_isSIM) { FAPI_INF("ATTR_IS_SIMULATION = 1, Awan/HWSimulator, so use smaller address range."); l_end_slave_rank = 0; uint32_t l_row_zero = 0; l_ecmd_rc |= o_endAddr.flushTo0(); // MASTER RANK = 0:3 l_ecmd_rc |= o_endAddr.insert( i_rank, 0, 4, 8-4 ); // SLAVE RANK = 4:6 l_ecmd_rc |= o_endAddr.insert( l_end_slave_rank, 4, 3, 8-3 ); // BANK = 7:10 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_bank, 7, 4, 32-4 ); // ROW = 11:27 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_row_zero, 11, 17, 32-17 ); // COL = 28:39, note: c2, c1, c0 always 0 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_col, 28, 12, 32-12 ); } // Else, set end address to be last address of i_rank else { l_ecmd_rc |= o_endAddr.flushTo0(); // MASTER RANK = 0:3 l_ecmd_rc |= o_endAddr.insert( i_rank, 0, 4, 8-4 ); // SLAVE RANK = 4:6 l_ecmd_rc |= o_endAddr.insert( l_end_slave_rank, 4, 3, 8-3 ); // BANK = 7:10 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_bank, 7, 4, 32-4 ); // ROW = 11:27 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_row, 11, 17, 32-17 ); // COL = 28:36 l_ecmd_rc |= o_endAddr.insert( (uint32_t)l_col, 28, 12, 32-12 ); } } if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } FAPI_INF("EXIT mss_get_address_range()"); return l_rc; } //------------------------------------------------------------------------------ // mss_get_mark_store //------------------------------------------------------------------------------ fapi::ReturnCode mss_get_mark_store( const fapi::Target & i_target, uint8_t i_rank, uint8_t & o_symbolMark, uint8_t & o_chipMark ) { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_markstore(64); ecmdDataBufferBase l_mbeccfir(64); ecmdDataBufferBase l_data(64); uint8_t l_dramWidth = 0; uint8_t l_symbolMarkGalois = 0; uint8_t l_chipMarkGalois = 0; uint8_t l_symbolsPerChip = 4; fapi::Target l_targetCentaur; uint8_t l_mbaPosition = 0; ecmdDataBufferBase l_mbscfg(64); uint8_t l_dd2_enable_exit_point_1 = 0; o_symbolMark = MSS_INVALID_SYMBOL; o_chipMark = MSS_INVALID_SYMBOL; // Get Centaur target for the given MBA l_rc = fapiGetParentChip(i_target, l_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA on %s.",i_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_target, l_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",i_target.toEcmdString()); return l_rc; } // Get l_dramWidth l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Check for i_rank out of range if (i_rank>=8) { FAPI_ERR("i_rank input to mss_get_mark_store out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture i_rank; uint8_t RANK = i_rank; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_GET_MARK_STORE_BAD_INPUT); return l_rc; } // Read markstore register for the given rank l_rc = fapiGetScom(l_targetCentaur, mss_markStoreRegs[i_rank][l_mbaPosition], l_markstore); if(l_rc) return l_rc; // If MPE FIR for the given rank (scrub or fetch) is on after the read, // we will read one more time just to make sure we get latest. l_rc = fapiGetScom(l_targetCentaur, mss_mbeccfir[l_mbaPosition], l_mbeccfir); if(l_rc) return l_rc; if (l_mbeccfir.isBitSet(i_rank) || l_mbeccfir.isBitSet(20 + i_rank)) { l_rc = fapiGetScom(l_targetCentaur, mss_markStoreRegs[i_rank][l_mbaPosition], l_markstore); if(l_rc) return l_rc; } // Get l_symbolMarkGalois l_ecmd_rc |= l_markstore.extractPreserve(&l_symbolMarkGalois, 0, 8, 8-8); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } if (l_symbolMarkGalois == 0x00) // No symbol mark { o_symbolMark = MSS_INVALID_SYMBOL; } else if (l_dramWidth == mss_MemConfig::X4) { FAPI_ERR("l_symbolMarkGalois invalid: symbol mark not allowed in x4 mode on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capture markstore ecmdDataBufferBase & MARKSTORE = l_markstore; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_X4_SYMBOL_ON_READ); return l_rc; } else // Converted from galois field to symbol index { o_symbolMark = MSS_SYMBOLS_PER_RANK; for ( uint32_t i = 0; i < MSS_SYMBOLS_PER_RANK; i++ ) { if ( l_symbolMarkGalois == mss_symbol2Galois[i] ) { o_symbolMark = i; break; } } if ( MSS_SYMBOLS_PER_RANK <= o_symbolMark ) { FAPI_ERR("Invalid galois field in markstore on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capture markstore ecmdDataBufferBase & MARKSTORE = l_markstore; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_MARKSTORE); return l_rc; } } // Get l_chipMarkGalois l_ecmd_rc |= l_markstore.extractPreserve(&l_chipMarkGalois, 8, 8, 8-8); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } if (l_chipMarkGalois == 0x00) // No chip mark { o_chipMark = MSS_INVALID_SYMBOL; } else // Converted from galois field to chip index { if (l_dramWidth == mss_MemConfig::X4) { l_symbolsPerChip = 2; } else if (l_dramWidth == mss_MemConfig::X8) { l_symbolsPerChip = 4; } o_chipMark = MSS_SYMBOLS_PER_RANK; for ( uint32_t i = 0; i < MSS_SYMBOLS_PER_RANK; i=i+l_symbolsPerChip) { if ( l_chipMarkGalois == mss_symbol2Galois[i] ) { o_chipMark = i; break; } } // TODO: create error if x4 mode and symbol 0,1? if ( MSS_SYMBOLS_PER_RANK <= o_chipMark ) { FAPI_ERR("Invalid galois field in markstore on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capture markstore ecmdDataBufferBase & MARKSTORE = l_markstore; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_MARKSTORE); return l_rc; } } // Get attribute that tells we have cen DD2, and can enable exit poing 1 l_rc = FAPI_ATTR_GET(ATTR_CENTAUR_EC_DD2_ENABLE_EXIT_POINT_1, &i_target, l_dd2_enable_exit_point_1); if(l_rc) { FAPI_ERR("Error getting ATTR_CENTAUR_EC_DD2_ENABLE_EXIT_POINT_1"); return l_rc; } if(l_dd2_enable_exit_point_1) { // If valid chip or symbol mark, enable exit point 1 if ((o_chipMark != MSS_INVALID_SYMBOL) || (o_symbolMark != MSS_INVALID_SYMBOL)) { // Read MBSCFGQ l_rc = fapiGetScom(l_targetCentaur, MBSCFGQ_0x02011411, l_mbscfg); if(l_rc) return l_rc; l_ecmd_rc |= l_mbscfg.setBit(0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MBSCFGQ l_rc = fapiPutScom(l_targetCentaur, MBSCFGQ_0x02011411, l_mbscfg); if(l_rc) return l_rc; } } FAPI_INF("mss_get_mark_store(): rank%d, chip mark = %d, symbol mark = %d", i_rank, o_chipMark, o_symbolMark ); return l_rc; } //------------------------------------------------------------------------------ // mss_put_mark_store //------------------------------------------------------------------------------ fapi::ReturnCode mss_put_mark_store( const fapi::Target & i_target, uint8_t i_rank, uint8_t i_symbolMark, uint8_t i_chipMark ) { FAPI_INF("ENTER mss_put_mark_store()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_markstore(64); ecmdDataBufferBase l_mbeccfir(64); ecmdDataBufferBase l_data(64); uint8_t l_dramWidth = 0; uint8_t l_symbolMarkGalois = 0; uint8_t l_chipMarkGalois = 0; fapi::Target l_targetCentaur; uint8_t l_mbaPosition = 0; uint8_t l_rank_index = 0; bool l_exit_point_1_needed = false; ecmdDataBufferBase l_mbscfg(64); uint8_t l_dd2_enable_exit_point_1 = 0; // Get Centaur target for the given MBA l_rc = fapiGetParentChip(i_target, l_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA on %s.",i_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_target, l_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",i_target.toEcmdString()); return l_rc; } // Get l_dramWidth l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Check for i_rank out of range if (i_rank>=8) { FAPI_ERR("i_rank input to mss_put_mark_store out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture i_rank; uint8_t RANK = i_rank; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_PUT_MARK_STORE_BAD_INPUT); return l_rc; } // Get l_symbolMarkGalois if (i_symbolMark == MSS_INVALID_SYMBOL) // No symbol mark { l_symbolMarkGalois = 0x00; } else if ( l_dramWidth == mss_MemConfig::X4 ) { FAPI_ERR("i_symbolMark invalid: symbol mark not allowed in x4 mode on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_symbolMark; uint8_t SYMBOL_MARK = i_symbolMark; // FFDC: Capure i_chipMark; uint8_t CHIP_MARK = i_chipMark; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_X4_SYMBOL_ON_WRITE); return l_rc; } else if ( MSS_SYMBOLS_PER_RANK <= i_symbolMark ) { FAPI_ERR("i_symbolMark invalid: symbol index out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_symbolMark; uint8_t SYMBOL_MARK = i_symbolMark; // FFDC: Capure i_chipMark; uint8_t CHIP_MARK = i_chipMark; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_INDEX); return l_rc; } else // Convert from symbol index to galois field { l_symbolMarkGalois = mss_symbol2Galois[i_symbolMark]; } l_ecmd_rc |= l_markstore.insert( l_symbolMarkGalois, 0, 8, 0 ); // Get l_chipMarkGalois if (i_chipMark == MSS_INVALID_SYMBOL) // No chip mark { l_chipMarkGalois = 0x00; } else if ( MSS_SYMBOLS_PER_RANK <= i_chipMark ) { FAPI_ERR("i_chipMark invalid: symbol index out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_symbolMark; uint8_t SYMBOL_MARK = i_symbolMark; // FFDC: Capure i_chipMark; uint8_t CHIP_MARK = i_chipMark; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_INDEX); return l_rc; } else if ((l_dramWidth == mss_MemConfig::X8) && (i_chipMark % 4) ) { FAPI_ERR("i_chipMark invalid: not first symbol index of a x8 chip on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_symbolMark; uint8_t SYMBOL_MARK = i_symbolMark; // FFDC: Capure i_chipMark; uint8_t CHIP_MARK = i_chipMark; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_CHIP_INDEX); return l_rc; } else if ((l_dramWidth == mss_MemConfig::X4) && (i_chipMark % 2) ) { FAPI_ERR("i_chipMark invalid: not first symbol index of a x4 chip on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_symbolMark; uint8_t SYMBOL_MARK = i_symbolMark; // FFDC: Capure i_chipMark; uint8_t CHIP_MARK = i_chipMark; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_CHIP_INDEX); return l_rc; } // TODO: create error if x4 mode and symbol 0,1? else // Convert from symbol index to galois field { l_chipMarkGalois = mss_symbol2Galois[i_chipMark]; } l_ecmd_rc |= l_markstore.insert( l_chipMarkGalois, 8, 8, 0 ); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write markstore register for the given rank l_rc = fapiPutScom(l_targetCentaur, mss_markStoreRegs[i_rank][l_mbaPosition], l_markstore); if(l_rc) return l_rc; // If MPE FIR for the given rank (scrub or fetch) is on after the write, // we will return a fapi::ReturnCode to indicate write may not have worked. // Up to caller to read again if they want to see what new chip mark is. l_rc = fapiGetScom(l_targetCentaur, mss_mbeccfir[l_mbaPosition], l_mbeccfir); if(l_rc) return l_rc; if (l_mbeccfir.isBitSet(i_rank) || l_mbeccfir.isBitSet(20 + i_rank)) { FAPI_ERR("Markstore write may have been blocked due to MPE FIR set on %s.",i_target.toEcmdString()); // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_symbolMark; uint8_t SYMBOL_MARK = i_symbolMark; // FFDC: Capure i_chipMark; uint8_t CHIP_MARK = i_chipMark; // FFDC: Capture MBECCFIR ecmdDataBufferBase & MBECCFIR = l_mbeccfir; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_MARKSTORE_WRITE_BLOCKED); return l_rc; } // Get attribute that tells we have cen DD2, and can enable exit poing 1 l_rc = FAPI_ATTR_GET(ATTR_CENTAUR_EC_DD2_ENABLE_EXIT_POINT_1, &i_target, l_dd2_enable_exit_point_1); if(l_rc) { FAPI_ERR("Error getting ATTR_CENTAUR_EC_DD2_ENABLE_EXIT_POINT_1"); return l_rc; } if(l_dd2_enable_exit_point_1) { // Read all mark store for both MBAs for ( l_mbaPosition = 0; l_mbaPosition < 2; l_mbaPosition++) { for ( l_rank_index = 0; l_rank_index < MSS_MAX_RANKS; l_rank_index++ ) { l_rc = fapiGetScom(l_targetCentaur, mss_markStoreRegs[l_rank_index][l_mbaPosition], l_markstore); if(l_rc) return l_rc; if (l_markstore.isBitSet(0,16)) { // Mark found, so exit point 1 needed l_exit_point_1_needed = true; break; } } if (l_exit_point_1_needed) break; } // Read MBSCFGQ l_rc = fapiGetScom(l_targetCentaur, MBSCFGQ_0x02011411, l_mbscfg); if(l_rc) return l_rc; // Enable exit point 1 if (l_exit_point_1_needed) { l_ecmd_rc |= l_mbscfg.setBit(0); } // Else, disable exit point 1 else { l_ecmd_rc |= l_mbscfg.clearBit(0); } if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write MBSCFGQ l_rc = fapiPutScom(l_targetCentaur, MBSCFGQ_0x02011411, l_mbscfg); if(l_rc) return l_rc; } // End if l_dd2_enable_exit_point_1 FAPI_INF("EXIT mss_put_mark_store()"); return l_rc; } //------------------------------------------------------------------------------ // mss_get_steer_mux //------------------------------------------------------------------------------ fapi::ReturnCode mss_get_steer_mux( const fapi::Target & i_target, uint8_t i_rank, mss_SteerMux::muxType i_muxType, uint8_t & o_dramSparePort0Symbol, uint8_t & o_dramSparePort1Symbol, uint8_t & o_eccSpareSymbol ) { fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_steerMux(64); ecmdDataBufferBase l_data(64); uint8_t l_dramWidth = 0; uint8_t l_dramSparePort0Index = 0; uint8_t l_dramSparePort1Index = 0; uint8_t l_eccSpareIndex = 0; fapi::Target l_targetCentaur; uint8_t l_mbaPosition = 0; o_dramSparePort0Symbol = MSS_INVALID_SYMBOL; o_dramSparePort1Symbol = MSS_INVALID_SYMBOL; o_eccSpareSymbol = MSS_INVALID_SYMBOL; // Get Centaur target for the given MBA l_rc = fapiGetParentChip(i_target, l_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA on %s.",i_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_target, l_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",i_target.toEcmdString()); return l_rc; } // Get l_dramWidth l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Check for i_rank or i_muxType out of range if ((i_rank>=8) || !((i_muxType==mss_SteerMux::READ_MUX) || (i_muxType==mss_SteerMux::WRITE_MUX))) { FAPI_ERR("i_rank or i_muxType input to mss_get_steer_mux out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_GET_STEER_MUX_BAD_INPUT); return l_rc; } // Read steer mux register for the given rank and mux type (read or write). if (i_muxType == mss_SteerMux::READ_MUX) { // Read muxes are in the MBS l_rc = fapiGetScom(l_targetCentaur, mss_readMuxRegs[i_rank][l_mbaPosition], l_steerMux); if(l_rc) return l_rc; } else { // Write muxes are in the MBA l_rc = fapiGetScom(i_target, mss_writeMuxRegs[i_rank], l_steerMux); if(l_rc) return l_rc; } // Get l_dramSparePort0Index l_ecmd_rc |= l_steerMux.extractPreserve(&l_dramSparePort0Index, 0, 5, 8-5); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Get o_dramSparePort0Symbol if index in valid range if ((l_dramWidth == mss_MemConfig::X8) && (l_dramSparePort0Index < MSS_X8_STEER_OPTIONS_PER_PORT)) { o_dramSparePort0Symbol = mss_x8dramSparePort0Index_to_symbol[l_dramSparePort0Index]; } else if ((l_dramWidth == mss_MemConfig::X4) && (l_dramSparePort0Index < MSS_X4_STEER_OPTIONS_PER_PORT0)) { o_dramSparePort0Symbol = mss_x4dramSparePort0Index_to_symbol[l_dramSparePort0Index]; } else { FAPI_ERR("Steer mux l_dramSparePort0Index out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capture steer mux ecmdDataBufferBase & STEER_MUX = l_steerMux; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_STEER_MUX); return l_rc; } // Get l_dramSparePort1Index l_ecmd_rc |= l_steerMux.extractPreserve(&l_dramSparePort1Index, 5, 5, 8-5); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Get o_dramSparePort1Symbol if index in valid range if ((l_dramWidth == mss_MemConfig::X8) && (l_dramSparePort1Index < MSS_X8_STEER_OPTIONS_PER_PORT)) { o_dramSparePort1Symbol = mss_x8dramSparePort1Index_to_symbol[l_dramSparePort1Index]; } else if ((l_dramWidth == mss_MemConfig::X4) && (l_dramSparePort1Index < MSS_X4_STEER_OPTIONS_PER_PORT1)) { o_dramSparePort1Symbol = mss_x4dramSparePort1Index_to_symbol[l_dramSparePort1Index]; } else { FAPI_ERR("Steer mux l_dramSparePort1Index out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capture steer mux ecmdDataBufferBase & STEER_MUX = l_steerMux; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_STEER_MUX); return l_rc; } // Get l_eccSpareIndex l_ecmd_rc |= l_steerMux.extractPreserve(&l_eccSpareIndex, 10, 6, 8-6); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Get o_eccSpareSymbol if index in valid range if (l_eccSpareIndex < MSS_X4_ECC_STEER_OPTIONS) { o_eccSpareSymbol = mss_eccSpareIndex_to_symbol[l_eccSpareIndex]; } else { FAPI_ERR("o_eccSpareSymbol out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capture steer mux ecmdDataBufferBase & STEER_MUX = l_steerMux; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_STEER_MUX); return l_rc; } FAPI_INF("mss_get_steer_mux(): rank%d, port0 steer = %d, port1 steer = %d, ecc steer = %d", i_rank, o_dramSparePort0Symbol, o_dramSparePort1Symbol, o_eccSpareSymbol ); return l_rc; } //------------------------------------------------------------------------------ // mss_put_steer_mux //------------------------------------------------------------------------------ fapi::ReturnCode mss_put_steer_mux( const fapi::Target & i_target, uint8_t i_rank, mss_SteerMux::muxType i_muxType, uint8_t i_steerType, uint8_t i_symbol ) { FAPI_INF("ENTER mss_put_steer_mux()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; ecmdDataBufferBase l_steerMux(64); ecmdDataBufferBase l_data(64); uint8_t l_dramWidth = 0; uint8_t l_dramSparePort0Index = 0; uint8_t l_dramSparePort1Index = 0; uint8_t l_eccSpareIndex = 0; fapi::Target l_targetCentaur; uint8_t l_mbaPosition = 0; // Get Centaur target for the given MBA l_rc = fapiGetParentChip(i_target, l_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA on %s.",i_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_target, l_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",i_target.toEcmdString()); return l_rc; } // Get l_dramWidth l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Check for i_rank or i_muxType or i_steerType or i_symbol out of range if ((i_rank>=8) || !((i_muxType==mss_SteerMux::READ_MUX) || (i_muxType==mss_SteerMux::WRITE_MUX)) || !((i_steerType == mss_SteerMux::DRAM_SPARE_PORT0) || (i_steerType == mss_SteerMux::DRAM_SPARE_PORT1) || (i_steerType == mss_SteerMux::ECC_SPARE)) || (i_symbol >= 72)) { FAPI_ERR("i_rank or i_muxType or i_steerType or i_symbol input to mss_get_steer_mux out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_PUT_STEER_MUX_BAD_INPUT); return l_rc; } // TODO: add error if ecc_spare and symbol is 0 or 1? // Read steer mux register for the given rank and mux type (read or write). if (i_muxType == mss_SteerMux::READ_MUX) { // Read muxes are in the MBS l_rc = fapiGetScom(l_targetCentaur, mss_readMuxRegs[i_rank][l_mbaPosition], l_steerMux); if(l_rc) return l_rc; } else { // Write muxes are in the MBA l_rc = fapiGetScom(i_target, mss_writeMuxRegs[i_rank], l_steerMux); if(l_rc) return l_rc; } // Convert from i_symbol to l_dramSparePort0Index if (i_steerType == mss_SteerMux::DRAM_SPARE_PORT0) { if (l_dramWidth == mss_MemConfig::X8) { l_dramSparePort0Index = MSS_X8_STEER_OPTIONS_PER_PORT; for ( uint32_t i = 0; i < MSS_X8_STEER_OPTIONS_PER_PORT; i++ ) { if ( i_symbol == mss_x8dramSparePort0Index_to_symbol[i] ) { l_dramSparePort0Index = i; break; } } if ( MSS_X8_STEER_OPTIONS_PER_PORT <= l_dramSparePort0Index ) { FAPI_ERR("No match for i_symbol = %d in mss_x8dramSparePort0Index_to_symbol[] on %s.", i_symbol, i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_TO_STEER); return l_rc; } } else if (l_dramWidth == mss_MemConfig::X4) { l_dramSparePort0Index = MSS_X4_STEER_OPTIONS_PER_PORT0; for ( uint32_t i = 0; i < MSS_X4_STEER_OPTIONS_PER_PORT0; i++ ) { if ( i_symbol == mss_x4dramSparePort0Index_to_symbol[i] ) { l_dramSparePort0Index = i; break; } } if ( MSS_X4_STEER_OPTIONS_PER_PORT0 <= l_dramSparePort0Index ) { FAPI_ERR("No match for i_symbol in mss_x4dramSparePort0Index_to_symbol[] on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_TO_STEER); return l_rc; } } l_ecmd_rc |= l_steerMux.insert( l_dramSparePort0Index, 0, 5, 8-5 ); } // Convert from i_symbol to l_dramSparePort1Index if (i_steerType == mss_SteerMux::DRAM_SPARE_PORT1) { if (l_dramWidth == mss_MemConfig::X8) { l_dramSparePort1Index = MSS_X8_STEER_OPTIONS_PER_PORT; for ( uint32_t i = 0; i < MSS_X8_STEER_OPTIONS_PER_PORT; i++ ) { if ( i_symbol == mss_x8dramSparePort1Index_to_symbol[i] ) { l_dramSparePort1Index = i; break; } } if ( MSS_X8_STEER_OPTIONS_PER_PORT <= l_dramSparePort1Index ) { FAPI_ERR("No match for i_symbol in mss_x8dramSparePort1Index_to_symbol[] on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_TO_STEER); return l_rc; } } else if (l_dramWidth == mss_MemConfig::X4) { l_dramSparePort1Index = MSS_X4_STEER_OPTIONS_PER_PORT1; for ( uint32_t i = 0; i < MSS_X4_STEER_OPTIONS_PER_PORT1; i++ ) { if ( i_symbol == mss_x4dramSparePort1Index_to_symbol[i] ) { l_dramSparePort1Index = i; break; } } if ( MSS_X4_STEER_OPTIONS_PER_PORT1 <= l_dramSparePort1Index ) { FAPI_ERR("No match for i_symbol in mss_x4dramSparePort1Index_to_symbol[] on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_TO_STEER); return l_rc; } } l_ecmd_rc |= l_steerMux.insert( l_dramSparePort1Index, 5, 5, 8-5 ); } // Convert from i_symbol to l_eccSpareIndex if (i_steerType == mss_SteerMux::ECC_SPARE) { if (l_dramWidth == mss_MemConfig::X4) { l_eccSpareIndex = MSS_X4_ECC_STEER_OPTIONS; for ( uint32_t i = 0; i < MSS_X4_ECC_STEER_OPTIONS; i++ ) { if ( i_symbol == mss_eccSpareIndex_to_symbol[i] ) { l_eccSpareIndex = i; break; } } if ( MSS_X4_ECC_STEER_OPTIONS <= l_eccSpareIndex ) { FAPI_ERR("No match for i_symbol in mss_eccSpareIndex_to_symbol[] on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_INVALID_SYMBOL_TO_STEER); return l_rc; } } else if (l_dramWidth == mss_MemConfig::X8) { FAPI_ERR("ECC_SPARE not valid with x8 mode on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: DRAM width uint8_t DRAM_WIDTH = l_dramWidth; // FFDC: Capure i_rank; uint8_t RANK = i_rank; // FFDC: Capure i_muxType uint8_t MUX_TYPE = i_muxType; // FFDC: Capure i_steerType uint8_t STEER_TYPE = i_steerType; // FFDC: Capure i_symbol uint8_t SYMBOL = i_symbol; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_NO_X8_ECC_SPARE); return l_rc; } l_ecmd_rc |= l_steerMux.insert( l_eccSpareIndex, 10, 6, 8-6 ); } if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // Write the steer mux register for the given rank and mux // type (read or write). if (i_muxType == mss_SteerMux::READ_MUX) { // Read muxes are in the MBS l_rc = fapiPutScom(l_targetCentaur, mss_readMuxRegs[i_rank][l_mbaPosition], l_steerMux); if(l_rc) return l_rc; } else { // Write muxes are in the MBA l_rc = fapiPutScom(i_target, mss_writeMuxRegs[i_rank], l_steerMux); if(l_rc) return l_rc; } FAPI_INF("EXIT mss_put_steer_mux()"); return l_rc; } //------------------------------------------------------------------------------ // mss_check_steering //------------------------------------------------------------------------------ fapi::ReturnCode mss_check_steering(const fapi::Target & i_target, uint8_t i_rank, uint8_t & o_dramSparePort0Symbol, uint8_t & o_dramSparePort1Symbol, uint8_t & o_eccSpareSymbol ) { // Get the read steer mux, with the assuption // that the write mux will be the same. return mss_get_steer_mux(i_target, i_rank, mss_SteerMux::READ_MUX, o_dramSparePort0Symbol, o_dramSparePort1Symbol, o_eccSpareSymbol); } //------------------------------------------------------------------------------ // mss_do_steering //------------------------------------------------------------------------------ fapi::ReturnCode mss_do_steering(const fapi::Target & i_target, uint8_t i_rank, uint8_t i_symbol, bool i_x4EccSpare) { FAPI_INF("ENTER mss_do_steering()"); fapi::ReturnCode l_rc; uint8_t l_steerType = 0; // 0 = DRAM_SPARE_PORT0, Spare DRAM on port0 // 1 = DRAM_SPARE_PORT1, Spare DRAM on port1 // 2 = ECC_SPARE, ECC spare (used in x4 mode only) // Check for i_rank or i_symbol out of range if ((i_rank>=MSS_MAX_RANKS) || (i_symbol>=MSS_SYMBOLS_PER_RANK)) { FAPI_ERR("i_rank or i_symbol input to mss_do_steer out of range on %s.",i_target.toEcmdString()); // Calling out FW high // FFDC: MBA target const fapi::Target & MBA = i_target; // FFDC: Capture i_rank; uint8_t RANK = i_rank; // FFDC: Capture i_symbol; uint8_t SYMBOL = i_symbol; // FFDC: Capture i_x4EccSpare uint8_t X4ECCSPARE = i_x4EccSpare; // Create new log. FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_DO_STEER_INPUT_OUT_OF_RANGE); return l_rc; } //------------------------------------------------------ // Determine l_steerType //------------------------------------------------------ if (i_x4EccSpare) { l_steerType = mss_SteerMux::ECC_SPARE; } else { // Symbols 71-40, 7-4 come from port0 if (((i_symbol<=MSS_PORT_0_SYMBOL_71)&&(i_symbol>=MSS_PORT_0_SYMBOL_40)) || ((i_symbol<=MSS_PORT_0_SYMBOL_7)&&(i_symbol>=MSS_PORT_0_SYMBOL_4))) { l_steerType = mss_SteerMux::DRAM_SPARE_PORT0; } // Symbols 39-8, 3-0 come from port1 else { l_steerType = mss_SteerMux::DRAM_SPARE_PORT1; } } //------------------------------------------------------ // Update write mux //------------------------------------------------------ l_rc = mss_put_steer_mux( i_target, // MBA i_rank, // Master rank: 0-7 mss_SteerMux::WRITE_MUX,// write mux l_steerType, // DRAM_SPARE_PORT0/DRAM_SPARE_PORT1/ECC_SPARE i_symbol); // First symbol index of DRAM to steer around if (l_rc) { FAPI_ERR("Error updating write mux on %s.",i_target.toEcmdString()); return l_rc; } //------------------------------------------------------ // Wait for a periodic cal. //------------------------------------------------------ // 250 ms delay for HW mode const uint64_t HW_MODE_DELAY = 250000000; // 200000 sim cycle delay for SIM mode const uint64_t SIM_MODE_DELAY = 200000; fapiDelay(HW_MODE_DELAY, SIM_MODE_DELAY); //------------------------------------------------------ // Update read mux //------------------------------------------------------ l_rc = mss_put_steer_mux( i_target, // MBA i_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_steerType, // DRAM_SPARE_PORT0/DRAM_SPARE_PORT1/ECC_SPARE i_symbol); // First symbol index of DRAM to steer around if (l_rc) { FAPI_ERR("Error updating read mux on %s.",i_target.toEcmdString()); return l_rc; } FAPI_INF("EXIT mss_do_steering()"); return l_rc; } //-------------------------------------------------------- //mss_restore_DRAM_repairs //--------------------------------------------------------- fapi::ReturnCode mss_restore_DRAM_repairs( const fapi::Target & i_target, uint8_t & o_repairs_applied, uint8_t & o_repairs_exceeded) { fapi::ReturnCode l_rc; bool l_flag_standby = false; struct repair_count l_count; l_rc = mss_restore_DRAM_repairs_asm(i_target,o_repairs_applied,o_repairs_exceeded,l_flag_standby,l_count); return l_rc; } //------------------------------------------------------------------------------ // mss_restore_DRAM_repairs_asm //------------------------------------------------------------------------------ fapi::ReturnCode mss_restore_DRAM_repairs_asm( const fapi::Target & i_target, uint8_t & o_repairs_applied, uint8_t & o_repairs_exceeded, bool i_standby_flag, struct repair_count &o_repair_count) { FAPI_INF("ENTER mss_restore_DRAM_repairs()"); fapi::ReturnCode l_rc; uint8_t l_dramWidth = 0; uint8_t l_dqBitmap[DIMM_DQ_RANK_BITMAP_SIZE]; // 10 byte array of bad bits ecmdDataBufferBase l_data(64); uint8_t l_port=0; uint8_t l_dimm=0; uint8_t l_rank=0; uint8_t l_byte=0; uint8_t l_nibble=0; uint8_t l_dq_pair_index = 0; uint8_t l_bad_dq_pair_index = 0; uint8_t l_bad_dq_pair_count=0; uint8_t l_dq_pair_mask = 0xC0; uint8_t l_byte_being_steered = 0xff; uint8_t l_bad_symbol = MSS_INVALID_SYMBOL; uint8_t l_symbol_mark = MSS_INVALID_SYMBOL; uint8_t l_chip_mark = MSS_INVALID_SYMBOL; uint8_t l_dramSparePort0Symbol = MSS_INVALID_SYMBOL; uint8_t l_dramSparePort1Symbol = MSS_INVALID_SYMBOL; uint8_t l_eccSpareSymbol = MSS_INVALID_SYMBOL; bool l_spare_exists = false; bool l_spare_used = false; bool l_chip_mark_used = false; bool l_symbol_mark_used = false; uint8_t l_valid_dimms = 0; uint8_t l_valid_dimm[2][2]; bool l_x4_DRAM_spare_low_exists = false; bool l_x4_DRAM_spare_high_exists = false; bool l_x4_DRAM_spare_used = false; bool l_x4_ECC_spare_used = false; uint8_t l_index = 0; // NO_SPARE = 0, LOW_NIBBLE = 1, HIGH_NIBBLE = 2, FULL_BYTE = 3 uint8_t l_spare_dram[2][2][4]; // Array defining if spare dram exit //New structures Updated to use for ASMI menu uint8_t l_steer[8][3]; uint8_t l_mark_store[8][2]; enum { MSS_REPAIRS_APPLIED = 1, MSS_REPAIRS_EXCEEDED = 2, }; uint8_t l_repair_status[2][2][4]={ {{0,0,0,0} , {0,0,0,0}}, {{0,0,0,0} , {0,0,0,0}}}; static const uint8_t l_repairs_applied_translation[8]={ 0x80, //rank0 (maps to port0_dimm0, port1_dimm0) 0x40, //rank1 (maps to port0_dimm0, port1_dimm0) 0x20, //rank2 (maps to port0_dimm0, port1_dimm0) 0x10, //rank3 (maps to port0_dimm0, port1_dimm0) 0x08, //rank4 (maps to port0_dimm1, port1_dimm1) 0x04, //rank5 (maps to port0_dimm1, port1_dimm1) 0x02, //rank6 (maps to port0_dimm1, port1_dimm1) 0x01}; //rank7 (maps to port0_dimm1, port1_dimm1) static const uint8_t l_repairs_exceeded_translation[2][2]={ // dimm0 dimm1 { 0x8, 0x4 }, // port0 { 0x2, 0x1 }}; // port1 // Start with no repairs applies and no repairs exceeded o_repairs_applied = 0; o_repairs_exceeded = 0; // Get array attribute that defines if spare dram exits // l_spare_dram[port][dimm][rank] // NO_SPARE = 0, LOW_NIBBLE = 1, HIGH_NIBBLE = 2, FULL_BYTE = 3 // NOTE: Typically will same value for whole Centaur. l_rc = FAPI_ATTR_GET(ATTR_VPD_DIMM_SPARE, &i_target, l_spare_dram); if(l_rc) { FAPI_ERR("Error reading attribute to see if spare exists on %s.",i_target.toEcmdString()); return l_rc; } // Get l_dramWidth l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Find out which dimms are functional l_rc = FAPI_ATTR_GET(ATTR_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, &i_target, l_valid_dimms); if (l_rc) { FAPI_ERR("Failed to get attribute: ATTR_MSS_EFF_DIMM_FUNCTIONAL_VECTOR on %s.",i_target.toEcmdString()); return l_rc; } l_valid_dimm[0][0] = (l_valid_dimms & 0x80); // port0, dimm0 l_valid_dimm[0][1] = (l_valid_dimms & 0x40); // port0, dimm1 l_valid_dimm[1][0] = (l_valid_dimms & 0x08); // port1, dimm0 l_valid_dimm[1][1] = (l_valid_dimms & 0x04); // port1, dimm1 //Initializing the repair count array for(l_rank =0;l_rank < 8;l_rank++) { o_repair_count.symbolmark_count[l_rank] = 0; o_repair_count.chipmark_count[l_rank] = 0; o_repair_count.steer_count[l_rank] = 0; } memset(l_steer,MSS_INVALID_SYMBOL,8*3); memset(l_mark_store,MSS_INVALID_SYMBOL,8*3); // For each port in the given MBA:0,1 for(l_port=0; l_port> 2; } // If spare is bad but not used, not valid to try repair if ( l_spare_exists && (l_byte==9) && (l_bad_dq_pair_count > 0) && !l_spare_used) { FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: Bad unused spare - no valid repair on %s", i_target.toEcmdString()); break; } // If more than one dq pair is bad if(l_bad_dq_pair_count > 1) { // If spare x8 DRAM exists and not used yet, if (l_spare_exists && !l_spare_used) { l_bad_symbol = mss_centaurDQ_to_symbol(8*l_byte,l_port) - 3; if(i_standby_flag) { mss_put_dummy_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_port, // l_port: 0,1 l_bad_symbol, // First symbol index of byte to steer l_steer); } else { // Update read mux l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_port, // l_port: 0,1 l_bad_symbol); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating read mux on %s.",i_target.toEcmdString()); return l_rc; } // Update write mux if(i_standby_flag) { //do nothing } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::WRITE_MUX,// write mux l_port, // l_port: 0,1 l_bad_symbol); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating write mux on %s.",i_target.toEcmdString()); return l_rc; } // Spare now used on this port,dimm,rank l_spare_used = true; // Remember which byte is being steered // so we know where to apply chip or symbol mark // if spare turns out to be bad l_byte_being_steered = l_byte; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED CHIP WITH X8 STEER on %s", 8*l_byte, 8*l_byte+7,l_bad_symbol, l_bad_symbol+3, i_target.toEcmdString()); } // Else if chip mark not used yet, update mark store with chip mark else if (!l_chip_mark_used) { // NOTE: Have to do a read/modify/write so we // only update chip mark, and don't overwrite // symbol mark. if(i_standby_flag) { mss_get_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Reading this just to write it back l_chip_mark, // Expecting MSS_INVALID_SYMBOL since no chip mark l_mark_store); } else { // Read mark store l_rc = mss_get_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Reading this just to write it back l_chip_mark ); // Expecting MSS_INVALID_SYMBOL since no chip mark } if (l_rc) { FAPI_ERR("Error reading markstore on %s.",i_target.toEcmdString()); return l_rc; } // Special case: // If this is a bad spare byte we are analyzing // the chip mark goes on the byte being steered if (l_byte==9) { l_chip_mark = mss_centaurDQ_to_symbol(8*l_byte_being_steered,l_port) - 3; FAPI_ERR("WARNING: Bad spare so chip mark goes on l_byte_being_steered = %d on %s", l_byte_being_steered ,i_target.toEcmdString()); } else { l_chip_mark = mss_centaurDQ_to_symbol(8*l_byte,l_port) - 3; } if(i_standby_flag) { mss_put_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Writting back exactly what we read l_chip_mark, // First symbol index of byte getting chip mark l_mark_store); } else { // Write mark store l_rc = mss_put_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Writting back exactly what we read l_chip_mark ); // First symbol index of byte getting chip mark } if (l_rc) { FAPI_ERR("Error updating markstore on %s.",i_target.toEcmdString()); return l_rc; } // Chip mark now used on this rank l_chip_mark_used = true; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED CHIP WITH X8 CHIP MARK on %s", 8*l_byte, 8*l_byte+7,l_chip_mark, l_chip_mark+3 ,i_target.toEcmdString()); } // Else, more bad bits than we can repair so update o_repairs_exceeded else { o_repairs_exceeded |= l_repairs_exceeded_translation[l_port][l_dimm]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_EXCEEDED; // If port1 repairs exceeded and port0 had a repair, say port0 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_APPLIED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[0][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x",l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, REPAIRS EXCEEDED %s", 8*l_byte, 8*l_byte+7, i_target.toEcmdString()); // Break out of loop on bytes break; } } // End If bad symbol count > 1 //Else if bad symbol count = 1 else if(l_bad_dq_pair_count == 1) { // If symbol mark not used yet, update mark store with symbol mark if (!l_symbol_mark_used) { // NOTE: Have to do a read/modify/write so we // only update symbol mark, and don't overwrite // chip mark. // Read mark store if(i_standby_flag) { mss_get_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Expecting MSS_INVALID_SYMBOL since no symbol mark l_chip_mark, // Reading this just to write it back l_mark_store); } else { l_rc = mss_get_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Expecting MSS_INVALID_SYMBOL since no symbol mark l_chip_mark ); // Reading this just to write it back } if (l_rc) { FAPI_ERR("Error reading markstore on %s.",i_target.toEcmdString()); return l_rc; } // Special case: // If this is a bad spare byte we are analying // the symbol mark goes on the byte being steered if (l_byte==9) { l_symbol_mark = mss_centaurDQ_to_symbol(8*l_byte_being_steered + 2*l_bad_dq_pair_index,l_port); FAPI_ERR("WARNING: Bad spare so symbol mark goes on l_byte_being_steered = %d on %s", l_byte_being_steered, i_target.toEcmdString()); } else { l_symbol_mark = mss_centaurDQ_to_symbol(8*l_byte + 2*l_bad_dq_pair_index,l_port); } // Update mark store if(i_standby_flag) { mss_put_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Single bad symbol found on this byte l_chip_mark, // Writting back exactly what we read l_mark_store); } else { l_rc = mss_put_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Single bad symbol found on this byte l_chip_mark ); // Writting back exactly what we read } if (l_rc) { FAPI_ERR("Error updating markstore on %s.",i_target.toEcmdString()); return l_rc; } // Symbol mark now used on this rank l_symbol_mark_used = true; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbol %d, FIXED SYMBOL WITH X2 SYMBOL MARK on %s", 8*l_byte + 2*l_bad_dq_pair_index, 8*l_byte + 2*l_bad_dq_pair_index + 1, l_symbol_mark, i_target.toEcmdString()); } // Else if spare x8 DRAM exists and not used yet, update steer mux else if (l_spare_exists && !l_spare_used) { l_bad_symbol = mss_centaurDQ_to_symbol(8*l_byte,l_port) - 3; // Update read mux if(i_standby_flag) { mss_put_dummy_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_port, // l_port: 0,1 l_bad_symbol, // First symbol index of byte to steer l_steer); } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_port, // l_port: 0,1 l_bad_symbol ); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating read mux on %s.",i_target.toEcmdString()); return l_rc; } // Update write mux if(i_standby_flag) { //do nothing } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::WRITE_MUX,// write mux l_port, // l_port: 0,1 l_bad_symbol ); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating write mux on %s.",i_target.toEcmdString()); return l_rc; } // Spare now used on this port,dimm,rank l_spare_used = true; // Remember which byte is being steered // so we where to apply chip or symbol mark // if spare turns out to be bad l_byte_being_steered = l_byte; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED SYMBOL WITH X8 STEER on %s", 8*l_byte + 2*l_bad_dq_pair_index, 8*l_byte + 2*l_bad_dq_pair_index + 1, l_bad_symbol, l_bad_symbol + 3, i_target.toEcmdString()); } // Else if chip mark not used yet, update mark store with chip mark else if (!l_chip_mark_used) { // NOTE: Have to do a read/modify/write so we // only update chip mark, and don't overwrite // symbol mark. // Read mark store if(i_standby_flag) { mss_get_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Reading this just to write it back l_chip_mark, // Expecting MSS_INVALID_SYMBOL since no chip mark l_mark_store); } else { l_rc = mss_get_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Reading this just to write it back l_chip_mark ); // Expecting MSS_INVALID_SYMBOL since no chip mark } if (l_rc) { FAPI_ERR("Error reading markstore on %s.",i_target.toEcmdString()); return l_rc; } // Special case: // If this is a bad spare byte we are analying // the chip mark goes on the byte being steered if (l_byte==9) { l_chip_mark = mss_centaurDQ_to_symbol(8*l_byte_being_steered,l_port) - 3; FAPI_ERR("WARNING: Bad spare so chip mark goes on l_byte_being_steered = %d on %s", l_byte_being_steered, i_target.toEcmdString()); } else { l_chip_mark = mss_centaurDQ_to_symbol(8*l_byte,l_port) - 3; } // Update mark store if(i_standby_flag) { mss_put_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Writting back exactly what we read l_chip_mark, // First symbol index of byte getting chip mark l_mark_store); } else { l_rc = mss_put_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // Writting back exactly what we read l_chip_mark ); // First symbol index of byte getting chip mark } if (l_rc) { FAPI_ERR("Error updating markstore on %s.",i_target.toEcmdString()); return l_rc; } // Chip mark now used on this rank l_chip_mark_used = true; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED SYMBOL WITH X8 CHIP MARK on %s", 8*l_byte + 2*l_bad_dq_pair_index, 8*l_byte + 2*l_bad_dq_pair_index + 1, l_chip_mark, l_chip_mark + 3, i_target.toEcmdString()); } // Else, more bad bits than we can repair so update o_repairs_exceeded else { o_repairs_exceeded |= l_repairs_exceeded_translation[l_port][l_dimm]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_EXCEEDED; // If port1 repairs exceeded and port0 had a repair, say port0 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_APPLIED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[0][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, REPAIRS EXCEEDED on %s", 8*l_byte + 2*l_bad_dq_pair_index, 8*l_byte + 2*l_bad_dq_pair_index + 1, i_target.toEcmdString()); // Break out of loop on bytes break; } } // End If bad symbol count = 1 } // End For each byte 0-9, where 9 is the spare } // End x8 ECC // x4 ECC // x4 chip mark, x4 ECC steer, spare x4 DRAM if CDIMM else if (l_dramWidth == mss_MemConfig::X4) { // Determine if spare x4 DRAM exists l_x4_DRAM_spare_low_exists = l_spare_dram[l_port][l_dimm][l_rank] == mss_MemConfig::LOW_NIBBLE; l_x4_DRAM_spare_high_exists = l_spare_dram[l_port][l_dimm][l_rank] == mss_MemConfig::HIGH_NIBBLE; // Start with spare x4 DRAM not used l_x4_DRAM_spare_used = false; // Read mark store if(i_standby_flag) { mss_get_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // MSS_INVALID_SYMBOL, since no symbol mark in x4 mode l_chip_mark, // MSS_INVALID_SYMBOL if no chip mark l_mark_store); } else { l_rc = mss_get_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // MSS_INVALID_SYMBOL, since no symbol mark in x4 mode l_chip_mark ); // MSS_INVALID_SYMBOL if no chip mark } if (l_rc) { FAPI_ERR("Error reading markstore on %s.",i_target.toEcmdString()); return l_rc; } // Check if chip mark used (may have been used on other port) l_chip_mark_used = l_chip_mark != MSS_INVALID_SYMBOL; // READ steer mux if(i_standby_flag) { mss_check_dummy_steering( i_target, 4*l_dimm + l_rank, l_dramSparePort0Symbol, l_dramSparePort1Symbol, l_eccSpareSymbol, l_steer); } else { l_rc = mss_check_steering( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_dramSparePort0Symbol, // Should be MSS_INVALID_SYMBOL since not used yet l_dramSparePort1Symbol, // Should be MSS_INVALID_SYMBOL since not used yet l_eccSpareSymbol); // MSS_INVALID_SYMBOL if no ECC steer in place yet } if (l_rc) { FAPI_ERR("Error reading steer mux %s.",i_target.toEcmdString()); return l_rc; } // Check if ECC spare used (may have been used on other port) l_x4_ECC_spare_used = l_eccSpareSymbol != MSS_INVALID_SYMBOL; // For each byte 0-9, where 9 is the spare for(l_byte=0; l_byte> (4 * l_nibble))) { // If ECC spare is bad and not used, not valid to try repair if ((l_port==1) && (l_byte==8) && (l_nibble == 1) && !l_x4_ECC_spare_used) { FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: Bad unused x4 ECC spare - no valid repair on %s", i_target.toEcmdString()); } // Else if DRAM spare is bad and not used, not valid to try repair else if (((l_byte==9) && (l_nibble == 0) && l_x4_DRAM_spare_low_exists && !l_x4_DRAM_spare_used) || ((l_byte==9) && (l_nibble == 1) && l_x4_DRAM_spare_high_exists && !l_x4_DRAM_spare_used)) { FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: Bad unused x4 DRAM spare - no valid repair on %s", i_target.toEcmdString()); } // Else if on the nibble not connected to a spare else if (((l_byte==9) && (l_nibble == 0) && !l_x4_DRAM_spare_low_exists) || ((l_byte==9) && (l_nibble == 1) && !l_x4_DRAM_spare_high_exists)) { // Do nothing //FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); //FAPI_ERR("WARNING: This nibble has no spare x4 DRAM connected on %s", i_target.toEcmdString()); } // Else if spare x4 DRAM exists and not used yet (and not ECC spare) else if (((l_x4_DRAM_spare_low_exists || l_x4_DRAM_spare_high_exists) && !l_x4_DRAM_spare_used) && !((l_port==1) && (l_byte==8) && (l_nibble == 1))) { // Find first symbol index for this bad nibble l_bad_symbol = mss_centaurDQ_to_symbol(8*l_byte + 4*l_nibble, l_port) - 1; // Update read mux if(i_standby_flag) { mss_put_dummy_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_port, // l_port: 0,1 l_bad_symbol, // First symbol index of byte to steer l_steer); } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux l_port, // l_port: 0,1 l_bad_symbol); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating read mux on %s.",i_target.toEcmdString()); return l_rc; } // Update write mux if(i_standby_flag) { //do nothing } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::WRITE_MUX,// write mux l_port, // l_port: 0,1 l_bad_symbol); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating write mux on %s.",i_target.toEcmdString()); return l_rc; } // Spare now used on this port,dimm,rank l_x4_DRAM_spare_used = true; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED CHIP WITH X4 DRAM STEER on %s", 8*l_byte + 4*l_nibble, 8*l_byte + 4*l_nibble + 3,l_bad_symbol, l_bad_symbol+1, i_target.toEcmdString()); } // Else if x4 ECC spare not used yet (and not DRAM spare) else if (!l_x4_ECC_spare_used && !(((l_byte==9) && (l_nibble == 0) && l_x4_DRAM_spare_low_exists) || ((l_byte==9) && (l_nibble == 1) && l_x4_DRAM_spare_high_exists))) { // Find first symbol index for this bad nibble l_bad_symbol = mss_centaurDQ_to_symbol(8*l_byte + 4*l_nibble, l_port) - 1; // Update read mux if(i_standby_flag) { mss_put_dummy_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux mss_SteerMux::ECC_SPARE,// Use ECC spare l_bad_symbol, // First symbol index of byte to steer l_steer); } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::READ_MUX, // read mux mss_SteerMux::ECC_SPARE,// Use ECC spare l_bad_symbol); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating read mux on %s.",i_target.toEcmdString()); return l_rc; } // Update write mux if(i_standby_flag) { //do nothing } else { l_rc = mss_put_steer_mux( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 mss_SteerMux::WRITE_MUX,// write mux mss_SteerMux::ECC_SPARE,// Use ECC spare l_bad_symbol); // First symbol index of byte to steer } if (l_rc) { FAPI_ERR("Error updating write mux on %s.",i_target.toEcmdString()); return l_rc; } // Spare now used on this port,dimm,rank l_x4_ECC_spare_used = true; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED CHIP WITH X4 ECC STEER on %s", 8*l_byte + 4*l_nibble, 8*l_byte + 4*l_nibble + 3,l_bad_symbol, l_bad_symbol+1, i_target.toEcmdString()); } // Else if x4 chip mark not used yet else if (!l_chip_mark_used) { // If this is a bad deployed ECC spare, the chip mark goes on the nibble being steered if ((l_port==1) && (l_byte==8) && (l_nibble == 1) && l_x4_ECC_spare_used) { // Find first symbol index of the nibble being steered with the ECC spare if(i_standby_flag) { mss_check_dummy_steering( i_target, 4*l_dimm + l_rank, l_dramSparePort0Symbol, l_dramSparePort1Symbol, l_eccSpareSymbol, l_steer); } else { l_rc = mss_check_steering( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_dramSparePort0Symbol, // don't care l_dramSparePort1Symbol, // don't care l_eccSpareSymbol); // first symbol index of the nibble being steered with the ECC spare } if (l_rc) { FAPI_ERR("Error reading steer mux %s.",i_target.toEcmdString()); return l_rc; } l_chip_mark = l_eccSpareSymbol; FAPI_ERR("WARNING: bad deployed ECC spare, so chip mark goes on the nibble being steered, symbols %d-%d on %s", l_chip_mark, l_chip_mark+1, i_target.toEcmdString()); } // Else if this is a bad deployed DRAM spare, the chip mark goes on the nibble being steered else if (((l_byte==9) && (l_nibble == 0) && l_x4_DRAM_spare_low_exists && l_x4_DRAM_spare_used) || ((l_byte==9) && (l_nibble == 1) && l_x4_DRAM_spare_high_exists && l_x4_DRAM_spare_used)) { // Find first symbol index of the nibble being steered with the DRAM spare if(i_standby_flag) { mss_check_dummy_steering( i_target, 4*l_dimm + l_rank, l_dramSparePort0Symbol, l_dramSparePort1Symbol, l_eccSpareSymbol, l_steer); } else { l_rc = mss_check_steering( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_dramSparePort0Symbol, // first symbol index of the nibble being steered with the port0 DRAM spare l_dramSparePort1Symbol, // first symbol index of the nibble being steered with the port1 DRAM spare l_eccSpareSymbol); // don't care } if (l_rc) { FAPI_ERR("Error reading steer mux %s.",i_target.toEcmdString()); return l_rc; } l_chip_mark = (l_port == 0) ? l_dramSparePort0Symbol:l_dramSparePort1Symbol; FAPI_ERR("WARNING: bad deployed DRAM spare, so chip mark goes on the nibble being steered, symbols %d-%d on %s", l_chip_mark, l_chip_mark+1, i_target.toEcmdString()); } // Else this is not a bad deployed ECC or DRAM spare else { l_chip_mark = mss_centaurDQ_to_symbol(8*l_byte + 4*l_nibble, l_port) - 1; } // Update mark store if(i_standby_flag) { mss_put_dummy_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // MSS_INVALID_SYMBOL, since no symbol mark in x4 mode l_chip_mark, // First symbol index of byte getting chip mark l_mark_store); } else { l_rc = mss_put_mark_store( i_target, // MBA 4*l_dimm + l_rank, // Master rank: 0-7 l_symbol_mark, // MSS_INVALID_SYMBOL, since no symbol mark in x4 mode l_chip_mark ); // First symbol index of byte getting chip mark } if (l_rc) { FAPI_ERR("Error updating markstore on %s.",i_target.toEcmdString()); return l_rc; } // Chip mark now used on this rank l_chip_mark_used = true; // Update which rank 0-7 has had repairs applied o_repairs_applied |= l_repairs_applied_translation[4*l_dimm + l_rank]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_APPLIED; // If port1 repairs applied and port0 had repairs exceeded, say port1 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_APPLIED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[1][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x", l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, symbols %d-%d, FIXED CHIP WITH X4 CHIP MARK on %s", 8*l_byte + 4*l_nibble, 8*l_byte + 4*l_nibble + 3,l_chip_mark, l_chip_mark+1, i_target.toEcmdString()); } // Else, more bad bits than we can repair so update o_repairs_exceeded else { o_repairs_exceeded |= l_repairs_exceeded_translation[l_port][l_dimm]; l_repair_status[l_port][l_dimm][l_rank]=MSS_REPAIRS_EXCEEDED; // If port1 repairs exceeded and port0 had a repair, say port0 repairs exceeded too if ((l_repair_status[1][l_dimm][l_rank] == MSS_REPAIRS_EXCEEDED) && (l_repair_status[0][l_dimm][l_rank] == MSS_REPAIRS_APPLIED)) { o_repairs_exceeded |= l_repairs_exceeded_translation[0][l_dimm]; } FAPI_ERR("WARNING: port=%d, dimm=%d, rank=%d, l_dqBitmap[%d] = %02x",l_port, l_dimm, l_rank, l_byte, l_dqBitmap[l_byte]); FAPI_ERR("WARNING: dq %d-%d, REPAIRS EXCEEDED %s", 8*l_byte + 4*l_nibble, 8*l_byte + 4*l_nibble + 3, i_target.toEcmdString()); // Break out of loop on nibbles break; } } // End if nibble bad } // End for each nibble // Break of of loop on bytes is we have already exceeded repairs on this port,dimm,rank if (l_repair_status[l_port][l_dimm][l_rank]==MSS_REPAIRS_EXCEEDED) break; } // End for each byte } // End x4 ECC } // End loop on rank } // End if valid dimm } // End loop on dimm } // End loop on port //Updating steer and mark_store arrays if(i_standby_flag) { for(l_rank =0;l_rank < 8;l_rank++) { for(l_index =0;l_index<3;l_index++) { if( l_index == 0) { if(l_steer[l_rank][l_index] != MSS_INVALID_SYMBOL) { o_repair_count.steer_count[l_rank] = o_repair_count.steer_count[l_rank] + 1; } } if( l_index == 1) { if(l_steer[l_rank][l_index] != MSS_INVALID_SYMBOL) { o_repair_count.steer_count[l_rank] = o_repair_count.steer_count[l_rank] + 1; } } if( l_index == 2) { if(l_steer[l_rank][l_index] != MSS_INVALID_SYMBOL) { o_repair_count.chipmark_count[l_rank] = o_repair_count.chipmark_count[l_rank] + 1; } } } } for(l_rank =0;l_rank < 8;l_rank++) { for(l_index =0;l_index<2;l_index++) { if(l_index == 0) { if(l_mark_store[l_rank][l_index] != MSS_INVALID_SYMBOL) { o_repair_count.symbolmark_count[l_rank] = o_repair_count.symbolmark_count[l_rank] + 1; } } if(l_index == 1) { if(l_mark_store[l_rank][l_index] != MSS_INVALID_SYMBOL) { o_repair_count.chipmark_count[l_rank] = o_repair_count.chipmark_count[l_rank] + 1; } } } } } for(l_rank =0;l_rank < 8;l_rank++) { FAPI_INF("\n\n\n RANK %d\n\n\n",l_rank); FAPI_INF("\n \nSymbol mark count %d",o_repair_count.symbolmark_count[l_rank] ); FAPI_INF("\n \nchip mark count %d",o_repair_count.chipmark_count[l_rank]) ; FAPI_INF("\n \nsteer mark count %d",o_repair_count.steer_count[l_rank]) ; FAPI_INF("_________________________________________________________"); } FAPI_INF("o_repairs_applied = %02x\n", o_repairs_applied); FAPI_INF("o_repairs_exceeded = %02x\n", o_repairs_exceeded); FAPI_INF("EXIT mss_restore_DRAM_repairs()"); return l_rc; } //------------------------------------------------------------------------------ // mss_centaurDQ_to_symbol //------------------------------------------------------------------------------ uint8_t mss_centaurDQ_to_symbol( uint8_t i_dq, uint8_t i_port ) { uint8_t o_symbol = MSS_INVALID_SYMBOL; if ( 64 <= i_dq ) // DQs 64 - 71 { o_symbol = (71 - i_dq) / 2; // symbols 0 - 3 if ( 0 == i_port ) o_symbol += 4; // symbols 4 - 7 } else // DQs 0 - 63 { o_symbol = (71 - i_dq + 8) / 2; // symbols 8 - 39 if ( 0 == i_port ) o_symbol += 32; // symbols 40 - 71 } return o_symbol; } //------------------------------------------------------------------------------ // mss_IPL_UE_isolation //------------------------------------------------------------------------------ fapi::ReturnCode mss_IPL_UE_isolation( const fapi::Target & i_target, uint8_t i_rank, uint8_t (&o_bad_bits)[2][10]) { FAPI_INF("ENTER mss_IPL_UE_isolation()"); fapi::ReturnCode l_rc; uint32_t l_ecmd_rc = 0; static const uint32_t maintBufferReadDataRegs[2][2][8]={ // UE trap 0: // Port0 beat double word {{MAINT0_MBA_MAINT_BUFF0_DATA0_0x03010655, // 0 DW0 MAINT0_MBA_MAINT_BUFF2_DATA0_0x03010675, // 1 DW2 MAINT0_MBA_MAINT_BUFF0_DATA1_0x03010656, // 2 DW4 MAINT0_MBA_MAINT_BUFF2_DATA1_0x03010676, // 3 DW6 MAINT0_MBA_MAINT_BUFF0_DATA2_0x03010657, // 4 DW8 MAINT0_MBA_MAINT_BUFF2_DATA2_0x03010677, // 5 DW10 MAINT0_MBA_MAINT_BUFF0_DATA3_0x03010658, // 6 DW12 MAINT0_MBA_MAINT_BUFF2_DATA3_0x03010678},// 7 DW14 // Port1 {MAINT0_MBA_MAINT_BUFF1_DATA0_0x03010665, // 0 DW1 MAINT0_MBA_MAINT_BUFF3_DATA0_0x03010685, // 1 DW3 MAINT0_MBA_MAINT_BUFF1_DATA1_0x03010666, // 2 DW5 MAINT0_MBA_MAINT_BUFF3_DATA1_0x03010686, // 3 DW7 MAINT0_MBA_MAINT_BUFF1_DATA2_0x03010667, // 4 DW9 MAINT0_MBA_MAINT_BUFF3_DATA2_0x03010687, // 5 DW11 MAINT0_MBA_MAINT_BUFF1_DATA3_0x03010668, // 6 DW13 MAINT0_MBA_MAINT_BUFF3_DATA3_0x03010688}},//7 DW15 // UE trap 1: // Port0 {{MAINT0_MBA_MAINT_BUFF0_DATA4_0x03010659, // 0 DW0 MAINT0_MBA_MAINT_BUFF2_DATA4_0x03010679, // 1 DW2 MAINT0_MBA_MAINT_BUFF0_DATA5_0x0301065a, // 2 DW4 MAINT0_MBA_MAINT_BUFF2_DATA5_0x0301067a, // 3 DW6 MAINT0_MBA_MAINT_BUFF0_DATA6_0x0301065b, // 4 DW8 MAINT0_MBA_MAINT_BUFF2_DATA6_0x0301067b, // 5 DW10 MAINT0_MBA_MAINT_BUFF0_DATA7_0x0301065c, // 6 DW12 MAINT0_MBA_MAINT_BUFF2_DATA7_0x0301067c},// 7 DW14 // Port1 {MAINT0_MBA_MAINT_BUFF1_DATA4_0x03010669, // 0 DW1 MAINT0_MBA_MAINT_BUFF3_DATA4_0x03010689, // 1 DW3 MAINT0_MBA_MAINT_BUFF1_DATA5_0x0301066a, // 2 DW5 MAINT0_MBA_MAINT_BUFF3_DATA5_0x0301068a, // 3 DW7 MAINT0_MBA_MAINT_BUFF1_DATA6_0x0301066b, // 4 DW9 MAINT0_MBA_MAINT_BUFF3_DATA6_0x0301068b, // 5 DW11 MAINT0_MBA_MAINT_BUFF1_DATA7_0x0301066c, // 6 DW13 MAINT0_MBA_MAINT_BUFF3_DATA7_0x0301068c}}};//7 DW15 static const uint32_t maintBufferRead65thByteRegs[2][4]={ // UE trap 0 {MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC0_0x03010695, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC1_0x03010696, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC2_0x03010697, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC3_0x03010698}, // UE trap 1 {MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC4_0x03010699, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC5_0x0301069a, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC6_0x0301069b, MAINT0_MBA_MAINT_BUFF_65TH_BYTE_64B_ECC7_0x0301069c}}; uint8_t l_UE_trap = 0; // 0,1, since UE can be in 1st or 2nd half of buffer uint8_t l_port = 0; // 0,1 uint8_t l_beat = 0; // 0-7 uint8_t l_byte = 0; // 0-9 uint8_t l_nibble = 0; // 0-17 uint8_t l_loop = 0; ecmdDataBufferBase l_data(64); ecmdDataBufferBase l_UE_trap0_signature(64); ecmdDataBufferBase l_UE_trap1_signature(64); ecmdDataBufferBase l_mbmmr(64); ecmdDataBufferBase l_mbmct(64); ecmdDataBufferBase l_mbstr(64); uint8_t l_initPattern = 0; uint8_t l_cmd_type = 0; fapi::Target l_targetCentaur; uint8_t l_mbaPosition = 0; uint32_t l_tmp_data_diff[2]; uint8_t l_tag_MDI = 0; uint8_t l_tmp_65th_byte_diff = 0; ecmdDataBufferBase l_diff(64); uint32_t l_ECC = 0; uint32_t l_tmp_ECC_diff = 0; ecmdDataBufferBase l_ECC_diff(32); uint8_t l_ECC_c6_c5_c4_01 = 0; uint8_t l_ECC_c6_c5_c4_23 = 0; uint8_t l_ECC_c3_c2_c1_c0_01 = 0; uint8_t l_ECC_c3_c2_c1_c0_23 = 0; uint8_t l_dramSparePort0Symbol = MSS_INVALID_SYMBOL; uint8_t l_dramSparePort1Symbol = MSS_INVALID_SYMBOL; uint8_t l_eccSpareSymbol = MSS_INVALID_SYMBOL; uint8_t l_dramWidth = 0; //---------------------------------------------------- // Get l_dramWidth //---------------------------------------------------- l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dramWidth); if(l_rc) { FAPI_ERR("Error getting DRAM width on %s.",i_target.toEcmdString()); return l_rc; } // Convert from attribute enum values: 8,4 to index values: 0,1 if(l_dramWidth == mss_MemConfig::X8) { l_dramWidth = 0; } else { l_dramWidth = 1; } //---------------------------------------------------- // Initialize o_bad_bits //---------------------------------------------------- for(l_port=0; l_port<2; l_port++ ) { for(l_byte=0; l_byte<10; l_byte++ ) { o_bad_bits[l_port][l_byte] = 0; } } //---------------------------------------------------- // Get the expected pattern (stored in mbmmr reg) //---------------------------------------------------- // Get Centaur target for the given MBA l_rc = fapiGetParentChip(i_target, l_targetCentaur); if(l_rc) { FAPI_ERR("Error getting Centaur parent target for the given MBA, on %s.",i_target.toEcmdString()); return l_rc; } // Get MBA position: 0 = mba01, 1 = mba23 l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_target, l_mbaPosition); if(l_rc) { FAPI_ERR("Error getting MBA position on %s.",i_target.toEcmdString()); return l_rc; } // MBMMR[4:7] contains the pattern index l_rc = fapiGetScom(l_targetCentaur, mss_mbmmr[l_mbaPosition], l_mbmmr); if(l_rc) return l_rc; l_ecmd_rc |= l_mbmmr.extractPreserve(&l_initPattern, 4, 4, 8-4); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // MBMCT[0:4] contains the cmd type l_rc = fapiGetScom(i_target, MBA01_MBMCTQ_0x0301060A, l_mbmct); if(l_rc) return l_rc; l_ecmd_rc |= l_mbmct.extractPreserve(&l_cmd_type, 0, 5, 8-5); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // No isolation if cmd is timebased steer cleanup if (l_cmd_type == 2) { FAPI_ERR("WARNING: rank%d maint UE during steer cleanup - no bad bit isolation possible on %s.", i_rank, i_target.toEcmdString()); return l_rc; } // No isolation if pattern is random if (l_initPattern == 8) { FAPI_ERR("WARNING: rank%d maint UE with random pattern - no bad bit isolation possible on %s.", i_rank, i_target.toEcmdString()); return l_rc; } FAPI_INF("Expected pattern%d = 0x%.8X 0x%.8X",l_initPattern, mss_maintBufferData[l_dramWidth][l_initPattern][0][0], mss_maintBufferData[l_dramWidth][l_initPattern][0][1]); //---------------------------------------------------- // Figure out which half of the buffer has the UE... // Remember we had to first load the buffers with // a hex signatue, and whichever gets overwritten // has a UE trapped //---------------------------------------------------- l_rc = fapiGetScom(i_target, MAINT0_MBA_MAINT_BUFF0_DATA0_0x03010655, l_UE_trap0_signature); if(l_rc) return l_rc; l_rc = fapiGetScom(i_target, MAINT0_MBA_MAINT_BUFF0_DATA4_0x03010659, l_UE_trap1_signature); if(l_rc) return l_rc; // UE may be trapped in both halves of the buffer, // but we will only use one. if ((l_UE_trap0_signature.getWord(0) != 0xFACEB00C) && (l_UE_trap0_signature.getWord(0) != 0xD15C0DAD)) { FAPI_INF("UE trapped in 1st half of maint buffer"); l_UE_trap = 0; } else if ((l_UE_trap1_signature.getWord(0) != 0xFACEB00C) && (l_UE_trap1_signature.getWord(0) != 0xD15C0DAD)) { FAPI_INF("UE trapped in 2nd half of maint buffer"); l_UE_trap = 1; } else { FAPI_ERR("IPL UE trapping didn't work on i_rank = %d on %s.", i_rank, i_target.toEcmdString()); // Read for FFDC: MBSTR[59]: UE trap enable bit l_rc = fapiGetScom(l_targetCentaur, mss_mbstr[l_mbaPosition], l_mbstr); if(l_rc) return l_rc; // Calling out MBA target high, deconfig, gard const fapi::Target & MBA = i_target; // FFDC: Capture UE trap contents ecmdDataBufferBase & UE_TRAP0 = l_UE_trap0_signature; ecmdDataBufferBase & UE_TRAP1 = l_UE_trap1_signature; // FFDC: MBMCT[0:4] contains the cmd type ecmdDataBufferBase & MBMCT = l_mbmct; // FFDC: MBMMR[4:7] contains the pattern index ecmdDataBufferBase & MBMMR = l_mbmmr; // FFDC: MBSTR[59]: UE trap enable bit ecmdDataBufferBase & MBSTR = l_mbstr; // Create new log FAPI_SET_HWP_ERROR(l_rc, RC_MSS_MAINT_NO_UE_TRAP); return l_rc; } //---------------------------------------------------- // DATA: Do XOR of expected and actual data to find stuck bits //---------------------------------------------------- for(l_port=0; l_port<2; l_port++ ) { l_tmp_data_diff[0] = 0; l_tmp_data_diff[1] = 0; FAPI_INF("port%d", l_port); for(l_beat=0; l_beat<8; l_beat++ ) { l_rc = fapiGetScom(i_target, maintBufferReadDataRegs[l_UE_trap][l_port][l_beat], l_data); if(l_rc) return l_rc; FAPI_INF("Actual data, beat%d: 0x%.8X 0x%.8X", l_beat, l_data.getWord(0), l_data.getWord(1)); FAPI_INF("Expected pattern%d = 0x%.8X 0x%.8X",l_initPattern, mss_maintBufferData[l_dramWidth][l_initPattern][l_port*8 + l_beat][0], mss_maintBufferData[l_dramWidth][l_initPattern][l_port*8 + l_beat][1]); // DO XOR of actual and expected data, and OR the result together for all 8 beats l_tmp_data_diff[0] |= l_data.getWord(0) ^ mss_maintBufferData[l_dramWidth][l_initPattern][l_port*8 + l_beat][0]; l_tmp_data_diff[1] |= l_data.getWord(1) ^ mss_maintBufferData[l_dramWidth][l_initPattern][l_port*8 + l_beat][1]; FAPI_INF("***************************************** l_tmp_diff: 0x%.8X 0x%.8X", l_tmp_data_diff[0], l_tmp_data_diff[1]); } // Put l_tmp_diff into a ecmdDataBufferBase to make it easier // to get into o_bad_bits l_ecmd_rc |= l_diff.insert(l_tmp_data_diff[0], 0, 32, 0); l_ecmd_rc |= l_diff.insert(l_tmp_data_diff[1], 32, 32, 0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } for(l_byte=0; l_byte<8; l_byte++ ) { l_ecmd_rc |= l_diff.extractPreserve(&o_bad_bits[l_port][l_byte], 8*l_byte, 8, 0); } if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } } // End loop on ports //---------------------------------------------------- // 65th byte: Do XOR of expected and actual 65th byte to find stuck bits //---------------------------------------------------- for(l_loop=0; l_loop<4; l_loop++ ) { l_tag_MDI = 0; l_tmp_65th_byte_diff = 0; l_rc = fapiGetScom(i_target, maintBufferRead65thByteRegs[l_UE_trap][l_loop], l_data); if(l_rc) return l_rc; // Grab bit 0 = Checkbit0_1 // Grab bit 1 = Tag0_2 // Grab bit 2 = Tag1_3 // Grab bit 3 = MDI l_ecmd_rc |= l_data.extractPreserve(&l_tag_MDI, 0, 4, 0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } FAPI_INF("Actual: bit0 (Checkbit0_1), bit1(Tag0_2), bit2(Tag1_3), bit3(MDI) = 0x%.2X", l_tag_MDI); FAPI_INF("Expected: bit0 (Checkbit0_1), bit1(Tag0_2), bit2(Tag1_3), bit3(MDI) = 0x%.2X", mss_65thByte[l_dramWidth][l_initPattern][l_loop]); // DO XOR of actual and expected data l_tmp_65th_byte_diff = l_tag_MDI ^ mss_65thByte[l_dramWidth][l_initPattern][l_loop]; FAPI_INF("***************************************** l_tmp_65th_byte_diff: 0x%.2X", l_tmp_65th_byte_diff); // Check for mismatch in bit 0: Checkbit0_1 if (l_tmp_65th_byte_diff & 0x80) { // Checkbit0_1 maps to port0 bit 64, which is on byte8 o_bad_bits[0][8] |= 0x80; } // Check for mismatch in bit 1: Tag0_2 if (l_tmp_65th_byte_diff & 0x40) { // Tag0_2 maps to port0 bit 65, which is on byte8 o_bad_bits[0][8] |= 0x40; } // Check for mismatch in bit 2: Tag1_3 if (l_tmp_65th_byte_diff & 0x20) { // Tag1_3 maps to port0 bit 64, which is on byte8 o_bad_bits[0][8] |= 0x80; } // Check for mismatch in bit 3: MDI if (l_tmp_65th_byte_diff & 0x10) { // MDI maps to port0 bit 65, which is on byte8 o_bad_bits[0][8] |= 0x40; } } // End loops through trapped 65th byte info //---------------------------------------------------- // ECC: Do XOR of expected and actual ECC bits to find stuck bits //---------------------------------------------------- for(l_loop=0; l_loop<4; l_loop++ ) { l_ECC = 0; l_rc = fapiGetScom(i_target, maintBufferRead65thByteRegs[l_UE_trap][l_loop], l_data); if(l_rc) return l_rc; // Grab bits 4:15 = ECC_c6_c5_c4, and bits 16:31 = ECC_c3_c2_c1_c0 l_ecmd_rc |= l_data.extractPreserve(&l_ECC, 4, 28, 4); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } FAPI_INF("Actual: ECC = 0x%.8X", l_ECC); FAPI_INF("Expected: ECC = 0x%.8X", mss_ECC[l_dramWidth][l_initPattern][l_loop]); // DO XOR of actual and expected data l_tmp_ECC_diff |= l_ECC ^ mss_ECC[l_dramWidth][l_initPattern][l_loop]; FAPI_INF("***************************************** l_tmp_ECC_diff: 0x%.8X", l_tmp_ECC_diff); } // Put l_tmp_ECC_diff into a ecmdDataBufferBase to make it easier // to get into o_bad_bits l_ecmd_rc |= l_ECC_diff.insert(l_tmp_ECC_diff, 0, 32, 0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } l_ecmd_rc |= l_ECC_diff.extractPreserve(&l_ECC_c6_c5_c4_01, 4, 6, 8-6); l_ecmd_rc |= l_ECC_diff.extractPreserve(&l_ECC_c6_c5_c4_23, 10, 6, 8-6); l_ecmd_rc |= l_ECC_diff.extractPreserve(&l_ECC_c3_c2_c1_c0_01, 16, 8, 0); l_ecmd_rc |= l_ECC_diff.extractPreserve(&l_ECC_c3_c2_c1_c0_23, 24, 8, 0); if(l_ecmd_rc) { l_rc.setEcmdError(l_ecmd_rc); return l_rc; } // The 6 bits of ECC_c6_c5_c4 maps to byte8 on port0 o_bad_bits[0][8] |= l_ECC_c6_c5_c4_01 | l_ECC_c6_c5_c4_23; // The 8 bits of ECC_c3_c2_c1_c0 maps to byte8 byte on port1 o_bad_bits[1][8] |= l_ECC_c3_c2_c1_c0_01 | l_ECC_c3_c2_c1_c0_23; //---------------------------------------------------- // Spare: Mark byte9 bad if bad bits found in position being steered //---------------------------------------------------- // READ steer mux, which gets me a symbol for port0 and port1 l_rc = mss_check_steering(i_target, i_rank, l_dramSparePort0Symbol, l_dramSparePort1Symbol, l_eccSpareSymbol); if(l_rc) return l_rc; //---------------------------- // x8 //---------------------------- if (l_dramWidth == 0) { // If steering on port0 if ( l_dramSparePort0Symbol != 0xff) { // Find the byte being steered l_byte = mss_x8_chip_mark_to_centaurDQ[l_dramSparePort0Symbol/4][0]/8; // If that byte has any bad bits in it, copy them to byte9, if (o_bad_bits[0][l_byte]) { o_bad_bits[0][9] = o_bad_bits[0][l_byte]; // Clear byte being steered, since it did not contribute to UE o_bad_bits[0][l_byte] = 0; } } // If steering on port1 if ( l_dramSparePort1Symbol != 0xff) { // Find the byte being steered l_byte = mss_x8_chip_mark_to_centaurDQ[l_dramSparePort1Symbol/4][0]/8; // If that byte has any bad bits in it, copy them to byte9, if (o_bad_bits[1][l_byte]) { o_bad_bits[1][9] = o_bad_bits[1][l_byte]; // Clear byte being steered, since it did not contribute to UE o_bad_bits[1][l_byte] = 0; } } } //---------------------------- // x4 //---------------------------- else { // If steering on port0 if ( l_dramSparePort0Symbol != 0xff) { // Find the nibble being steered (0-17) l_nibble = mss_x4_chip_mark_to_centaurDQ[l_dramSparePort0Symbol/2][0]/4; // If odd nibble (1,3,5,7,9,11,13,15,17) if (l_nibble % 2) { // If that nibble has any bad bits in it, copy them to byte9, if (o_bad_bits[0][l_nibble/2] & 0x0f) { o_bad_bits[0][9] = (o_bad_bits[0][l_nibble/2] << 4) & 0xf0; // Clear nibble being steered, since it did not contribute to UE o_bad_bits[0][l_nibble/2] &= 0xf0; } } // Else even nibble (0,2,4,6,8,10,12,14,16) else { // If that nibble has any bad bits in it, copy them to byte9, if (o_bad_bits[0][l_nibble/2] & 0xf0) { o_bad_bits[0][9] = o_bad_bits[0][l_nibble/2] & 0xf0; // Clear nibble being steered, since it did not contribute to UE o_bad_bits[0][l_nibble/2] &= 0x0f; } } } // If steering on port1 if ( l_dramSparePort1Symbol != 0xff) { // Find the nibble being steered (0-17) l_nibble = mss_x4_chip_mark_to_centaurDQ[l_dramSparePort1Symbol/2][0]/4; // If odd nibble (1,3,5,7,9,11,13,15,17) if (l_nibble % 2) { // If that nibble has any bad bits in it, copy them to byte9, if (o_bad_bits[1][l_nibble/2] & 0x0f) { o_bad_bits[1][9] = (o_bad_bits[1][l_nibble/2] << 4) & 0xf0; // Clear nibble being steered, since it did not contribute to UE o_bad_bits[1][l_nibble/2] &= 0xf0; } } // Else even nibble (0,2,4,6,8,10,12,14,16) else { // If that nibble has any bad bits in it, copy them to byte9, if (o_bad_bits[1][l_nibble/2] & 0xf0) { o_bad_bits[1][9] = o_bad_bits[1][l_nibble/2] & 0xf0; // Clear nibble being steered, since it did not contribute to UE o_bad_bits[1][l_nibble/2] &= 0x0f; } } } // If ecc spare used if ( l_eccSpareSymbol != 0xff) { // Find the nibble being steered (0-17) l_nibble = mss_x4_chip_mark_to_centaurDQ[l_eccSpareSymbol/2][0]/4; // Find the port being steered (0,1) l_port = mss_x4_chip_mark_to_centaurDQ[l_eccSpareSymbol/2][1]; // If odd nibble (1,3,5,7,9,11,13,15,17) if (l_nibble % 2) { // If that nibble has any bad bits in it, copy them to port1,nibble 17 if (o_bad_bits[l_port][l_nibble/2] & 0x0f) { o_bad_bits[1][8] |= o_bad_bits[l_port][l_nibble/2] & 0x0f; // Clear nibble being steered, since it did not contribute to UE o_bad_bits[l_port][l_nibble/2] &= 0xf0; } } // Else even nibble (0,2,4,6,8,10,12,14,16) else { // If that nibble has any bad bits in it, copy them to port1,nibble 17 if (o_bad_bits[l_port][l_nibble/2] & 0xf0) { o_bad_bits[1][8] |= (o_bad_bits[l_port][l_nibble/2] >> 4) & 0x0f; // Clear nibble being steered, since it did not contribute to UE o_bad_bits[l_port][l_nibble/2] &= 0x0f; } } } } //---------------------------------------------------- // Show results //---------------------------------------------------- FAPI_ERR("WARNING: IPL UE isolation results for rank = %d on %s.", i_rank, i_target.toEcmdString()); FAPI_ERR("WARNING: Expected pattern = 0x%.8X", mss_maintBufferData[l_dramWidth][l_initPattern][0][0]); for(l_port=0; l_port<2; l_port++ ) { for(l_byte=0; l_byte<10; l_byte++ ) { FAPI_ERR("WARNING: o_bad_bits[port%d][byte%d] = %02x", l_port, l_byte, o_bad_bits[l_port][l_byte]); } } FAPI_INF("EXIT mss_IPL_UE_isolation()"); return l_rc; } //------------------------------------------------------------------------------ // mss_get_dummy_mark_store //------------------------------------------------------------------------------ void mss_get_dummy_mark_store( const fapi::Target & i_target, uint8_t i_rank, uint8_t & o_symbolMark, uint8_t & o_chipMark, uint8_t mark_store[8][2]) { FAPI_INF("ENTER mss_get_dummy_mark_store(), i_rank = %d", i_rank); o_symbolMark = mark_store[i_rank][0]; o_chipMark = mark_store[i_rank][1]; FAPI_INF("EXIT mss_get_dummy_mark_store(): o_symbolMark = %d, o_chipMark = %d", o_symbolMark, o_chipMark); } //------------------------------------------------------------------------------ // mss_put_dummy_mark_store //------------------------------------------------------------------------------ void mss_put_dummy_mark_store( const fapi::Target & i_target, uint8_t i_rank, uint8_t i_symbolMark, uint8_t i_chipMark, uint8_t mark_store[8][2]) { FAPI_INF("ENTER mss_put_dummy_mark_store(): i_rank = %d, i_symbolMark = %d, i_chipMark = %d", i_rank, i_symbolMark, i_chipMark ); mark_store[i_rank][0] = i_symbolMark; mark_store[i_rank][1] = i_chipMark; FAPI_INF("EXIT mss_put_dummy_mark_store()"); } //------------------------------------------------------------------------------ // mss_get_dummy_steer_mux //------------------------------------------------------------------------------ void mss_get_dummy_steer_mux( const fapi::Target & i_target, uint8_t i_rank, mss_SteerMux::muxType i_muxType, uint8_t & o_dramSparePort0Symbol, uint8_t & o_dramSparePort1Symbol, uint8_t & o_eccSpareSymbol, uint8_t steer[8][3]) { FAPI_INF("ENTER mss_get_dummy_steer_mux(): i_rank = %d", i_rank ); o_dramSparePort0Symbol = steer[i_rank][0]; o_dramSparePort1Symbol = steer[i_rank][1]; o_eccSpareSymbol = steer[i_rank][2]; FAPI_INF("EXIT mss_get_dummy_steer_mux(): port0 steer = %d, port1 steer = %d, ecc steer = %d", o_dramSparePort0Symbol, o_dramSparePort1Symbol, o_eccSpareSymbol ); } //------------------------------------------------------------------------------ // mss_put_dummy_steer_mux //------------------------------------------------------------------------------ void mss_put_dummy_steer_mux( const fapi::Target & i_target, uint8_t i_rank, mss_SteerMux::muxType i_muxType, uint8_t i_steerType, uint8_t i_symbol, uint8_t steer[8][3]) { FAPI_INF("ENTER mss_put_dummy_steer_mux(): i_rank = %d, i_steerType = %d, i_symbol = %d", i_rank, i_steerType, i_symbol ); steer[i_rank][i_steerType] = i_symbol; FAPI_INF("EXIT mss_put_dummy_steer_mux()"); } //------------------------------------------------------------------------------ // mss_check_dummy_steering //------------------------------------------------------------------------------ void mss_check_dummy_steering(const fapi::Target & i_target, uint8_t i_rank, uint8_t & o_dramSparePort0Symbol, uint8_t & o_dramSparePort1Symbol, uint8_t & o_eccSpareSymbol, uint8_t steer[8][3]) { // Get the read steer mux, with the assuption // that the write mux will be the same. mss_get_dummy_steer_mux( i_target, i_rank, mss_SteerMux::READ_MUX, o_dramSparePort0Symbol, o_dramSparePort1Symbol, o_eccSpareSymbol, steer); }