/**************************************************************
$Workfile:   diagSys.c  $
***************************************************************
**
** FIRMWARE, Copyright (C) 2000-2002        
** Ikanos Communication, Fremont, CA  
** All rights reserved.
**
** The information and contents of this file are the
** proprietary information of Ikanos Communication and may not
** be disclosed or used without the formal written approval of
** Ikanos Communication
**
$Revision: 1.1 $
$Date: 2006/10/16 04:34:50 $
**************************************************************/

#include "stdio.h"
#include "string.h"
#include "bsp.h"

#include "bitmask.h"
#include "dapi.h"
#include "apiproto.h"
#include "ipos.h"
//#include "elmdef.h"
#include "afeIntf.h"

#include "diag.h" 
#include "diag_ver.h"

/***********************************************************************/
/*                   LOCAL TYPES and CONSTS                            */ 
/***********************************************************************/

#define AFE_PROMPTS 

/* --- System Tests --- */
#define IPOSD_MSEC_BME_CONFIG_WAIT 300  /* 1044 symbols*250usec + margin */

//typedef int  (*iposDiagFunc) (tBmeStruct *pBme, int portNum);                                                                                                                                  

/***********************************************************************/
/*                   LOCAL VARIABLES                                   */ 
/***********************************************************************/
static bool bPrintOutput;     

static bool bTestInProgress; 
static int  diagErrCode;


/***********************************************************************/
/*                   LOCAL FUNCTIONS                                   */
/***********************************************************************/
static bool diagIsPrintOutputOk();


/*******************************************************************************
/*                  SYSTEM TEST Configuration 
/*          
/*******************************************************************************/

void iposDiagSetDefaultBmeProfile (ipos_bme_provision *pBmeProvision)
{
  memset ((char *)pBmeProvision, 0, sizeof(ipos_bme_provision));

  pBmeProvision->vendorIdT1E1 = 3;       /* vendor ID for T1E1, not used for ITU */
  pBmeProvision->vendorIdITU[8] = 55;    /* vendor ID for ITU, not used not used for T1E1 vendorIdITU[8]*/
  pBmeProvision->revisionNum = 17185;    /* revision number      */
  pBmeProvision->serialNum[32] = 13;     /* serial number        */
  pBmeProvision->utopiaOption = 0x03;    /* bit0:ATM_LEVEL_2, bit1: ATM extend mode
                                         /*      bit3: ATM_remove_hec, bit7: Packet Transport mode */
  pBmeProvision->utopiaDataSize = 53;   /* default: 53, range: 5-255    */
  pBmeProvision->optionMask = 0;         /* bit0: NTR_DISABLE, bit1: IMUX_ENABLE */
  pBmeProvision->bandPlan = BP3_998_4;   /* System band plan                     */
  pBmeProvision->numPort = IPOS_MAX_PORTS/IPOS_MAX_BME; /* Max Number of Ports */
  //pBmeProvision->psdMaskLevelIndx;
  //pBmeProvision->k0[3];
  //pBmeProvision->k1[3];
  //pBmeProvision->custId;
  //pBmeProvision->[3];

}

