/**     h8_tests.c
 **
 ** Author: Ted Schmitz
 ** Date of original creation September 2, 2009
 **
 **     There are a number of tests the h8 can perform on itself via an Octeon
 ** request to run those tests.  This module contains logic to invoke those
 ** tests and wait for the results of the test from the h8.
 **
 **/
#include "h8_tests.h"
#include "ll_bist.h"
#include "diag_mon/errhand.h"
#include "diag_mon/errcodes.h"
#include "diag_mon/diag_mon.h"
#include "diag_mon/ascii_functions.h"
#include "io_drivers.h"

/* table of MMC sensors */
static struct sensor_table st[] = 
  {
    {SENSOR_1,  SENSOR_1_NAME},
    {SENSOR_2,  SENSOR_2_NAME},
    {SENSOR_3,  SENSOR_3_NAME},
    {SENSOR_4,  SENSOR_4_NAME},
    {SENSOR_5,  SENSOR_5_NAME},
    {SENSOR_6,  SENSOR_6_NAME},
    {SENSOR_7,  SENSOR_7_NAME},
    {SENSOR_8,  SENSOR_8_NAME},
    {SENSOR_9,  SENSOR_9_NAME},
    {SENSOR_10, SENSOR_10_NAME},
    {SENSOR_11, SENSOR_11_NAME},
    {SENSOR_12, SENSOR_12_NAME},

    {SENSOR_TABLE_TERM, 0},        /* table terminator */
  };


/*****************************************************************************
 **                          H8 Error Logic Test
 **
 **   This is a debug function to send commands to the H8 to verify 1st that 
 ** the H8 is listening for BIST commands and 2nd to force the H8 to return
 ** an error with the command to verify the software error logic is functioning
 ** correctly.  
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - A BIST command is sent to the H8 in which it intentionally reports
 **          back an error.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void h8_error_logic_test(void)
{
  int ret_status;             /* status returned from the Uboot call */

  /* This BIST command should not return errors */
  //ret_status = send_bist_cmd_to_h8(BIST_CMD_NOP, 0,0);

   /* This BIST command should return errors */
  ret_status = send_bist_cmd_to_h8(BIST_CMD_ERR_LOGIC_TEST, 0,0,0);

}

/*****************************************************************************
 **                        H8 FPGA Dual Port RAM Test
 **
 **   This is a function to instruct the H8 to run its FPGA dual-port RAM test
 ** and report the results back to the Octeon.
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - A BIST command is sent to the H8 to execute its FPGA dual-port
 **          RAM tests and report results back to Octeon.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void h8_fpga_dp_ram_test(void)
{
  int ret_status;             /* status returned from the Uboot call */

  /* This BIST command should not return errors */
  //ret_status = send_bist_cmd_to_h8(BIST_CMD_NOP, 0,0);

  /* This BIST command should return errors */
  ret_status = send_bist_cmd_to_h8(BIST_CMD_FPGA_RAM_TEST, 0,0,0);

}

/*****************************************************************************
 **                        H8 Sensor Test
 **
 **   This test sends a command to the H8 to retrieve individual sensor 
 ** readings including the upper and lower limits of that reading.  This test
 ** them compares the actual reading to the limits and reports an error if any
 ** sensor is greater then upper limit or les thatn the lower limit.  All 
 ** pertinent error information is also display with the error.
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - Octeon sends multiple commands (one for each sensor) to the h8 to
 **          retrieve each sensor's current readings and limits.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void h8_sensors_test(void)
{
  unsigned char bist_cmd_payload[FPGA_MB_MAX_BYTES];
  uint8_t bist_rx_msg[FPGA_MB_MAX_BYTES]; /* bist rx msg working space */

  int ret_status;             /* status returned from the Uboot call */
  unsigned short reading;     /* actual sensor reading */
  unsigned short lo_limit;    /* low sensor limit */
  unsigned short hi_limit;    /* high sensor limit */
  unsigned swork;             /* 16-bit working register */
  struct errhand_info eh;     /* err info structure */
  char umsg[80];              /* user created message */
  int i;

