/**   pm_mem_test_56x4.c
 **
 **   This module includes all the low-level persistent memory tests for the 
 ** NPA-56x4 AMC card.
 **
 **   These tests run from Uboot after Uboot re-locates itself to RAM. 
 **
 ** Created by Ted Schmitz, June 9, 2009
 **
 **/
#include <common.h>

#include "pm_mem_test_npa56x4.h"
#include "diag_mon/errcodes.h"
#include "ll_bist.h"
#include "ll_post_types.h"
#include "common_mem_test.h"
#include "asm_utils.h"
#include "ll_post_utils.h"

/*****************************************************************************
 **               Persistent Memory Data Lines Test - Phase II
 **
 **   This function verifies the data lines to the Persistent Memory by writing
 ** and reading a variety of test patterns designed to verify each data pin 
 ** connected to the memory.  This is a Phase II test and is called by the 
 ** diagnostic monitor's test manager.
 **
 ** NOTE: ALL ERROR STOPS HAVE BEEN VERIFIED IN THIS TEST.
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - The data lines on the persistent memory will be verified.  Any
 **          failures will be reported to the system via the error handler.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void pm_data_lines_test(void)
{
  uint64_t * tp;                /* pointer to test patterns */
  volatile uint16_t * sptr;     /* 16-bit data working pointer */
  uint64_t cur_test_pat;        /* current 64-bit test pattern */
  uint16_t data_read;           /* data read back from PM */
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  uint16_t swork;               /* 16-bit working reg */
  struct errhand_info eh;       /* err info structure */
  int i;

  hl_spin_wheel();             /* let operator know we are not hung */

  /**   Must set up TLB to access the 0x13000000 - 0x14FFFFFF area. This 
   ** region is the persistent memory for both the TNPA-5644 & 
   ** TNPA-5654 boards.  In this case we use TLB 0 entry.
   **/
  //disp_tlbs();
  ll_write_tlb_entry(0, BEG_ADRS_OF_PERS_MEM_BLK_1, 
                     BEG_ADRS_OF_PERS_MEM_BLK_1, 
                     (LENGTH_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_2),
                     TLB_DVG_BITS);
  //disp_tlbs();

  /**   Start out by writing and verifying some basic patterns to see if we 
   ** have any stuck-ats or stuck-to's.
   **/
  tp = (uint64_t *) &data_test_pats_64b[0]; /* get pointer to test patterns */
  sptr = (uint16_t *) BEG_ADRS_OF_PERS_MEM_BLK_1; /* data lines test beg adrs */

  while(*tp != (uint64_t) END_OF_TABLE)
    {
    cur_test_pat = *tp;         /* get next test pat from table */

#ifdef ENABLE_DATA_LINES_DEBUG /* debug */
    //printf("tp = %08lX\n",(unsigned long) tp);
    printf("\ntest pat = %04x\n",(u16) cur_test_pat);
#endif

    //sptr[0] = (u16) 0x0102; /* DEBUG - mess up the data in ram */
    sptr[0] = (u16) cur_test_pat; /* write next test pat to test adrs */
    sptr[1] = (u16) ~cur_test_pat; /* write inverse test pat to next loc */
    //sptr[1] = (u16) 0x3210; /* DEBUG - mess up data in 2nd loc */

#if 0 /* hard way, read/write 2MB data */
    ll_asm_flush_cache(BEG_ADRS_LINES_TEST_ADDR_DR1,CACHE_FLUSH_READ_LENGTH);
#else /* easy way - flush L2 cache in hardare */
    ll_flush_l2c();  /* flush L2 cache in hardware */
#endif
    hl_spin_wheel();             /* let operator know we are not hung */
    /* read data back in 1st location and verify it */
    data_read = sptr[0];       /* read 1st location */

    if (data_read != (u16) cur_test_pat)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) cur_test_pat;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    /* read data back on upper DIMM and verify it */
    data_read = sptr[1];       /* read back 2nd location */

    if (data_read != (u16) ~cur_test_pat)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) ~cur_test_pat;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork+2;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    /**
     ** Do it again but reverse which location gets what test pattern.
     **/
    //sptr[0] = (u16) 0x0203; /* DEBUG - mess up the data in ram */
    sptr[0] = (u16) ~cur_test_pat; /* write inverse of test pat to 1st loc*/
    sptr[1] = (u16) cur_test_pat; /* write cur test pat to 2nd loc*/
    //sptr[1] = (u16) 0x4321; /* DEBUG - mess up data in 2nd loc */

    //ll_asm_flush_cache(BEG_ADRS_LINES_TEST_ADDR_DR1,CACHE_FLUSH_READ_LENGTH);
    ll_flush_l2c();  /* flush L2 cache in hardware */
    hl_spin_wheel();             /* let operator know we are not hung */

    /* read data back on lower DIMM and verify it */
    data_read = sptr[0];       /* read back 1st location */

    if (data_read != (u16) ~cur_test_pat)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) ~cur_test_pat;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    /* read data back on upper DIMM and verify it */
    data_read = sptr[1];       /* read back 2nd location */

    if (data_read != (u16) cur_test_pat)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) cur_test_pat;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork+2;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    tp++;                       /* inc pointer to next test pattern */
    } /* end while */