void iposDiagSetCoDefaultPortProfile (ipos_port_profile *pPortProfile)
{
  memset ((char *)pPortProfile, 0, sizeof(ipos_port_profile));

  pPortProfile->PortProfileNum=1; 

  /* Port Provision parameters */
  pPortProfile->PortProvParms.InterleavedChannel = 1; /* 0 - 63 */
  pPortProfile->PortProvParms.FastChannel = 0;                /* 0 - 63 */
  pPortProfile->PortProvParms.LineType = 0x81;     /* automatic */
  pPortProfile->PortProvParms.DslMode = 5; /* Both fast and interleaved/slow channel exists */
  pPortProfile->PortProvParms.RateAdaptationMode = 1;        /* Startup */
  pPortProfile->PortProvParms.InterleavedPercentage = 100;
  pPortProfile->PortProvParms.UpstreamMaxRateFast = 800; /* kbps */
  pPortProfile->PortProvParms.UpstreamMinRateFast = 10; /* kbps */
  pPortProfile->PortProvParms.UpstreamMaxRateSlow = 0; /* kbps */
  pPortProfile->PortProvParms.UpstreamMinRateSlow = 0; /* kbps */
  pPortProfile->PortProvParms.UpstreamMaxInterDelay = 20; /* milli seconds ? */
  pPortProfile->PortProvParms.DownstreamMaxRateFast = 800; /* kbps */
  pPortProfile->PortProvParms.DownstreamMinRateFast = 10; /* kbps */
  pPortProfile->PortProvParms.DownstreamMaxRateSlow = 0; /* kbps */
  pPortProfile->PortProvParms.DownstreamMinRateSlow = 0; /* kbps */
  pPortProfile->PortProvParms.DownstreamMaxInterDelay = 20; /* milli seconds ? */
  pPortProfile->PortProvParms.NumParityFast = 4; /* no.of parity bytes */
  pPortProfile->PortProvParms.NumParitySlow = 4; /* no.of parity bytes */
  pPortProfile->PortProvParms.MaxNoiseMargin = 28; /* 0 - 31.0 db, steps of 0.1 db */
  pPortProfile->PortProvParms.TargetNoiseMargin = 12; /* 0 - 31 db, steps of 0.1 db */
  pPortProfile->PortProvParms.MinNoiseMargin = 10; /* 0 - 31 db, steps of 0.1 db */
  pPortProfile->PortProvParms.BandPlan=BP3_998_4;
  pPortProfile->PortProvParms.NumRFIBand=0;
  /* Set these if NumRFIBand>0*/
  pPortProfile->PortProvParms.Band1Start=0;
  pPortProfile->PortProvParms.Band1Stop=0;

  pPortProfile->PortProvParms.RFIBand1 = 0;
  pPortProfile->PortProvParms.RFIBand2 = 0;
  pPortProfile->PortProvParms.RFIBand3 = 0;
  pPortProfile->PortProvParms.RFIBand4 = 0;
  pPortProfile->PortProvParms.RFIBand5 = 0;

  pPortProfile->OptionParms.PortOption = 0;
  pPortProfile->OptionParms.Reserved1 = 0;
  pPortProfile->OptionParms.Reserved2 = 0;
  pPortProfile->OptionParms.Reserved3 = 0;

  /* Port Instantiate paramaters */

  /* Port Start Reset parameters */
  pPortProfile->PortStartResetParms.PortStartParm = 0;        /* StartMode - Port Initiate, 
                                                                                                                    RateAdaptationMode - Fixed */

  /* Port Stop parameters */
  pPortProfile->PortStopParms.PortStopParm = 1; /* graceful stop */

  pPortProfile->BandMod.bandModifier = 0x33;               //optional band off
  /* Port Destroy parameters */

  return; 
}


/*******************************************************************************
/*                  SYSTEM TEST Rx Msg Polling
/*          
/*******************************************************************************/

int diagRcvPoll(ipos_port_id pid, int txMsgErrCode, int nMsecsRxWait)
{
  int tick = 10;
  int i;
  int errCode;

  #define IPOSD_MSECS_PER_LOOP (100)

  //IPOS_PRINTF("\ntxMsgErrCode (0x%x)\n", txMsgErrCode);
  if (txMsgErrCode == IPOS_SUCCESS)
  {
    for (i=0; i < nMsecsRxWait;)
    {
      delayMSecs(IPOSD_MSECS_PER_LOOP);
      /* tick is the polling period in msec  - Not Applicable for NO OS */
      errCode = iposEntryRcvPoll(tick, pid.bmeNum);   
      if (bTestInProgress == FALSE)
        break;
      i += IPOSD_MSECS_PER_LOOP;
    }

    if (bTestInProgress == TRUE)
    {
      IPOS_PRINTF("\nTIMEOUT!!! diagRcvPoll\n");
      errCode = IPOS_ERROR_EXPIRED;
      bTestInProgress = FALSE;
    }
    else
      errCode = diagErrCode; //Set in the Callback routine
  }
  else
    errCode = txMsgErrCode;

  //IPOS_PRINTF("errCode(0x%x)\n", errCode);
  return (errCode);
}