#ifdef SENSOR_DEBUG
  printf("\n");
  printf("\nSensor"
         "\nNumber LRead Reading HRead Name\n");
#endif

  i = 0;
  do
    {
    /* set up sensor num in payload */
    bist_cmd_payload[BC_SR_SENNUM] = st[i].sensor_no;
    ret_status = send_bist_cmd_to_h8(BIST_CMD_SENSOR_DIAG, BC_SR_PL_LEN_XMIT,
                                     bist_cmd_payload, bist_rx_msg);

    /* copy sensor data to working regs */
    reading = bist_rx_msg[BIST_RX_MB_PAYLOAD+BC_SR_RREAD];
    lo_limit = bist_rx_msg[BIST_RX_MB_PAYLOAD+BC_SR_LOWTH];
    hi_limit = bist_rx_msg[BIST_RX_MB_PAYLOAD+BC_SR_HIGHTH];

    /* verify sensor is >= low limit and <= high limit */
    if ((reading < lo_limit) || (reading > hi_limit))
      {
      sprintf(umsg, "Sensor %02d, '%s', is out of range!",
              st[i].sensor_no, st[i].sensor_name);
      eh.call_type = EH_DATA_ADRS_MSG_FRU;
      eh.error_stop = ES2800;
      eh.sup_error_stop = SES0000;
      eh.severity = SLEVEL_FATAL;
      swork = ((lo_limit << 8) & 0xFF00); /* combine lo & hi limits */
      swork |= (hi_limit & 0x00FF);
      eh.data_exp[0] = swork;
      eh.data_rec[0] = (unsigned int) reading;
      eh.fail_adrs = (unsigned int) st[i].sensor_no;
      eh.disp_size = DISP_SIZE_2B;
      eh.void_ptr = umsg;
      eh.fru_list[0] = mb;
      eh.fru_list[1] = 0xFF;

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

      //return FAIL;
      }

#ifdef SENSOR_DEBUG
    printf(" %03d    %03d    %03d    %03d  %s\n",
           st[i].sensor_no, lo_limit, reading, hi_limit, st[i].sensor_name);

#endif

    i++;
    } while (st[i].sensor_no != SENSOR_TABLE_TERM);


}

/*****************************************************************************
 **                      Display H8 Sensors
 **
 **   This function retrieves all the temperature sensor and voltage monitor
 ** readings and limits from the H8 and display them on the screen.
 ** 
 **
 ** INPUT - Nothing
 **
 ** OUTPUT - Octeon sends multiple commands (one for each sensor) to the h8 to
 **          retrieve each sensor's current readings and limits.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void disp_h8_sensors(void)
{
  unsigned char bist_cmd_payload[FPGA_MB_MAX_BYTES];
  uint8_t bist_rx_msg[FPGA_MB_MAX_BYTES]; /* bist rx msg working space */

  int ret_status;             /* status returned from the Uboot call */
  unsigned short reading;     /* actual sensor reading */
  unsigned short lo_limit;    /* low sensor limit */
  unsigned short hi_limit;    /* high sensor limit */
  int i;

  printf("\n");
  printf("\n- Dump Of MMC Sensors & Limits -");
  printf("\nSensor  Low  Actual  High  Sensor"
         "\nNumber Limit Reading Limit Name");
  printf("\n------ ----- ------- ----- -------------------\n");

  i = 0;
  do
    {
    /* set up sensor num in payload */
    bist_cmd_payload[BC_SR_SENNUM] = st[i].sensor_no;
    ret_status = send_bist_cmd_to_h8(BIST_CMD_SENSOR_DIAG, BC_SR_PL_LEN_XMIT,
                                     bist_cmd_payload, bist_rx_msg);

    /* copy sensor data to working regs */
    reading = bist_rx_msg[BIST_RX_MB_PAYLOAD+BC_SR_RREAD];
    lo_limit = bist_rx_msg[BIST_RX_MB_PAYLOAD+BC_SR_LOWTH];
    hi_limit = bist_rx_msg[BIST_RX_MB_PAYLOAD+BC_SR_HIGHTH];

    printf(" %03d    %03d    %03d    %03d  %s",
           st[i].sensor_no, lo_limit, reading, hi_limit, st[i].sensor_name);

    /* flag any readings that are out of range */
    if ((reading < lo_limit) || (reading > hi_limit))
      printf(" <-- OUT OF RANGE!\n");
    else
      printf("\n");

    i++;
    } while (st[i].sensor_no != SENSOR_TABLE_TERM);

}

