/**   phase1_error_handler.c
 **
 **   This module includes functions to handle error conditions for the
 ** built-in BIST tests
 **
 ** Created by Ted Schmitz, October 15, 2008
 **
 ** DATE    INTLS  Description
 ** ------- ------ ------------------------------
 ** 4-10-09  TMS   Ported the code to the TNPA-56x4 board and made mecessary
 **                updates to work with BIST system.  Removed all references
 **                to global variables so the code coudl be called before BIST
 **                was moved into RAM.
 **/
#include <common.h>
#include <config.h>
#include "ll_bist.h"
#include "diag_mon/ascii_functions.h"
#include "diag_mon/errcodes.h"
#include "common_mem_test.h"
#include "phase1_error_handler.h"
#include "ll_post_types.h"
#include "diag_mon/errhand.h"
#include "ll_post_utils.h"
#include "ll_post.h"


/*****************************************************************************
 **                      Phase One Error handler
 **                        Report A RAM Error
 **
 **    This function is called when a RAM test fails.  It performs
 ** the following duties:
 ** 1 - Terminate the test sign on message with: "Failed!\n"
 ** 2 - Display all the available error informaton like: failure address, 
 **     expected & received data, etc.
 ** 3 - Save all error information in NVRAM
 **
 ** INPUT - "msp" = pointer to ASCII message, terminated with a null, to be
 **         displayed by this function.
 **       - "fail_adrs" = 64-bit address where problem was detected.
 **       - "exp_data" = 64-bit data expected at failure address.
 **       - "bad_data_rec" = 64-bit bad data read from failure address.
 **       - "length" = length, in bytes, of the expected and received data.
 **
 ** OUTPUT - User supplied message, if any, will be displayed on the console.
 **        - Failure information will be displayed on the console.
 **        - Failure information will be saved in NVRAM.
 **
 ** RETURN - Nothing
 **
 *****************************************************************************/
void p1_error_handler(struct error_data * eh)
{
  int result;                    /* results of various func calls, etc. */
  unsigned char bworke;          /* 8-bit expected data */
  unsigned char bworkr;          /* 8-bit received data */
  unsigned short sworke;         /* 16-bit expected data */
  unsigned short sworkr;         /* 16-bit received data */
  unsigned long lworke;          /* 32-bit expected data */
  unsigned long lworkr;          /* 32-bit received data */
  unsigned short test_modes;     /* test modes retrieved from SEEPROM */
  union b64_data b64;            /* union to manage a 64-bit data */
  struct save_fail sf;           /* failure save info structure */

  if ((eh->call_type & EH_DISP_WARN) == EH_DISP_WARN)
    {
    printf("Warning!\n");         /* terminate test sign-on message */
    sf.eh.severity = SLEVEL_WARN; /* save in main err hand struct */
    }
  else
    {
    printf("Failed!\n");          /* terminate test sign-on message */
    sf.eh.severity = SLEVEL_FATAL; /* save in main err hand struct */

    /**
     ** flag a test has failed 
     **/
    /* read up test modes */
    result = read_select_data_from_seeprom_timed((unsigned char *) 
                                                 &test_modes, TEST_MODE_OS, 
                                                 TOT_TMODE_BYTES);
    if (result == PROBLEM_DETECTED)
      {
      report_seeprom_problem(ES2690);   /* log the error & exit */
      return;
      }

    test_modes |= TM_ERR_PENDING;      /* flag the error */

    /* write "fatal error detected" flag to seeprom */
    result = write_select_data_to_seeprom_timed((unsigned char *) &test_modes,
                                                TEST_MODE_OS, TOT_TMODE_BYTES);
    if (result == PROBLEM_DETECTED)
      {
      report_seeprom_problem(ES2700);     /* log the error & exit */
      return;
      }

    /* re-calc & store new check sum */
    if (calc_write_seeprom_csum_timed() == PROBLEM_DETECTED)
      report_seeprom_problem(ES2700);     /* log the error & exit */

    } /* end 'if ((eh->call_type...' */

  if (eh->msgp != 0x00)         /* disp any user supplied messages */
    printf("\n%s\n",eh->msgp);

  printf("\nError Code = %04X%04X\n",eh->error_stop,eh->sup_error_stop);

  b64.llwork = eh->fail_adrs;
  printf("Failure address = %016qx\n", eh->fail_adrs);
  //sf.eh.fail_adrs = b64.ul.lo_work; /* save in main err hand struct */
  sf.eh.fail_adrs = eh->fail_adrs; /* save in main err hand struct */

  if (eh->length == BYTES_1)
    { /* convert exp & rec data to 8-bit values */
    bworke = (unsigned char) eh->exp_data;
    bworkr = (unsigned char) eh->rec_data;
    printf("Data expected: %02x\n",bworke);
    printf("Bad data rec: %02x\n",bworkr);
    sf.eh.disp_size = DISP_SIZE_1B;
    }
  else if (eh->length == BYTES_2)
    { /* convert exp & rec data to 16-bit values */
    sworke = (unsigned char) eh->exp_data;
    sworkr = (unsigned char) eh->rec_data;
    printf("Data expected: %04x\n",sworke);
    printf("Bad data rec: %04x\n",sworkr);
    sf.eh.disp_size = DISP_SIZE_2B;
    }
  else if (eh->length == BYTES_4)
    { /* convert exp & rec data to 16-bit values */
    lworke = (unsigned char) eh->exp_data;
    lworkr = (unsigned char) eh->rec_data;
    printf("Data expected: %08x\n",lworke);
    printf("Bad data rec: %08x\n",lworkr);
    sf.eh.disp_size = DISP_SIZE_4B;
    }
  else
    { /* BYTES_8: display native 64-bit values */
    b64.llwork = eh->exp_data;
    printf("Data expected: %08lX%08lX\n",b64.ul.up_work,b64.ul.lo_work);
#if 0 /* old way saves 32-bits in each of two elements of array */
    sf.eh.data_exp[0] = b64.ul.up_work;/* save in main err hand struct */
    sf.eh.data_exp[1] = b64.ul.lo_work;
#else /* new way saves all 64-bits on one array element */
    sf.eh.data_exp[0] = eh->exp_data;/* save in main err hand struct */
#endif
    b64.llwork = eh->rec_data;
    printf("Bad data rec: %08lX%08lX\n",b64.ul.up_work,b64.ul.lo_work);

#if 0 /* old way saves 32-bits in each of two elements of array */
    sf.eh.data_rec[0] = b64.ul.up_work;/* save in main err hand struct */
    sf.eh.data_rec[1] = b64.ul.lo_work;
#else/* new way saves all 64-bits on one array element */
    sf.eh.data_rec[0] = eh->rec_data;/* save in main err hand struct */
#endif
    sf.eh.disp_size = DISP_SIZE_8B;
    }

  printf("\n");

  /**   Save error information in non-volatile storage.  To do this fill
   ** the appropriate structure with the error information and call the
   ** common nvram save utility.
   **/
  sf.eh.call_type = (int) eh->call_type;
  sf.eh.error_stop = eh->error_stop;
  sf.eh.sup_error_stop = eh->sup_error_stop;
  sf.eh.void_ptr = 0;
  sf.eh.fru_list[0] = 0xff; /* nor FRUs for now */
  sf.test_no = eh->test_no;
  sf.exec_count = eh->exec_count;
  sf.err_msg[0] = 0;

  save_error_info_in_nv_storage(&sf);

}