/*******************************************************************************/
/*                  SYSTEM TESTS Functions
/*          
/*  These functions are similiar to those found in iposapi.c.  The system
/*  test functions use the standard iPOS interface.  The Transmit/Receive 
/*  Maintenance interface is part of the standard iPOS.  The iPOS
/*  is only run when the BME is executing code and can send and receive 
/*  messages.
/*  
/*******************************************************************************/





/***********************************************************************/
/*     IPOS Diagnostic Interfaces(Wrappers) for System Tests           */
/***********************************************************************/

int iposDiagBmeProvision(int BmeNum, ipos_bme_provision *pBmeProvision)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;
  ipos_port_id pid;

  pid.bmeNum = BmeNum;
  pid.portNum = 1;


  IPOS_DIAG_PRINTB(BmeNum, IPOSD_PRINT_TRACE,"IPOS_DIAG:BME PROVISION.........");
  errCode = iposBmeProvision(BmeNum, pBmeProvision, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);

  return (errCode);
}

int iposDiagPortProvision(ipos_port_id pid, ipos_port_profile *pPortProfile)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:PORT PROVISION........");
  errCode = iposPortProvision(pid, pPortProfile, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}

int iposDiagPortStart(ipos_port_id pid)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:PORT START............");
  errCode = iposPortStart(pid, cmdTag, cntRpt, (void *)iposDiagPortStartCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_START_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}

int iposDiagPortReset(ipos_port_id pid)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  U8 portResetParm = 1;
  int errCode = IPOS_SUCCESS;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:PORT RESET............");
  errCode = iposPortReset(pid, portResetParm, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}

int iposDiagPortStop(ipos_port_id pid)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:PORT STOP.............");
  errCode = iposPortStop(pid, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}