#if 1 /* disable for now */
  /** Okay so far.  Now walk a one and a zero through the data lines to
   ** check for any single bit being stuck to any other bit.
   **/
#ifdef ENABLE_DATA_LINES_DEBUG
  printf("Starting walking 1's test...\n");
#endif
  i = 0;

  do /* walking 1's test */
    {
    swork = ((1 << i) & 0xFFFF); /* calc next walking 1's pattern */

    //sptr[0] = (u16) 0x0304; /* DEBUG - mess up the data in ram */
    sptr[0] = swork;          /* write walking 1's to 1st location */
    sptr[1] = ~swork;         /* write walking 0's to 2nd location */
    //sptr[1] = (u16) 0x5432; /* DEBUG - mess up data in 2nd loc */

#ifdef ENABLE_DATA_LINES_DEBUG /* debug */
    printf("i = %0d\n",i);
    printf("next W1's pattern = %04lx, inverted = %04lx\n",swork, (u16)~swork);
#endif

    //ll_asm_flush_cache(BEG_ADRS_LINES_TEST_ADDR_DR1,CACHE_FLUSH_READ_LENGTH);
    ll_flush_l2c();  /* flush L2 cache in hardware */
    hl_spin_wheel();             /* let operator know we are not hung */

    /* read data back on lower DIMM and verify it */
    data_read = sptr[0];       /* read back 1st location */

    if (data_read != swork)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) swork;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    /* read data back from 2nd location */
    data_read = sptr[1];       /* read back 2nd location */

    if (data_read != (u16) ~swork)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) ~swork;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork+2;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    i++;
    } while (swork != 0x8000);

#ifdef ENABLE_DATA_LINES_DEBUG
  printf("Starting walking 0's test...\n");
#endif

  i = 0;
  do /* walking 0's on lower DIMM, walking 1's on upper DIMM */
    {
      swork = (u16) ~((1 << i) & 0xFFFF);

#ifdef ENABLE_DATA_LINES_DEBUG /* debug */
    //printf("i = %0d\n",i);
    printf("next W0's pattern = %04lx, inverted = %04lx\n",swork, (u16) ~swork);
#endif

    //sptr[0] = (u16) 0x0405; /* DEBUG - mess up the data in ram */
    sptr[0] = swork;         /* write walking 0's to 1st location */
    sptr[1] = (u16) ~swork;  /* write walking 1's to 2nd location */
    //sptr[1] = (u16) 0x6543; /* DEBUG - mess up data in 2nd loc */

    //ll_asm_flush_cache(BEG_ADRS_LINES_TEST_ADDR_DR1,CACHE_FLUSH_READ_LENGTH);
    ll_flush_l2c();  /* flush L2 cache in hardware */
    hl_spin_wheel();             /* let operator know we are not hung */

    /* read data back in 1st location */
    data_read = sptr[0];       /* read back 1st location */

    if (data_read != swork)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) swork;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    /* read data back from 2dn location */
    data_read = sptr[1];       /* read back 2nd location */

    if (data_read != (u16) ~swork)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2650;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) ~swork;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) sptr;
      fail_adrs = (uint64_t) lwork+2;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      return;
      }

    i++;
    } while (swork != 0x7FFF);
#endif /* if 0 */

  ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */

}