/*****************************************************************************
 **                 BIST Menu Command To Set Mux Mode
 **
 **   This function is a BIST command to manually set up the XAUI muxes into
 ** one of the several available modes.
 ** 
 ** INPUT - Nothing
 **
 ** Value  Description
 ** -----  --------------------------------------------------------------
 ** 0x00   Configure mux according to current switch settings (normal mode)
 ** 0x01   Connect QLM1 & QLM3 to AMC connector.
 ** 0x02   Connect QLM1 & QLM3 to Front panel PHYs.
 ** 0x04   Loop data coming in from the AMC connector back to the AMC 
 **        connector.
 ** 0x08   Loop data from QLM1 & QLM3 back to QLM1 & QLM3 respectively.
 **
 **        All these mux modes are define in the appropriate "ll_bist.h"
 **        module near symbol "DIAG_BOARD_CONFIG_PORTS_INACTIVE".
 **
 ** OUTPUT - A BIST command is sent to the H8 to configure the XAUI mux.
 **
 ** RETURN - Nothing
 **
 ****************************************************************************/
void bist_menu_set_xaui_mux_mode(void)
{
  int mode;              /* mux mode entered by operator */
  int legal_mux_mode;    /* flag indication if mux mode is legal */
  int i;

  /* define all the legal mux modes */
  char mux_modes[] = 
    {DIAG_BOARD_CONFIG_PORTS_INACTIVE,
     DIAG_BOARD_CONFIG_PORTS_FORCEAMCS,
     DIAG_BOARD_CONFIG_PORTS_FORCEFRONT,
     DIAG_BOARD_CONFIG_PORTS_LOOPAMCS,
     DIAG_BOARD_CONFIG_PORTS_LOOPQLMS,
     0xFF};

  //printf("\nparam_count = %0d\n",param_count);

  legal_mux_mode = FALSE;  /* no legal mux mode found yet */

  /* make sure at least 1 parameter was entered */
  if (param_count >= 2)
    {
    /* conv 1st argument to mux mode */
    mode = conv_ascii_decimal_string_to_binary(args[1]); 

    // printf("mode = %0d\n",mode);

    /* see if the mux mode entered is legal */
    i = 0;
    do
      {
        //printf("mux_modes[%0d] = %0x\n",i, mux_modes[i]);
      if (mux_modes[i] == (char) mode)
        {
        legal_mux_mode = TRUE;
        break;
        }
      i++;
      } while (mux_modes[i] != (char) 0xFF);

    }
  
  /* display usage text if wrong number of parameters have been envetered or
     the operator entered an illegal mux mode.
  */
  if (legal_mux_mode != TRUE)
    {
    printf("\n\nIlegal mode or no mode entered!\n");
    printf("Set XAUI Mux mode command usage: ");
    printf("sx mode\n");
    printf("Where 'mode' is:\n");
    printf("Mode Description\n"
           "---- ---------------------------------------\n");
    printf(" 0   Config mux according to current switch settings "
           "(normal mode)\n");
    printf(" 1   Connect QLM1 & QLM3 to AMC connector.\n");
    printf(" 2   Connect QLM1 & QLM3 to Front panel PHYs.\n");
    printf(" 4   Loop data coming in from the AMC connector back to the AMC\n"
           "     connector.\n");
    printf(" 8   Loop data from QLM1 & QLM3 back to QLM1 & QLM3 "
           "respectively.\n");
  
    return;
    }

  /* set up the xaui mux mode now */
  h8_config_xaui_mux((unsigned char) mode);

  /**

  Don't forget to reset the xaui mode when BIST is exited.

  **/
}