int iposDiagUtopiaLbStart(ipos_port_id pid)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:UTOPIA LOOPBACK.......");
  errCode = iposLbStart(pid, cmdTag, (int)(HPI_LPBK_NTWK_UTOPIA), (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}

int iposDiagSendTestSignals(ipos_port_id pid, ipos_test_signals *pTestSignals)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:SEND SIGNALS..........");
  errCode = iposSendTestSignals(pid, pTestSignals, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}

int iposDiagDetectTestSignals(ipos_port_id pid, ipos_test_signals *pTestSignals, int *pData)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;

  bPrintOutput = diagIsPrintOutputOk();

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:DETECT SIGNALS........");
  errCode = iposDetectTestSignals(pid, pTestSignals, cmdTag, cntRpt, (void *)iposDiagDetectSignalsCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  pData = (int *)DmaArray; 
  return (errCode);
}




int iposDiagAfeLb(ipos_port_id pid)
{
  char line[10];

  #define  TOTAL_NUM_TONES 2048
  
  #define  AFE_LB_NUM_TONES 3
  #define  AFE_LB_TONE1 383
  #define  AFE_LB_TONE2 511
  #define  AFE_LB_TONE3 639
  
  #define  AFE_LB_TONE1_SNR 0x9672B
  #define  AFE_LB_TONE2_SNR 0x2692EC
  #define  AFE_LB_TONE3_SNR 0x3E4A7
  
  #define  AFE_LB_TONE1_MARGIN 0x100
  #define  AFE_LB_TONE2_MARGIN 0x100
  #define  AFE_LB_TONE3_MARGIN 0x100
  
  #define  AFE_LB_LAST_LOW_TONE 20   //Last tone with HIGH_NOISE threshold
  #define  AFE_LB_HIGH_NOISE_THRSHLD 0x2000 //Raw value, not dBm nor dB
  #define  AFE_LB_NOISE_THRSHLD      0x20  //Raw value, not dBm nor dB

  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;
  int tone;
  ipos_test_signals sTestSignals;
  int *pData;
  int afeNum = pid.portNum >> 1;

  bPrintOutput = diagIsPrintOutputOk();

  IPOS_DIAG_PRINT1(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:AFE%d LOOPBACK........", afeNum);
  IPOS_DIAG_PRINTNOB(pid.bmeNum, IPOSD_PRINT_INFO,"\n");

  memset ((char *)&sTestSignals, 0, sizeof(ipos_test_signals));
  sTestSignals.SigType = (U8)HPI_XMT_TONES;
  sTestSignals.NumTones = (U8)AFE_LB_NUM_TONES;
  sTestSignals.Tone1 = (U16)(AFE_LB_TONE1); 
  sTestSignals.Tone2 = (U16)(AFE_LB_TONE2); 
  sTestSignals.Tone3 = (U16)(AFE_LB_TONE3); 

  
  errCode = iposSendTestSignals(pid, &sTestSignals, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  if (errCode != IPOS_SUCCESS)
  {
    diagPutErrCode(pid, errCode);
    return (errCode);
  }

#ifdef AFE_PROMPTS
  IPOS_PRINTF("\nSendSignals success. Enter to continue('x'=>exit)\n");
  getstr(line);
  if (line[0] == 'x')
  {
    return (IPOS_SUCCESS);
  }
#endif

  delayMSecs(IPOSD_MSEC_BME_CONFIG_WAIT);

  // set the AFE loopback register
  BmeStruct[pid.bmeNum].BmeParms.DebugParms.Parm1 = (S32)('w' - '0');
  BmeStruct[pid.bmeNum].BmeParms.DebugParms.Parm2 = afeNum;
  BmeStruct[pid.bmeNum].BmeParms.DebugParms.Parm3 = 0x8a;//AFE Reg
  BmeStruct[pid.bmeNum].BmeParms.DebugParms.Parm4 = 0x11;//Value

  errCode = iposBmeMon(pid, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  if (errCode != IPOS_SUCCESS)
  {
    diagPutErrCode(pid, errCode);
    return (errCode);
  }

#ifdef AFE_PROMPTS 
  IPOS_PRINTF("The AFE should now be in loopback reg 0x8a should = 0x11('x'=>exit)\n");
  IPOS_PRINTF("Enter to continue\n");
  getstr(line);
  if (line[0] == 'x')
  {
    return (IPOS_SUCCESS);
  }
#endif

  memset ((char *)&sTestSignals, 0, sizeof(ipos_test_signals));
  sTestSignals.SigType = HPI_RX_POWER;
  errCode = iposDetectTestSignals(pid, &sTestSignals, cmdTag, cntRpt, (void *)iposDiagDetectSignalsCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);

  if (errCode == IPOS_SUCCESS)
  {
#ifdef AFE_PROMPTS
    IPOS_PRINTF("DetectSignals success. Enter to do comparison. ('x'=>exit)\n");
    getstr(line);
    if (line[0] == 'x')
    {
      return (IPOS_SUCCESS);
    }

#endif

    pData = (int *)DmaArray;

    pData++; //skip value at DC

    for (tone = 1; tone < (int)(TOTAL_NUM_TONES); tone++)
    {
      switch (tone)
      {
        case AFE_LB_TONE1:
          if (*pData < AFE_LB_TONE1_SNR + AFE_LB_TONE1_MARGIN && *pData > AFE_LB_TONE1_SNR - AFE_LB_TONE1_MARGIN)
          {
            IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_VERBOSE,
                             "passed: SNR Tone(%d) Expected(0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_TONE1_SNR), *pData);
          }
          else
          {
            errCode = IPOS_ERROR_AFE_TONE1;
            IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_INFO,
                             "FAILED: SNR Tone(%d) Expected(0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_TONE1_SNR), *pData);
          }
          break;
        case AFE_LB_TONE2:
          if (*pData < AFE_LB_TONE2_SNR + AFE_LB_TONE2_MARGIN && *pData > AFE_LB_TONE2_SNR - AFE_LB_TONE2_MARGIN)
          {
            IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_VERBOSE,
                             "passed: SNR Tone(%d) Expected(0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_TONE2_SNR), *pData);
          }
          else
          {
            errCode = IPOS_ERROR_AFE_TONE2;
            IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_INFO,
                             "FAILED: SNR Tone(%d) Expected(0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_TONE2_SNR), *pData);
          }
          break;
        case AFE_LB_TONE3:
          if (*pData < AFE_LB_TONE3_SNR + AFE_LB_TONE1_MARGIN && *pData > AFE_LB_TONE3_SNR - AFE_LB_TONE1_MARGIN)
          {
            IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_VERBOSE,
                             "passed: SNR Tone(%d) Expected(0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_TONE3_SNR), *pData);
          }
          else
          {
            errCode = IPOS_ERROR_AFE_TONE3;
            IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_INFO,
                             "FAILED: SNR Tone(%d) Expected(0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_TONE3_SNR), *pData);
          }
          break;
        default:
          if (tone < AFE_LB_LAST_LOW_TONE || tone == TOTAL_NUM_TONES)
          {
            if (*pData < AFE_LB_HIGH_NOISE_THRSHLD)
            {
              IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_VERBOSE,
                               "passed: SNR Tone(%d) Expected < (0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_HIGH_NOISE_THRSHLD), *pData);
            }
            else
            {
              errCode = IPOS_ERROR_AFE_LOW_TONE_NOISE;
              IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_INFO,
                               "FAILED: SNR Tone(%d) Expected < (0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_HIGH_NOISE_THRSHLD), *pData);
            }

          }
          else
          {
            if (*pData < AFE_LB_NOISE_THRSHLD)
            {
              IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_VERBOSE,
                               "passed: SNR Tone(%d) Expected < (0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_NOISE_THRSHLD), *pData);
            }
            else
            {
              errCode = IPOS_ERROR_AFE_NOISE;
              IPOS_DIAG_PRINT3(pid,IPOSD_PRINT_INFO,
                               "FAILED: SNR Tone(%d) Expected < (0x%x) Actual(0x%x)\n", tone,(int)(AFE_LB_NOISE_THRSHLD), *pData);
            }

          }
          break;

      }
      //if (errCode != IPOS_SUCCESS)
      //    break;

      pData++;
    }
  }


  diagPutErrCode(pid, errCode);
  return (errCode);
}
                             
/* The Garabite test assumes that the BME has been downloaded, the System Provisioned and the 
   port provsioned.
   
   pData: Output ptr to 2048 ints 
 
*/


int iposDiagGarabite(ipos_port_id pid,  int *pData/*2048 ints */)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;
  ipos_test_signals sTestSignals;

  bPrintOutput = diagIsPrintOutputOk();

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:GARABITE..............");

  memset ((char *)&sTestSignals, 0, sizeof(ipos_test_signals));

  sTestSignals.SigType = HPI_XMT_GARABIT;
  errCode = iposSendTestSignals(pid, &sTestSignals, cmdTag, cntRpt, (void *)iposDiagCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT); 
  if (errCode != IPOS_SUCCESS)
  {
    diagPutErrCode(pid, errCode);
    return (errCode);
  }


  /*Must wait 1044 symbols for the BME configuration to be complete */
  /* This is 1044*250usec = 261msecs */
  delayMSecs(IPOSD_MSEC_BME_CONFIG_WAIT);

  sTestSignals.SigType = HPI_RX_POWER;
  errCode = iposDetectTestSignals(pid, &sTestSignals, cmdTag, cntRpt, (void *)iposDiagDetectSignalsCb);
  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);

  diagPutErrCode(pid, errCode);

  pData = (int *)DmaArray; //A 2048 array

  return (errCode);

}


int iposDiagDeviceVersion(int BmeNum)
{
  U8  cmdTag = 71;
  U32 cntRpt = 0; 
  int errCode = IPOS_SUCCESS;
  ipos_port_id pid;        

  pid.bmeNum = BmeNum;
  pid.portNum = 1;

  IPOS_DIAG_PRINT(pid, IPOSD_PRINT_TRACE,"IPOS_DIAG:DEVICE VERSIONS.......");
  BmeStruct[BmeNum].Port[0].PortParms.DeviceVerParms.VersionStr[0] = 'Z';
  BmeStruct[BmeNum].Port[0].PortParms.DeviceVerParms.VersionStr[0] = 'Q';
  errCode = iposDeviceVersion(BmeNum, cmdTag, cntRpt, (void *)iposDiagBmeVersionCb);

  errCode = diagRcvPoll(pid, errCode, IPOSD_MSEC_RX_WAIT);
  diagPutErrCode(pid, errCode);
  return (errCode);
}



/*******************************************************************************
/*                  SYSTEM TEST Callbacks
/*          
/*  Diagnotosic Callback Functions and the Erorr Code test result function
/*          
/*******************************************************************************/
void diagPutErrCode(ipos_port_id pid, int errCode)
{
  if (errCode == IPOS_SUCCESS)
  {
    IPOS_DIAG_PRINTB_SUCCESS(pid.bmeNum);
  }
  else
  {
    IPOS_DIAG_PRINTB_FAIL(pid.bmeNum, errCode);
  }
}



/*******************************************************************************/
int iposDiagCb(ipos_port_id portId, U8 UID, U32 uPar,  int status, void *par)
{
  diagErrCode = status;
  bTestInProgress = FALSE;
  return (status);
}

/*******************************************************************************/
int iposDiagPortStartCb(ipos_port_id portId, U8 UID, U32 uPar,  int status, void *par)
{
  if (par != NULL)
  {
    status = *(int*)par;
  }
  diagErrCode = status;
  bTestInProgress = FALSE;
  return (status);
}

/*******************************************************************************/
int iposDiagPortStatusCb(ipos_port_id portId, U8 UID, U32 uPar,  int status, void *par)
{
  int bandRate = 64;

  if (status == IPOS_SUCCESS)
  {
    iposDiagLogPortStatus(portId, (ipos_port_status *)par, bandRate);
  }

  diagErrCode = status;
  bTestInProgress = FALSE;
  return (diagErrCode);
}

/*******************************************************************************/
int iposDiagLogPortStatus(ipos_port_id pid, ipos_port_status *pPortStatus, int bandRate)
{

  short txPwr = pPortStatus->TransmitPower;
  short sign;
  int i;

  IPOS_PRINTF ("\nExtended Port Status\n");
  IPOS_PRINTF ("=================\n");
  IPOS_PRINTF ("Bme: %d Port: %d\n",pid.bmeNum,pid.portNum);


  IPOS_PRINTF ("Downstream line rate: %ld kbps\n", pPortStatus->DsLineRate*bandRate);

  IPOS_PRINTF ("Upstream line rate: %ld kbps\n",pPortStatus->UsLineRate*bandRate);

  IPOS_PRINTF ("Fast Downstream payload rate: %ld kbps\n",pPortStatus->FastDsPayloadRate*bandRate);

  IPOS_PRINTF ("Slow Downstream payload rate: %ld kbps\n",pPortStatus->SlowDsPayloadRate*bandRate);

  IPOS_PRINTF ("Fast Upstream payload rate: %ld kbps\n", pPortStatus->FastUsPayloadRate*bandRate);

  IPOS_PRINTF ("Slow Upstream payload rate: %ld kbps\n",pPortStatus->SlowUsPayloadRate*bandRate);

	IPOS_PRINTF ("\nDownstream attainable payload rate: %d kbps",
               pPortStatus->DsAttainableRate*bandRate);

	IPOS_PRINTF ("\nDownstream attainable line rate: %d kbps",
                pPortStatus->DsAttainableLineRate*bandRate);

#ifdef VTU_O
	IPOS_PRINTF ("\nUpstream attainable payload rate: %d kbps",
               pPortStatus->UsAttainableRate*bandRate);

	IPOS_PRINTF ("\nUpstream attainable line rate: %d kbps",
               pPortStatus->UsAttainableLineRate*bandRate);
#endif

	IPOS_PRINTF ("\nDownstream Training Margin: %d.%d dB", pPortStatus->DsTrainingMargin / 10,
          pPortStatus->DsTrainingMargin % 10);

#ifdef VTU_O
	IPOS_PRINTF ("\nUpstream Training Margin: %d.%d dB", pPortStatus->UsTrainingMargin / 10,
          pPortStatus->UsTrainingMargin % 10);
#endif

	IPOS_PRINTF ("\nDownstream Line Protection (Slow Path): %d.%d DMT Symbols",
          pPortStatus->SlowDsLineProtection/ 10, pPortStatus->SlowDsLineProtection % 10);

	IPOS_PRINTF ("\nUpstream Line Protection (Slow Path): %d.%d DMT Symbols",
          pPortStatus->SlowUsLineProtection/ 10, pPortStatus->SlowUsLineProtection % 10);

  IPOS_PRINTF ("\nNear-end ITU Vendor Id: 0x");
  for (i = 0; i < 8; i++)
    IPOS_PRINTF ("%02x", pPortStatus->NeItuVendorId[i]);

  IPOS_PRINTF ("\nFar-end ITU Vendor Id: 0x");
  for (i = 0; i < 8; i++)
    IPOS_PRINTF ("%02x", pPortStatus->FeItuVendorId[i]);

  IPOS_PRINTF ("Downstream delay: %d.%d ms\n", pPortStatus->DsDelay/10, pPortStatus->DsDelay%10);
  IPOS_PRINTF ("Upstream delay: %d.%d ms\n", pPortStatus->UsDelay/10, pPortStatus->UsDelay%10);

  if (txPwr>=0)
    sign = 1;
  else
  {
    sign = -1;
  }
  txPwr = sign*txPwr;

  IPOS_PRINTF("\nTx total power %d.%d dbm\n", sign*(txPwr / 10), txPwr % 10);

  return (IPOS_SUCCESS);                

}


/*******************************************************************************/
int iposDiagDetectSignalsCb(ipos_port_id portId, U8 UID, U32 uPar,  int status, void *par)
{
#define IPOSD_DMA_BUF_SIZE 0x2000
#define IPOSD_SNR_SIZE 4 /* 4 bytes per SNR reading */
#define IPOSD_SNR_OUTPUT_COLS 1 /* 1 column in output */

  U32 addr = 0;

  if (status == IPOS_SUCCESS)
  {
    if (par)
    {
      addr = *(U32 *)par;
    }
    else
      status = IPOS_ERROR_NO_MSGBUF;

    if (addr)
    {
      //Use BME Debug Utility to DMA from BME to Host Memory
      //The utility uses an extern array called DmaArray.
      int nBytes = (int)(IPOSD_DMA_BUF_SIZE);
      rdm(portId.bmeNum, addr,nBytes);
      if (bPrintOutput == TRUE)
      {
        bmeMonDumpBuffHex (DmaArray, nBytes,(int)(IPOSD_SNR_SIZE), (int)IPOSD_SNR_OUTPUT_COLS);
        IPOS_PRINTF("\n");
      }
    }
    else
      status = IPOS_ERROR_MSG_SOURCE;
  }

  diagErrCode = status;
  bTestInProgress = FALSE;
  return (status);
}


/*******************************************************************************/
int iposDiagBmeVersionCb(ipos_port_id portId, U8 UID, U32 uPar,  int status, void *par)
{
  tBmeStruct *pBme = &BmeStruct[portId.bmeNum];

  if (status == IPOS_SUCCESS)
  {
    iposDiagLogDeviceVer(pBme->BmeNum, pBme->Port[0].PortParms.DeviceVerParms.VersionLen,
                         pBme->Port[0].PortParms.DeviceVerParms.VersionStr); 
  }

  diagErrCode = status;
  bTestInProgress = FALSE;
  return (status);
}

/*******************************************************************************/
int    iposDiagLogDeviceVer(int bmeNum, int  len, char *string)
{

  int     i;
  IPOS_PRINTF ("\nBME Firmware Versions");
  IPOS_PRINTF ("\n=====================\n");
  for (i=0;i<len;i++)
  {
    IPOS_PRINTF("%c", string[i]);
    if (string[i] == '\n')
    {
      IPOS_PRINTF("");
    }

  }
  IPOS_PRINTF("\n");
  return (IPOS_SUCCESS);                
}


static bool diagIsPrintOutputOk()
{
  char line[5];

  IPOS_PRINTF("\nDo you want the results printed to the screen? (Y/N)>");
  getstr(line);
  switch (line[0])
  {
    case 'Y':
    case 'y':
      return (TRUE);
    default:
      IPOS_PRINTF("Invalid Selection. Output will NOT be printed\n");
      //Fallthru
    case 'N':
    case 'n':
      return (FALSE);
  }
}