/*****************************************************************************
 **             Persistent Memory Address Lines Test - Phase II
 **
 **   This function verifies the address lines to the Persistent Memory by 
 ** writing a unique value to every 16-bit location then reading it all back
 ** and verifying the data.  This is a Phase II test and is called by the 
 ** diagnostic monitor's test manager.
 **
 ** NOTE: ALL ERROR STOPS HAVE BEEN VERIFIED IN THIS TEST.
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - The address lines on the persistent memory will be verified.  Any
 **          failures will be reported to the system via the error handler.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void pm_address_lines_test(void)
{
  volatile uint16_t * sptr;     /* 16-bit data working pointer */
  uint16_t data_read;           /* data read back from PM */
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  struct errhand_info eh;       /* err info structure */
  int i;

  hl_spin_wheel();             /* let operator know we are not hung */

  /**   Must set up TLB to access the 0x13000000 - 0x14FFFFFF area. This 
   ** region is the persistent memory for both the TNPA-5644 & 
   ** TNPA-5654 boards.  In this case we use TLB 0 entry.
   **/
  //disp_tlbs();
  ll_write_tlb_entry(0, BEG_ADRS_OF_PERS_MEM_BLK_1, 
                     BEG_ADRS_OF_PERS_MEM_BLK_1, 
                     (LENGTH_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_2),
                     TLB_DVG_BITS);
  //disp_tlbs();

  /* fill each location with a unique value */
  sptr = (uint16_t *) BEG_ADRS_OF_PERS_MEM_BLK_1; /* point to beg of PM */
  for (i = 0; i < LENGTH_PERS_MEM_BLK_1; i++)
    {
#if 0 /* debug - mess up one location to test error logic */
    if (i == 0x350)
      sptr[i] = (u16) 0xF0E1;
    else
#endif
   sptr[i] = (u16) i;        /* write next location */

    if ((i % PM_ADRS_LNS_WHEEL_INTER) == 0)
      hl_spin_wheel();             /* let operator know we are not hung */
    }

  hl_spin_wheel();             /* let operator know we are not hung */
  /* read it all back and verify the data in each location */
  for (i = 0; i < LENGTH_PERS_MEM_BLK_1; i++)
    {
    if ((i % PM_ADRS_LNS_WHEEL_INTER) == 0)
      hl_spin_wheel();             /* let operator know we are not hung */

    data_read = sptr[i];            /* read next location from PM */

    if (data_read != (u16) i)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2660;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = (u64) i;
      eh.data_rec[0] = (u64) data_read;
      lwork = (uint32_t) &sptr[i];
      fail_adrs = (uint64_t) lwork;
      eh.fail_adrs = fail_adrs;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    } /* end ' for (i = 0;...' */

  ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */

}

/*****************************************************************************
 **             Persistent Memory Cells Test - Phase II
 **
 **   This function verifies the address lines to the Persistent Memory by 
 ** writing a unique value to every 16-bit location then reading it all back
 ** and verifying the data.  This is a Phase II test and is called by the 
 ** diagnostic monitor's test manager.
 **
 ** NOTE: ALL ERROR STOPS HAVE BEEN VERIFIED IN THIS TEST.
 **
 ** ALSO NOTE:  This test takes about 2:12 to run using relocatable, assembly 
 **             language fill & verify routines and about 3:04 using "C"
 **             logic or assembly fill & verify that is run from FLASH.  Turns 
 **             out Persistent Memory is on the boot bus which has much slower 
 **             access speeds than the DDR2 bus.  Thus the seemingly long test 
 **             time for such a small block of memory.
 **
 **             It is unclear whether or not the assembly fill & verify routines
 **             actually work since I am unable to force a failure by messing
 **             up the data (unless I stop in the middle of one of the assembly
 **             functions with an emulator, then the bad data is detected).
 **             For this reason I elected to use the "C" write and verify logic
 **             for now.  Should revisit this issue at some future date.
 **             
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - The address lines on the persistent memory will be verified.  Any
 **          failures will be reported to the system via the error handler.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void pm_cells_test(void)
{
  uint64_t * tp;                /* pointer to test patterns */
  volatile uint16_t * sptr;     /* 16-bit data working pointer */
  uint64_t cur_test_pat;        /* current 64-bit test pattern */
  struct errhand_info eh;       /* err info structure */
  /* uint64_t asm_result_array[ASM_TEST_DATA_LEN]; */ /* asm test results array */
#ifndef USE_ASM_FUNCS_IN_CELLS_TEST
  uint64_t fail_adrs;           /* address where failure was detected */
  uint32_t lwork;               /* 32-bit working reg */
  uint16_t data_read;           /* data read back from PM */
  int i;
#endif

  invalidate_L1_Dcache();

  hl_spin_wheel();             /* let operator know we are not hung */

  /**   Must set up TLB to access the 0x13000000 - 0x14FFFFFF area. This 
   ** region is the persistent memory for both the TNPA-5644 & 
   ** TNPA-5654 boards.  In this case we use TLB 0 entry.
   **/
  //disp_tlbs();
  ll_write_tlb_entry(0, BEG_ADRS_OF_PERS_MEM_BLK_1, 
                     BEG_ADRS_OF_PERS_MEM_BLK_1, 
                     (LENGTH_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_2),
                     TLB_DVG_BITS);
  //disp_tlbs();

  tp = (uint64_t *) &data_test_pats_64b[0]; /* get pointer to test patterns */
  sptr = (uint16_t *) BEG_ADRS_OF_PERS_MEM_BLK_1; /* data lines test beg adrs */

  //printf("\n");
  while(*tp != (uint64_t) END_OF_TABLE)
    {
    cur_test_pat = *tp;         /* get next test pat from table */

    //printf("Writing test pattern = %04X\n",(u16) cur_test_pat);

#ifdef USE_ASM_FUNCS_IN_CELLS_TEST /* asm fill */

    /* fill 1st half of PM */
#if 1
    ll_fill_ram_16(BEG_ADRS_OF_PERS_MEM_BLK_1,
                   (BEG_ADRS_OF_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_1), 
                   (cur_test_pat & 0xFFFF));
#else
    ll_ram_fill_16_rel(BEG_ADRS_OF_PERS_MEM_BLK_1,
                      (BEG_ADRS_OF_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_1), 
                      ASM_CODE_REL_PM, (cur_test_pat & 0xFFFF));
#endif

    ll_flush_l2c();  /* flush L2 cache in hardware */
    hl_spin_wheel();             /* let operator know we are not hung */

    /* fill 2nd half of PM */
#if 1
    ll_fill_ram_16(BEG_ADRS_OF_PERS_MEM_BLK_2,
                   (BEG_ADRS_OF_PERS_MEM_BLK_2 + LENGTH_PERS_MEM_BLK_2), 
                   (cur_test_pat & 0xFFFF));
#else
    ll_ram_fill_16_rel(BEG_ADRS_OF_PERS_MEM_BLK_2,
                      (BEG_ADRS_OF_PERS_MEM_BLK_2 + LENGTH_PERS_MEM_BLK_2), 
                      ASM_CODE_REL_PM, (cur_test_pat & 0xFFFF));
#endif

    ll_flush_l2c();  /* flush L2 cache in hardware */
    hl_spin_wheel();             /* let operator know we are not hung */

#if 0 /* debug - cause a failure (this does not work) */
    sptr[0x345] = (u16) 0x1234;
    ll_flush_l2c();  /* flush L2 cache in hardware */
#endif

#else /* "C" logic fill */

    /* fill in the entire persitent memory with the next test pattern */
    for (i = 0; i < LENGTH_PERS_MEM_BLK_1; i++)
      {
#if 0 /* debug - mess up one location to test error logic */
      if (i == 0x1234)
        sptr[i] = (u16) 0xF0E1;
      else
#endif
     sptr[i] = (u16) cur_test_pat;    /* write next location */

      if ((i % PM_ADRS_LNS_WHEEL_INTER) == 0)
        hl_spin_wheel();             /* let operator know we are not hung */
      }
#endif

    //printf("Verifying test pattern = %04X\n",(u16) cur_test_pat);

#ifdef USE_ASM_FUNCS_IN_CELLS_TEST /* asm verify */
    invalidate_L1_Dcache();
    //cur_test_pat = (u16) 0x1234; /* cause a failure (this does not work here) */

    /* verify 1st half of PM */
#if 1
    /* this is the slower version */
    ll_asm_ram_cells_16_verify(BEG_ADRS_OF_PERS_MEM_BLK_1,
                    (BEG_ADRS_OF_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_1),
                    &asm_result_array[0], (cur_test_pat & 0xFFFF));
#else
    /* this version is considerably faster */
    ll_asm_ram_cells_verify_16_rel(BEG_ADRS_OF_PERS_MEM_BLK_1,
                    (BEG_ADRS_OF_PERS_MEM_BLK_1 + LENGTH_PERS_MEM_BLK_1),
                    &asm_result_array[0], ASM_CODE_REL_PM, 
                    (cur_test_pat & 0xFFFF));
#endif
    hl_spin_wheel();             /* let operator know we are not hung */

    /* if the line above is replaced with the line below, a failure should 
       occur. However, for some reason, no failure is detected??? */
                                   //0x0123456787654321ull);

    /* check the results and report any failures */
    if (asm_result_array[ASM_TEST_RESULTS] == ASM_TEST_FAILED)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2670;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = asm_result_array[ASM_TEST_EXP_DATA];
      eh.data_rec[0] = asm_result_array[ASM_TEST_BAD_DATA];
      eh.fail_adrs = asm_result_array[ASM_TEST_ADRS_AT_FAULT];
      eh.disp_size = DISP_SIZE_8B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

    /* verify 2nd half of PM */
#if 1
    ll_asm_ram_cells_16_verify(BEG_ADRS_OF_PERS_MEM_BLK_2,
                    (BEG_ADRS_OF_PERS_MEM_BLK_2 + LENGTH_PERS_MEM_BLK_2),
                    &asm_result_array[0], (cur_test_pat & 0xFFFF));
#else
    ll_asm_ram_cells_verify_16_rel(BEG_ADRS_OF_PERS_MEM_BLK_2,
                    (BEG_ADRS_OF_PERS_MEM_BLK_2 + LENGTH_PERS_MEM_BLK_2),
                    &asm_result_array[0], ASM_CODE_REL_PM, 
                    (cur_test_pat & 0xFFFF));
#endif
    hl_spin_wheel();             /* let operator know we are not hung */

    /* if the line above is replaced with the line below, a failure should 
       occur. However, for some reason, no failure is detected??? */
                                   //0x0123456787654321ull);

    /* check the results and report any failures */
    if (asm_result_array[ASM_TEST_RESULTS] == ASM_TEST_FAILED)
      {
      eh.call_type = EH_FAIL;
      eh.error_stop = ES2670;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      eh.data_exp[0] = asm_result_array[ASM_TEST_EXP_DATA];
      eh.data_rec[0] = asm_result_array[ASM_TEST_BAD_DATA];
      eh.fail_adrs = asm_result_array[ASM_TEST_ADRS_AT_FAULT];
      eh.disp_size = DISP_SIZE_8B;
      eh.void_ptr = 0;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

      /* report the error to the BIST system */
      error_handler(&eh);
      ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
      return;
      }

#else /* "C" logic verify */

    /* read it all back and verify every location is correct */
    for (i = 0; i < LENGTH_PERS_MEM_BLK_1; i++)
      {
      if ((i % PM_ADRS_LNS_WHEEL_INTER) == 0)
        hl_spin_wheel();             /* let operator know we are not hung */

      data_read = sptr[i];            /* read next location from PM */

      //cur_test_pat = (u16) 0x1234; /* cause a failure (this works) */

      if (data_read != (u16) cur_test_pat)
        {
        eh.call_type = EH_FAIL;
        eh.error_stop = ES2670;
        eh.sup_error_stop = SES0000;
        eh.severity = SLEVEL_FATAL;
        eh.data_exp[0] = (u64) cur_test_pat;
        eh.data_rec[0] = (u64) data_read;
        lwork = (uint32_t) &sptr[i];
        fail_adrs = (uint64_t) lwork;
        eh.fail_adrs = fail_adrs;
        eh.disp_size = DISP_SIZE_2B;
        eh.void_ptr = 0;
        eh.fru_list[0] = mb;
        eh.fru_list[1] = 0xFF;

        /* report the error to the BIST system */
        error_handler(&eh);
        ll_restore_tlb_entry_0(); /* restore TLB 0 back to original values */
        return;
        }

      }/* end 'for (i = 0;...' */
#endif

    tp++;                       /* inc pointer to next test pattern */
    } /* end while */

}

