/**************************************************************
$Workfile:   rmmapp.c  $
***************************************************************
**
** Host Application, 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 "apitype.h"
#include "apistruct.h"
#include "apposmacro.h"
#include "eocapi.h"
#include "host_ver.h"
#include "oampdef.h"
#include "perfconfig.h"
#include "bmetl.h"
#include "rmmapp.h"
#include "dapi_parms.h"

extern	char	bootloadInfo(void);
extern	void	reboot(int);
extern  int	getPortNum (ipos_port_id *pid);
extern          eoamp_port_state oampGetPortState(ipos_port_id pid);

/*  OO Design Pattern is Singleton.  Exactly one instance of the object (deviceVersions) per BME */

/*  Object has 2 public methods, storeDeviceVersion and getDeviceVersion */

#define  HOST_VER_INDEX		0
#define  BME_FW_VER_INDEX	1
#define  BME_HW_VER_INDEX	2
#define  AFE_HW_VER_INDEX	3
#define  IFE_HW_VER_INDEX	4
#define  NUMBER_DEVICE_VERSIONS	(IFE_HW_VER_INDEX + 1)
extern tBmeStruct BmeStruct[];

static struct {
	char	version[ 300 ];
	U16	offsets[ NUMBER_DEVICE_VERSIONS ];
} deviceVersions[ MAX_NUM_OF_BMES ];
int autoEnetRptEnable = 0;
static struct {
	U8 autoNego;
	U8 enetLink;
	U8 enetSpeed;
	U8 enetAGC;
	U8 enetFlowCtrl;
	U8 enetLpBack;

} enetPhyParams;
#ifdef VTU_O
static int remEnetAutoRptFlag;
static U8 remEnetStatRptFlag[MAX_PORTS_PER_BME+1];
#endif
void
storeDeviceVersions( ipos_port_id portId, U8 UID, U32 uPar, int status, ipos_bme_ver *par )
{
	char	*baseAddr = &(deviceVersions[ portId.bmeNum - 1 ].version[ 0 ]);
	char	*curAddr = baseAddr;
	char	*deviceAddr = par->VersionStr;
	char	*searchAddr = deviceAddr;
	U16	 ifeLen = 0;			/* computed directly */
	int	 bmeIndex = portId.bmeNum - 1;	/* Use C-stype index !! */

	if (portId.bmeNum > MAX_NUM_OF_BMES)
	{
		printf( "\nstore device versions called for BME %d, expected no more than %d\n",
		           portId.bmeNum, MAX_NUM_OF_BMES );
		return;
	}
/*
 * baseAddr is the base of the version attribute for the object
 * curAddr is the current address where the next version string will be copied
 * deviceAddr is the current address in the version string from iPOS / BME
 * searchAddr is where we are searching for the end of the embedded version
 *      (BEME/AFE/IFE) from iPOS / BME
 */

	memset( curAddr, 0, sizeof( deviceVersions[ bmeIndex ].version ) );
	strcpy( curAddr, VERSION_STR );
	deviceVersions[ bmeIndex ].offsets[ HOST_VER_INDEX ] = 0;
	deviceVersions[ bmeIndex ].offsets[ BME_FW_VER_INDEX ] = strlen( curAddr ) + 1;
	curAddr += deviceVersions[ bmeIndex ].offsets[ BME_FW_VER_INDEX ];

/* sanity check ... should never happen
   sizeof( deviceVersions[ bmeIndex ].version ) is 50 bytes larger than par->VersionStr */

	if (par->VersionLen + deviceVersions[ bmeIndex ].offsets[ BME_FW_VER_INDEX ] >=
			sizeof( deviceVersions[ bmeIndex ].version ))
	{
		printf( "\nwarning: possible overflow in store device versions, sizes: %d %d %d\n",
			   par->VersionLen,
			   deviceVersions[ bmeIndex ].offsets[ BME_FW_VER_INDEX ],
			   sizeof( deviceVersions[ bmeIndex ].version )
		);
	}

	for (
		 searchAddr = deviceAddr;
		*searchAddr != '\n' && (searchAddr - deviceAddr) < par->VersionLen;
		 searchAddr++
	) {}

	if (*searchAddr != '\n')
	{
		printf( "\ncould not parse BME firmware version from string\n%s\n", par->VersionStr );
		return;
	}
	else if ( ((curAddr + (searchAddr - deviceAddr)) - baseAddr) >=
				sizeof( deviceVersions[ bmeIndex ].version ) )
	{
		printf( "\nOverflow with BME firmware version in store device versions\n" );
		return;
	}

	deviceVersions[ bmeIndex ].offsets[ BME_HW_VER_INDEX ] =
		 deviceVersions[ bmeIndex ].offsets[ BME_FW_VER_INDEX ] + (searchAddr - deviceAddr) + 1;
	strncpy( curAddr, deviceAddr, (searchAddr - deviceAddr) );
	curAddr[ (searchAddr - deviceAddr) ] = '\0';
	curAddr += ((searchAddr - deviceAddr) + 1);
	deviceAddr = searchAddr + 1;

	for (
		searchAddr = deviceAddr;
		strncmp( searchAddr, " AFE", strlen( " AFE" )) != 0 && 
			(searchAddr - (char *) &(par->VersionStr[ 0 ])) < par->VersionLen;
		searchAddr++
	) {}

	if (strncmp( searchAddr, " AFE", strlen( " AFE" )) != 0)
	{
		printf( "\ncould not parse BME hardware version from string\n%s\n", par->VersionStr );
		return;
	}
	else if ( ((curAddr + (searchAddr - deviceAddr)) - baseAddr) >=
				sizeof( deviceVersions[ bmeIndex ].version ) )
	{
		printf( "\nOverflow with BME firmware version in store device versions\n" );
		return;
	}

	deviceVersions[ bmeIndex ].offsets[ AFE_HW_VER_INDEX ] =
		 deviceVersions[ bmeIndex ].offsets[ BME_HW_VER_INDEX ] + (searchAddr - deviceAddr) + 1;
	strncpy( curAddr, deviceAddr, (searchAddr - deviceAddr) );
	curAddr[ (searchAddr - deviceAddr) ] = '\0';
	curAddr += ((searchAddr - deviceAddr) + 1);
	deviceAddr = searchAddr + 1;

	for (
		 searchAddr = deviceAddr;
		*searchAddr != '\n' && (searchAddr - deviceAddr) < par->VersionLen;
		 searchAddr++
	) {}

	if (*searchAddr != '\n')
	{
		printf( "\ncould not parse AFE hardware version from string\n%s\n", par->VersionStr );
		return;
	}
	else if ( ((curAddr + (searchAddr - deviceAddr)) - baseAddr) >=
				sizeof( deviceVersions[ bmeIndex ].version ) )
	{
		printf( "\nOverflow with BME firmware version in store device versions\n" );
		return;
	}

	deviceVersions[ bmeIndex ].offsets[ IFE_HW_VER_INDEX ] =
		 deviceVersions[ bmeIndex ].offsets[ AFE_HW_VER_INDEX ] + (searchAddr - deviceAddr) + 1;
	strncpy( curAddr, deviceAddr, (searchAddr - deviceAddr) );
	curAddr[ (searchAddr - deviceAddr) ] = '\0';
	curAddr += ((searchAddr - deviceAddr) + 1);
	deviceAddr = searchAddr + 1;

	ifeLen = par->VersionLen - (deviceAddr - (char *) &(par->VersionStr[ 0 ]));
	strncpy( curAddr, deviceAddr, ifeLen );
	curAddr[ ifeLen ] = '\0';
}

const char *
getDeviceVersion( int bmeNum, eDeviceChoice eDesired )
{
	S16	index = -1;
	U16	offset;

	switch (eDesired)
	{
	  case eHOST_VERISON:
		index = HOST_VER_INDEX;
		break;

          case eBME_FW_VERSION:
		index = BME_FW_VER_INDEX;
		break;

          case eBME_HW_VERSION:
		index = BME_HW_VER_INDEX;
		break;

          case eAFE_VERSION:
		index = AFE_HW_VER_INDEX;
		break;

          case eIFE_VERSION:
		index = IFE_HW_VER_INDEX;
		break;

          case eNO_DEVICE:
		index = -1;
		break;

	  default:
		printf( "\nUnrecogined device choice in get device version %d\n", eDesired );
		index = -1;
		break;
	}

	if (index < 0)
	  return( NULL );
	else
	{
		offset = deviceVersions[ bmeNum - 1 ].offsets[ index ];
		return( &(deviceVersions[ bmeNum - 1 ].version[ offset ]) );
	}
}

/* all entry points that start with "ui" are part of the user interface
   These are not fundamental to the implementation of the protocol.	*/

/* this user interface is for debug */

void
uiShowDeviceVersions( int bmeNum )
{
#ifdef DEBUG_DEVICE_VERSIONS
	int	bmeIndex = bmeNum - 1;
	int	iter;

	if (bmeIndex >= MAX_NUM_OF_BMES)
	{
		printf( "\nshow device versions, invalid BME number %d\n", bmeNum );
		return;
	}
	else
	{
		printf( "\n" );
		for (iter = 0; iter < NUMBER_DEVICE_VERSIONS; iter++)
		{
			U16	 offset = deviceVersions[ bmeIndex ].offsets[ iter ];
			char	*pVersion = &(deviceVersions[ bmeIndex ].version[ offset ]);

			printf( "%d: offset %u, length of version: %d, version string: %s\n",
				 iter, offset, strlen( pVersion ), pVersion
			);
		}
	}
#else
	printf( "\nshow device versions not available, use commands 20 and 90\n" );
#endif
}

#if (defined VTU_O || defined INI_SUPPORT)
static struct {
	char	*label;
	U8	 ieSubtype;
	U8	 ieValue;
} uiEtherStatusValue[] = {
	{ "Link is down", LINK_STATUS, LINK_IS_DOWN },
	{ "Link is up", LINK_STATUS, LINK_IS_UP },
	{ "Half duplex", DUPLEX_STATUS, HALF_DUPLEX },
	{ "Full duplex", DUPLEX_STATUS, FULL_DUPLEX },
	{ "10 Base-T", TRANSMISSION_SPEED, TEN_BASE_T },
	{ "100 Base-T", TRANSMISSION_SPEED, HUNDRED_BASE_T },
	{ "flow control disabled", PAUSE_FRAME_STATUS, FLOW_CONTROL_DISABLED },
	{ "flow control enabled", PAUSE_FRAME_STATUS, FLOW_CONTROL_ENABLED },
	{ "Unknown status", IE_NO_INFO, UNKNOWN_STATUS }
};

static const char *
uiShowEthernetSybtypeStatus( int ieSubtype, int value )
{
	int			 iter;
	static const char	*defaultValue = "Undefined";

	for (iter = 0; iter < sizeof( uiEtherStatusValue ) / sizeof( uiEtherStatusValue[ 0 ] ); iter++)
	  if (uiEtherStatusValue[ iter ].ieValue == value &&
	      uiEtherStatusValue[ iter ].ieSubtype == ieSubtype)
	    return( uiEtherStatusValue[ iter ].label );
	  else if (uiEtherStatusValue[ iter ].ieSubtype == IE_NO_INFO &&
	      uiEtherStatusValue[ iter ].ieValue == value)
	    return( uiEtherStatusValue[ iter ].label );

	return( defaultValue );
}
#endif

void
uiShowEthernetStatus( ipos_port_id pid )
{
#ifdef INI_SUPPORT
	int	 errCode, lineNum, ptmfIndex;

	getLineNum( pid, &lineNum );
	if (lineNum < 1 || lineNum > MAX_NUM_OF_PORTS)
	{
		printf( "\nInvalid port b%dp%d\n", pid.bmeNum, pid.portNum );
	}
	else
	{
		errCode = getIniPhy( lineNum, &ptmfIndex );
		if (errCode != IPOS_SUCCESS)
		{
			printf( "\nProblem getting the PTMF index for port b%dp%d\n",
				   pid.bmeNum, pid.portNum
			);
		}
		else
		{
			U32	value32;
			int	ptmfStatus;

			printf( "\nshow ethernet status, port b%dp%d, line number: %d, PTMF index: %d\n",
				   pid.bmeNum, pid.portNum, lineNum, ptmfIndex );
			ptmfStatus = iposPtmfGetConfigParam( ptmfIndex, ENET_LINK_EN, &value32 );
			printf( "link status: %ld, returned %d\n", value32, ptmfStatus );
			printf( "\t%s\n", uiShowEthernetSybtypeStatus( LINK_STATUS, value32 ) );

			ptmfStatus = iposPtmfGetConfigParam( ptmfIndex, ENET_LINK_DUPLEX, &value32 );
			printf( "duplex status: %ld, returned: %d\n", value32,  ptmfStatus );
			printf( "\t%s\n", uiShowEthernetSybtypeStatus( DUPLEX_STATUS, value32 ) );

			ptmfStatus = iposPtmfGetConfigParam( ptmfIndex, ENET_LINK_SPEED, &value32 );
			printf( "transmission speed: %ld, returned: %d\n", value32,  ptmfStatus );
			printf( "\t%s\n", uiShowEthernetSybtypeStatus( TRANSMISSION_SPEED, value32 ) );

			ptmfStatus = iposPtmfGetConfigParam( ptmfIndex, ENET_LINK_FLOW_CONTROL, &value32 );
			printf( "link flow control: %ld, returned: %d\n", value32, ptmfStatus );
			printf( "\t%s\n", uiShowEthernetSybtypeStatus( PAUSE_FRAME_STATUS, value32 ) );

			ptmfStatus = iposPtmfGetCounter( ptmfIndex,  RX_ENET_PAUSE_FRAMES, &value32 );
			printf( "pause frame(s) sent: %ld, returned %d\n", value32, ptmfStatus );
		}
	}
#else
	printf( "\nEthernet is not supported on this system\n" );
#endif
}

/****************************************************************************/

#define MAX_RMM_SET_RESPONSE	16		/* 5 byte std header + 4 bytes IE elements */

#ifdef VTU_O
static struct {
	char	*label;
	U8	 ieType;
	U8	 ieSubtype;
} uiRMMIeTypeLabels[] = {
	{ "Host Application Version", FIRMWARE_VERSION_INFO, HOST_VERSION_INFO },
	{ "BME Firmware Version", FIRMWARE_VERSION_INFO, BME_VERSION_INFO },
	{ "BME Hardware Version", FIRMWARE_VERSION_INFO, BME_HW_VERSION_INFO },
	{ "AFE Hardware Version", FIRMWARE_VERSION_INFO, AFE_VERSION_INFO },
	{ "IFE Hardware Version", FIRMWARE_VERSION_INFO, IFE_VERSION_INFO },
	{ "Ethernet Link Status", ETHERNET_STATUS_INFO, LINK_STATUS },
	{ "Ethernet Duplex", ETHERNET_STATUS_INFO, DUPLEX_STATUS },
	{ "Ethernet Transmission Speed", ETHERNET_STATUS_INFO, TRANSMISSION_SPEED },
	{ "Ethernet Pause Pulse Status", ETHERNET_STATUS_INFO, PAUSE_FRAME_STATUS },
	{ "Ethernet Count of Pause Pulse Frames", ETHERNET_STATUS_INFO, COUNT_PAUSE_FRAMES },
	{ "Seconds with CRC errors", ERRORED_SECONDS_INFO, SECONDS_WITH_CRC },
	{ "Seconds with LOS", ERRORED_SECONDS_INFO, SECONDS_WITH_LOS },
	{ "Seconds with SEF", ERRORED_SECONDS_INFO, SECONDS_WITH_SEF },
	{ "Seconds with LOF", ERRORED_SECONDS_INFO, SECONDS_WITH_LOF },
	{ "MDIO Regs Value", MDIO_REGISTER_VALUES, NOT_A_REGISTER },
    { "Total Number of Pins ", GPIO_PIN_LIST, GPIO_PIN_NO },
    { "Mask Value", GPIO_PIN_LIST, GPIO_PIN_MASK },
	{ "Pins Value", GPIO_PIN_LIST, GPIO_PIN_VALUE },
	{ "BME ID No", MODEM_ID_INFO, BME_ID_INFO},
	{ "IFE ID No", MODEM_ID_INFO, IFE_ID_INFO},
    { "AFE ID No", MODEM_ID_INFO, AFE_ID_INFO},
	{ "Manufaturing ID", MODEM_ID_INFO, MANUFATURING_ID_INFO },
	{ "Model Number", MODEM_ID_INFO, MODEL_NUMBER_INFO },
	{ "Serial Number", MODEM_ID_INFO, SERIAL_NUMBER_INFO },
	{ "Boot Loader Version", MODEM_ID_INFO, BOOTLOADER_VERSION_INFO },
    { "Auto-negotiate/Fixed Mode", GET_ENET_CFG, AUTO_NEGOTIATION},
	{ "Fixed Mode Link Speed    ", GET_ENET_CFG, ETHERNET_SPEED},
    { "Fixed Mode Link Duplex   ", GET_ENET_CFG, ETHERNET_LINK},
	{ "Ethernet AGC Enable      ", GET_ENET_CFG, ETHERNET_AGC},
	{ "Flow Control Enable      ", GET_ENET_CFG, ETHERNET_FLOW_CTRL},
    { "Ethernet Loopback Type   ", GET_ENET_CFG, ETHERNET_LPBACK},
	{ "Remote Tx Power", REMOTE_EXT_STATUS, TX_POWER},
	{ "Not defined", IE_NO_INFO, IE_NO_INFO }
};

static const char *
uiRMMGetLabel( U8 ieType, U8 ieSubtype )
{
	static const char	*defaultValue = "Undefined";
	int			 iter;

	for (iter = 0; iter < sizeof( uiRMMIeTypeLabels ) / sizeof( uiRMMIeTypeLabels[ 0 ] ); iter++)
	  if (uiRMMIeTypeLabels[ iter ].ieType == ieType &&
	      uiRMMIeTypeLabels[ iter ].ieSubtype == ieSubtype)
	    return( uiRMMIeTypeLabels[ iter ].label );
	  else if (uiRMMIeTypeLabels[ iter ].ieType == IE_NO_INFO)
	    return( uiRMMIeTypeLabels[ iter ].label );

	return( defaultValue );
}

/* Only the CO calls RMMMsg2Struct ... */

static int
RMMMsg2Struct( U8 *pMsgBuf, void *pStructBuf, U8 *pMsgType )
{
	U8		 ack = pMsgBuf[ IPOS_MSGHDR_ACK ];
	int		 size;
	int		 ieType = 0;
	int		 ieLen = 0;
	int		 retval = IPOS_SUCCESS;
	void		*elementAddr = NULL;
	ieDecoder	 ourDecoder = NULL;

	*pMsgType = *(pMsgBuf+1);		/* 2nd byte in standard message is message type */

	if (*pMsgType == IPOSRMM_SET)
	{
		if (ack == IPOS_ACK_CMD)
		{
			rmm_reboot_firmware	*pRebootStruct = (rmm_reboot_firmware *) pStructBuf;

			elementAddr = (void *) &(pRebootStruct->firmwareChoice);
		}
		else
		{
			rmm_reboot_status	*pCpeResp = (rmm_reboot_status *) pStructBuf;

			elementAddr = (void *) &(pCpeResp->status);
		}

		size = iposEocDecodeCtrlHdr( pMsgBuf, (ipos_ctrl_hdr *) pStructBuf );
	        pMsgBuf += size ;
		ieType = *pMsgBuf++;
		ieLen = *pMsgBuf++;

		ourDecoder = appEocGetDecoder( EOC_RMM_PROTOCOL, ieType, IE_NO_INFO );
		if (ourDecoder == NULL)
		{
		    printf( "No decoder in RMMMsg2Struct, message: %d, ieType: %d\n", *pMsgType, ieType );
			return( IPOS_ERROR );
		}

		size = ourDecoder( pMsgBuf, elementAddr, ieLen );
	}

	return( retval );
}

static void
uiReportRebootStatus( ipos_port_id pid, U8 uid, int status, void *pData, int dataLen )
{
	U8			*pEocMsg = (U8 *) pData;
	U8	 		 msgType;
	rmm_reboot_status	 cpeResp;

	if (status != IPOS_SUCCESS)
	{
		if (status == IPOSEOC_ERROR_TIMEOUT)
		  printf( "\nReboot of remote modem timed out on port b%dp%d\n",
			   pid.bmeNum, pid.portNum
		  );
		else
		  printf( "\nReboot of remote modem failed for port b%dp%d, status is %d\n",
			   pid.bmeNum, pid.portNum, status
		  );
	}
	else
	{
		memset( &cpeResp, 0, sizeof( cpeResp ) );
		RMMMsg2Struct( (U8 *) pEocMsg, (void *) &cpeResp, &msgType );
		if (cpeResp.status == REBOOT_OK)
		  printf( "\nModem at other end of port b%dp%d should reboot shortly\n",
			 pid.bmeNum, pid.portNum
		  );
		else if (cpeResp.status == INCOMPATIBLE_BOOTLOADER)
		  printf( "\nModem at other end of port b%dp%d cannot reboot: incompatible boot loader\n",
			pid.bmeNum, pid.portNum
		  );
		else
		  printf( "\nFor port b%dp%d, received unrecognized reboot status of %d\n",
			 pid.bmeNum, pid.portNum, cpeResp.status
		  );
	}

	printf(PROMPT);
}

static void
uiReportSevereError(ipos_port_id pid, U8 errorValue )
{
	printf( "\nRemote mode accessed through b%dp%d reports error\n", pid.bmeNum, pid.portNum );
	if (errorValue == PROBLEM_PARSING)
	  printf( "Problem parsing message\n" );
	else if (errorValue == INPUT_OVERFLOW)
	  printf( "Ran off the end of the input message\n" );
	else if (errorValue == OUTPUT_OVERFLOW)
	  printf( "Requested data does not fit in a single message\n" );
	else if (errorValue == FEATURE_NOT_SUPPORTED)
	  printf( "Requested feature not supported\n" );
	else
	  printf( "Unrecognized error value %d\n", errorValue );
}

static int
uiReportIetypeWithSubtypes( int ieType, U8 *pEocMsg, int ieLen )
{
	U8		*pEocBase = pEocMsg;
	int		 ieSubType, ieSubLen, size = 0;
	int i;
	int nwInfo;
	unsigned char and_mask;
	char  bin_str[9];
	char		 infoElement[ MAX_MSG_SIZE ];
	const char	*pIeLabel = NULL;
	short txPwr, sign;
	ieDecoder	 ourDecoder = NULL;
    if (ieType ==MDIO_REGISTER_VALUES)
    {
		while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != NOT_A_REGISTER))
		{

		ieSubType = *pEocMsg++;
		ieSubLen = *pEocMsg++;
		ourDecoder = appEocGetDecoder( EOC_RMM_PROTOCOL, ieType, NOT_A_REGISTER );
		if (ourDecoder == NULL)
		{
			printf(
		   "\nNo decoder for RMM protocol, IE type: %d, subtype %d, skipping\n",
		      ieType, ieSubType
			);
		}
		else
		{
		 pIeLabel = uiRMMGetLabel( ieType, NOT_A_REGISTER);
		 ourDecoder( pEocMsg, (void *) &infoElement[ 0 ], ieSubLen );
		 if (ieSubType == 0)
			 printf("\n");
		 if (ieSubType <= 9)
			 printf ("%s for REG  %d: %04x \n", pIeLabel, ieSubType, *((U16 *) (&infoElement[0])));
		 else
			 printf ("%s for REG %d: %04x \n", pIeLabel, ieSubType, *((U16 *) (&infoElement[0])));
		}
		pEocMsg += ieSubLen;
		size += (ieSubLen + 2);
	}
}
  else if (ieType == MDIO_FPGA_REGISTER_VALUES)
  {
    U16 mdioReg_no = 0;   
    U16 mdioReg_value = 0;
    
    mdioReg_no |= (*(pEocMsg++) << 8);
    mdioReg_no |= *(pEocMsg++);
    
    /*check the Status byte */
    pEocMsg += 2;
    if(*(pEocMsg) == IPOS_SUCCESS)
    {
      pEocMsg -= 2; 
    
      mdioReg_value |= (*(pEocMsg++) << 8);
      mdioReg_value |= *(pEocMsg++);

      printf("FPGA Reg Value for Reg 0x%x: 0x%04x  \n ",
              mdioReg_no,mdioReg_value);
    }
    else
      printf("Error in Getting Value for FPGA Reg 0x%x \n ",mdioReg_no);
  }
	else if (ieType ==GPIO_PIN_LIST)
  {
		while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != NOT_A_REGISTER) )
	{
		ieSubType = *pEocMsg++;
		ieSubLen = *pEocMsg++;

		ourDecoder = appEocGetDecoder( EOC_RMM_PROTOCOL, ieType, ieSubType );
		if (ourDecoder == NULL)
		{
			printf(
		   "\nNo decoder for RMM protocol, IE type: %d, subtype %d, skipping\n",
		      ieType, ieSubType
			);
		}
		else
		{
			pIeLabel = uiRMMGetLabel( ieType, ieSubType );
			ourDecoder( pEocMsg, (void *) &infoElement[ 0 ], ieSubLen );
			if (ieSubType == GPIO_PIN_NO)
				printf( "\n%s: %d\n", pIeLabel, *((U8 *) (&infoElement[ 0 ])) );
			else{
				/* Set bit8 to 1 and all other bits to 0 10000000 */
                and_mask = 0x80;

				for (i=0; i<8; i++) {
					bin_str[i] = ((infoElement[0] & and_mask) ? '1' : '0');
					and_mask >>= 1;
				}

				bin_str[8] = '\0';
                printf( "%s [P7P6..P0]: %s\n", pIeLabel, bin_str);
			
			}
		}
		pEocMsg += ieSubLen;
		size += (ieSubLen + 2);
	}
	}
	else if (ieType ==GET_AUTOENET_RPT_FLAG)
	{
		remEnetAutoRptFlag = *pEocMsg++;
	    printf ("\nRemote Ethernet Status Autonomous Report Flag = %d",remEnetAutoRptFlag);
	}
  else if (ieType == ENET_ADDRESS_FILTERING)
  {
    while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO))
    {
      ieSubType = *pEocMsg++;
      ieSubLen = *pEocMsg++;

      pIeLabel = uiRMMGetLabel( ieType, ieSubType);

      if (ieSubType == LEARNED_ADDRESS)
      {
        size += (ieSubLen + 2);
        i = 1;

        while(ieSubLen)
        {
          printf ("\n    Address [%02i] = %02x.%02x.%02x.%02x.%02x.%02x",
                i,
                *pEocMsg++,
                *pEocMsg++,
                *pEocMsg++,
                *pEocMsg++,
                *pEocMsg++,
                *pEocMsg++ );
          
          ieSubLen -= 6;
          i++;
        }
      }
      else
        printf ("\n Unsupported Sub-Type %d", ieSubType);
      
    }
  }
  else
  {
    while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO) )
    {
		ieSubType = *pEocMsg++;
		ieSubLen = *pEocMsg++;

		ourDecoder = appEocGetDecoder( EOC_RMM_PROTOCOL, ieType, ieSubType );
		if (ourDecoder == NULL)
		{
			printf(
		   "\nNo decoder for RMM protocol, IE type: %d, subtype %d, skipping\n",
		      ieType, ieSubType
			);
		}
		else
		{
			pIeLabel = uiRMMGetLabel( ieType, ieSubType );
			ourDecoder( pEocMsg, (void *) &infoElement[ 0 ], ieSubLen );
		  /*
		   * All firmware versions are strings
		   * All errored seconds are U32's
		   *
		   */
			if (ieType == FIRMWARE_VERSION_INFO)
			  printf( "%s: %s\n", pIeLabel, &infoElement[ 0 ] );
			else if (ieType == ERRORED_SECONDS_INFO)
			  printf( "%s: %lu\n", pIeLabel, *((U32 *) (&infoElement[ 0 ])) );
			else if (ieType == ETHERNET_STATUS_INFO)
			{
				if (ieSubType == COUNT_PAUSE_FRAMES)
				  printf( "%s: %lu\n", pIeLabel, *((U32 *) (&infoElement[ 0 ])) );
				else
				{
					U8	value8 = *((U8 *) (&infoElement[ 0 ]));

					printf( "%s: %u\n", pIeLabel, value8 );
					printf( "\t%s\n", uiShowEthernetSybtypeStatus( ieSubType, value8 ) );
				}
			}
			else if (ieType == MODEM_ID_INFO)
			{
				if (ieSubType == BME_ID_INFO) 
				{
					U32 bitMask = (*((U32 *) (&infoElement[ 0 ]))) & 0x80000000;
					if (bitMask == 0x80000000)
					printf("\nRemote CPE is Hostless \n");
					printf( "%s: %lu\n", pIeLabel, (*((U32 *) (&infoElement[ 0 ])) & 0xffffff));

				}
				if ((ieSubType == IFE_ID_INFO) || (ieSubType == AFE_ID_INFO))
					printf( "%s: %lu\n", pIeLabel, *((U32 *) (&infoElement[ 0 ])) );
				if (ieSubType == VENDOR_ID_INFO)
				{
					if ( *((U32 *) (&infoElement[ 0 ])) == 0x23fb5)
					{
		               printf("\nVendor ID: IKANOS\t");
                       printf ("Value: in Hex: %04lx, in Decimal: %ld\n", *((U32 *) (&infoElement[ 0 ])), *((U32 *) (&infoElement[ 0 ])));
					}
	                else
		              printf ("\nVendor ID (Value): %04lx (HEX), %ld (DECIMAL) \n", *((U32 *) (&infoElement[ 0 ])), *((U32 *) (&infoElement[ 0 ])));
				}
				if (ieSubType == NETWORK_INTERFACE_INFO)
				{
					U32 netId = *((U32 *) (&infoElement[ 0 ]));
                    
					if (netId == 0)
						printf("\n Network Interface not supported \n");
					else
					{
						nwInfo = netId >> 24;
						printf("The Network Type = %d", nwInfo);
						nwInfo = (netId &0xffff00) >> 8;
                        printf("\nPart Number = %d", nwInfo);
						nwInfo = (netId & 0xff);
						printf("\nPart Version = %d", nwInfo);

					}

 
				}
				if ((ieSubType == MANUFATURING_ID_INFO) ||
					(ieSubType == MODEL_NUMBER_INFO) ||
					(ieSubType == SERIAL_NUMBER_INFO) ||
					(ieSubType == BOOTLOADER_VERSION_INFO))
			        printf( "%s: %s\n", pIeLabel, &infoElement[ 0 ] );

			}
			else if (ieType == GET_ENET_CFG)
			{
				printf( "\n %s: %02x", pIeLabel, *((U8 *) (&infoElement[ 0 ])) );
			}
			else if (ieType == REMOTE_EXT_STATUS)
			{
				txPwr = *((U16 *) (&infoElement[ 0 ]));
				if(txPwr>=0) 
		           sign = 1;
	            else
	     		   sign = -1;
	
	            txPwr = sign*txPwr;
				printf( "\n %s: %d.%d dbm", pIeLabel,sign*(txPwr / 10), txPwr % 10);
			}
		  /* else the calling program should have filter out the unexpected IE type !! */
		}

		pEocMsg += ieSubLen;
		size += (ieSubLen + 2);
	}
}
	return( size );
}
static void
uiReportStatusByte( int ieType, U8 *pEocMsg, int ieLen )
{
	U8	status = *pEocMsg;
	if (ieType == SET_PHY_LOOPBACK_STATUS)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet PHY looback succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet PHY looback feature not implemented\n" );
	}
	if (ieType == SET_AUTOENET_STATUS_RPT)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet Enet Status Autonomous Reporting succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet Enet Status Autonomous Reporting not implemented\n" );
	}
	if (ieType == SET_ENET_FLOW_CTRL_STATUS)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet Ethernet Flow Control succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet Ethernet Flow Control feature not implemented\n" );
	}
	if (ieType == CLEAR_REMOTE_CNT_STATUS)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet Clear Remote Counters succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet Clear Remote Counters feature not implemented\n" );
	}
	if (ieType == SET_PHY_PARAMS_STATUS)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet Remote Ethernet PHY Configuration  succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet Remote Ethernet PHY Configuration feature not implemented\n" );
	}
	if (ieType == SET_MDIOREG_STATUS)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet MDIO Register succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet MDIO Register feature not implemented\n" );
		else if(status == IPOSRMM_ILLEGAL_REG)
		  printf("\nRequest not processed as the register is a Standard Register\n");
	}
	if (ieType == SET_MDIOFPGAREG_STATUS)
	{
		if (status == IPOS_SUCCESS)
		  printf( "\nSet FPGA MDIO Register succeeded\n" );
		else if (status == FEATURE_NOT_SUPPORTED)
		  printf( "\nSet FPGA MDIO Register feature not implemented\n" );
		else if(status == IPOSRMM_ILLEGAL_REG)
		  printf("\nRequest not processed as the register is a Read Only Register\n");
                else if(status == IPOS_ERROR)
		  printf("\nRequest not processed: Incorrect FPGA Address on CPE\n");
	}
}

static void
uiReportRemoteIeTypes( ipos_port_id pid, U8 uid, int status, void *pData, int dataLen )
{
	U8	*pEocBase = (U8 *) pData;
	U8	*pEocMsg = (U8 *) pData;
	int	 ieType, ieLen;
	int	 msgLen = pEocBase[ EOC_LEN_B ];

	if (status != IPOS_SUCCESS)
	{
		if (status == IPOSEOC_ERROR_TIMEOUT)
		  printf( "\nAttempt to get values from the remote modem timed out on port b%dp%d\n",
			   pid.bmeNum, pid.portNum
		  );
		else
		  printf(
	    "\nAttempt to get values from the remote modem failed for port b%dp%d, status is %d\n",
	       pid.bmeNum, pid.portNum, status
		  );
	}
	else
	  pEocMsg += IPOS_MSGHDR_DATA;

	while ( ((pEocMsg - pEocBase) < msgLen) && (*pEocMsg != IE_NO_INFO) )
	{
		ieType = *pEocMsg++;
		ieLen =	*pEocMsg++;

		if (ieType == FIRMWARE_VERSION_INFO ||
		    ieType == ETHERNET_STATUS_INFO ||
		    ieType == ERRORED_SECONDS_INFO ||
			ieType == MDIO_REGISTER_VALUES ||
			ieType == GPIO_PIN_LIST ||
			ieType == MODEM_ID_INFO ||
			ieType == GET_ENET_CFG ||
			ieType == REMOTE_EXT_STATUS ||
			ieType == GET_AUTOENET_RPT_FLAG ||
			ieType == ENET_ADDRESS_FILTERING ||
			ieType == MDIO_FPGA_REGISTER_VALUES
      		)
		{
			uiReportIetypeWithSubtypes( ieType, pEocMsg, ieLen );
		}

		else if (ieType == SET_PHY_LOOPBACK_STATUS)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
		else if (ieType == SET_ENET_FLOW_CTRL_STATUS)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
		else if (ieType == CLEAR_REMOTE_CNT_STATUS)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
		else if (ieType == SET_PHY_PARAMS_STATUS)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
        else if (ieType == SET_MDIOREG_STATUS)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
                else if (ieType == SET_MDIOFPGAREG_STATUS)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
		else if (ieType == SET_AUTOENET_STATUS_RPT)
		{
			uiReportStatusByte( ieType, pEocMsg, ieLen );
		}
	  /* CPE might send a response with an IE type of IE_SEVERE_ERROR.  Control would come here.
	     Future enhancement: look for this error IE type and report accordingly.	*/

		else if (ieType == IE_SEVERE_ERROR)
		{
			uiReportSevereError( pid, *pEocMsg );
		}
		else
		  printf( "\nCPE returned unsupported IE type of %d (length: %d)\n", ieType, ieLen );

		pEocMsg += ieLen;
	}
	printf( PROMPT );
}
static void
uiReportRemoteSetStatus( ipos_port_id pid, U8 uid, int status, void *pData, int dataLen )
{
	if (status != IPOS_SUCCESS)
	{
		if (status == IPOSEOC_ERROR_TIMEOUT)
		  printf( "\nconfiguring the remote modem timed out on port b%dp%d\n",
			   pid.bmeNum, pid.portNum
		  );
		else
		  printf( "\nconfiguring the remote modem failed for port b%dp%d, status is %d\n",
			   pid.bmeNum, pid.portNum, status
		  );
	}
	else
  {
	  uiReportRemoteIeTypes( pid, uid, status, pData, dataLen );
  }
	printf(PROMPT);
}
#endif

static int
RMMStruct2Msg( void *pStructBuf, U8 msgType, U8 *pBuf )
{
	int		 size = 0, size2 = 0;
	U8		 ack;
	U8		 ieType, ieLen;
	U8		*pLocalBuf = pBuf;
	U8		**pMsgBuf = &pLocalBuf;
	void		*elementAddr = NULL;
	ieEncoder	 ourEncoder = NULL;

	if (msgType == IPOSRMM_SET) {
		ipos_ctrl_hdr	*pCtrlHdr = (ipos_ctrl_hdr *) pStructBuf;

		ack = pCtrlHdr->ack;
		if (ack == IPOS_ACK_CMD)	/* co --> cpe */
		{
			rmm_reboot_firmware	*pRebootFirmware = (rmm_reboot_firmware *) pStructBuf;

			elementAddr = (void *) &(pRebootFirmware->firmwareChoice);
			ieType = REBOOT_FIRMWARE_INFO;
			ieLen = sizeof( pRebootFirmware->firmwareChoice );
		}
		else				/* cpe --> co */
		{
			rmm_reboot_status	*pRebootStatus = (rmm_reboot_status *) pStructBuf;

			elementAddr = (void *) &(pRebootStatus->status);
			ieType = REBOOT_STATUS_INFO;
			ieLen = sizeof( pRebootStatus->status );
		}

	/* programming common to CMD or ACK */

		ourEncoder = ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, ieType, IE_NO_INFO );
		if (ourEncoder == NULL)
		{
		    printf( "No encoder in RMMStruct2Msg, message: %d, ieType: %d\n", msgType, ieType );
			return( 0 );
		}

		size2 = iposEocEncodeCtrlHdr( (ipos_ctrl_hdr *) pStructBuf, pMsgBuf );
		size = size2;

		**pMsgBuf = ieType;
		*pMsgBuf += 2;
		size += 2;
		size2 = ourEncoder( elementAddr, pMsgBuf, ieLen );
		size += size2;
		*(*pMsgBuf - size2 - 1) = size2;	/* ie length */
		pBuf[ IPOS_MSGHDR_MSGLEN ] = size;
	}

	return( size );
}

void
uiGetRemoteVersion( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteVerMsg[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteVerMsg[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteVerMsg[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteVerMsg;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = FIRMWARE_VERSION_INFO;
	*(pEocMsg++) = HOST_VERSION_INFO;	/* TT ID 1240 */
	*(pEocMsg++) = BME_VERSION_INFO;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of subtypes */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteVerMsg[ 0 ];
	lenGetRemoteVerMsg = pEocMsg - pEocBase;
	getRemoteVerMsg[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteVerMsg;

	iposEocCmdCoreSend( pid,
			   &getRemoteVerMsg[ 0 ], lenGetRemoteVerMsg,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Version not available from CPE user interface\n" );
#endif
}

void
uiGetRemoteErroredSeconds( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteErroredSeconds[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteErroredSeconds[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteErroredSeconds[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteErroredSeconds;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = ERRORED_SECONDS_INFO;
	*(pEocMsg++) = SECONDS_WITH_CRC;
	*(pEocMsg++) = SECONDS_WITH_LOS;
	*(pEocMsg++) = SECONDS_WITH_SEF;
	*(pEocMsg++) = SECONDS_WITH_LOF;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of subtypes */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteErroredSeconds[ 0 ];
	lenGetRemoteErroredSeconds = pEocMsg - pEocBase;
	getRemoteErroredSeconds[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteErroredSeconds;

	iposEocCmdCoreSend( pid,
			   &getRemoteErroredSeconds[ 0 ], lenGetRemoteErroredSeconds,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Errored Seconds not available from CPE user interface\n" );
#endif
}

void
uiGetRemoteEthernetStatus( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteEthernetStatus[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteEthernetStatus[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteEthernetStatus[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteEthernetStatus;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = ETHERNET_STATUS_INFO;
	*(pEocMsg++) = LINK_STATUS;
	*(pEocMsg++) = DUPLEX_STATUS;
	*(pEocMsg++) = TRANSMISSION_SPEED;
	*(pEocMsg++) = PAUSE_FRAME_STATUS;
	*(pEocMsg++) = COUNT_PAUSE_FRAMES;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of subtypes */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteEthernetStatus[ 0 ];
	lenGetRemoteEthernetStatus = pEocMsg - pEocBase;
	getRemoteEthernetStatus[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteEthernetStatus;

	iposEocCmdCoreSend( pid,
			   &getRemoteEthernetStatus[ 0 ], lenGetRemoteEthernetStatus,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Ethernet Status not available from CPE user interface\n" );
#endif
}

void
uiGetRemoteMDIORegs( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteMDIORegs[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteMDIORegs[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteMDIORegs[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteMDIORegs, reg;
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = MDIO_REGISTER_LIST;
    for (reg = 0; reg<32 ; reg++)
		*(pEocMsg++) = reg;
	*(pEocMsg++) = NOT_A_REGISTER;		/* terminate list of MDIO registers */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteMDIORegs[ 0 ];
	lenGetRemoteMDIORegs = pEocMsg - pEocBase;
	getRemoteMDIORegs[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteMDIORegs;
	iposEocCmdCoreSend( pid,
			   &getRemoteMDIORegs[ 0 ], lenGetRemoteMDIORegs,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Registers not available from CPE user interface\n" );
#endif
}


void
uiGetRemoteFpgaMDIOReg( ipos_port_id pid,U16 mdioReg_no)
{
#ifdef VTU_O
	U8		 getRemoteMDIORegs[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteMDIORegs[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteMDIORegs[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteMDIORegs;
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
  
	*(pEocMsg++) = MDIO_FPGA_REGISTER_VALUES;
	*pEocMsg++ = 4;				/* place for length */
	
	
  *(pEocMsg++) = FPGA_DIRECT_ADDRESS_REGISTER;
    
  *(pEocMsg++) = ((mdioReg_no & 0x0000ff00) >> 8);
	*(pEocMsg++) = (mdioReg_no & 0x000000ff);
 
	*(pEocMsg++) = FPGA_DIRECT_DATA_REGISTER;
	
  ieLen = pEocMsg - pEocBase ;

  /* terminate list of types for the CPE to get */
	*(pEocMsg++) = IE_NO_INFO;

	pEocBase = &getRemoteMDIORegs[ 0 ];
	lenGetRemoteMDIORegs = pEocMsg - pEocBase;
	getRemoteMDIORegs[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteMDIORegs;
	iposEocCmdCoreSend( pid,
	  &getRemoteMDIORegs[ 0 ], lenGetRemoteMDIORegs,
	  0,
	  IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
	  uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Fpga Registers not available from CPE \
                user interface\n" );
#endif
}

/* Get the remote CPE's Learned Ethernet Address  */
void
uiGetRemoteLearnedEnetAddress( ipos_port_id pid )
{
#ifdef VTU_O

  U8		 getRemoteEnetAddr[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteEnetAddr[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteEnetAddr[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteEnetAddr;
	ipos_ctrl_hdr	 ctrlHdr;
  
//  printf( "\nGet Remote Learned Ethernet Address 1\n" );

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				                    /* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = ENET_ADDRESS_FILTERING;
	*(pEocMsg++) = LEARNED_ADDRESS;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of MDIO registers */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */

	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteEnetAddr[ 0 ];
	lenGetRemoteEnetAddr = pEocMsg - pEocBase;
	getRemoteEnetAddr[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteEnetAddr;

	iposEocCmdCoreSend( pid,
			   &getRemoteEnetAddr[ 0 ], lenGetRemoteEnetAddr,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);

//  printf( "\nGet Remote Learned Ethernet Address 2\n" );
#endif
#ifdef VTU_R
	printf( "\nGet Remote Learned Ethernet Address not available from CPE user interface\n" );
#endif
}


void
uiGetRemoteEnetCfg( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteEnetCfg[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteEnetCfg[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteEnetCfg[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteEnetCfg;
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = GET_ENET_CFG;
    *(pEocMsg++) = AUTO_NEGOTIATION;
	*(pEocMsg++) = ETHERNET_SPEED;
	*(pEocMsg++) = ETHERNET_LINK;
	*(pEocMsg++) = ETHERNET_AGC;
	*(pEocMsg++) = ETHERNET_FLOW_CTRL;
	*(pEocMsg++) = ETHERNET_LPBACK;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of subtypes */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteEnetCfg[ 0 ];
	lenGetRemoteEnetCfg = pEocMsg - pEocBase;
	getRemoteEnetCfg[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteEnetCfg;
	iposEocCmdCoreSend( pid,
			   &getRemoteEnetCfg[ 0 ], lenGetRemoteEnetCfg,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Enet Cfg not available from CPE user interface\n" );
#endif
}

void
uiGetRemoteEnetAutoRptFlag( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteEnetAutoRptFlag[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteEnetAutoRptFlag[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteEnetAutoRptFlag[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteEnetAutoRptFlag;
	
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = GET_AUTOENET_RPT_FLAG;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteEnetAutoRptFlag[ 0 ];
	lenGetRemoteEnetAutoRptFlag = pEocMsg - pEocBase;
	getRemoteEnetAutoRptFlag[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteEnetAutoRptFlag;
	
	iposEocCmdCoreSend( pid,
			   &getRemoteEnetAutoRptFlag[ 0 ], lenGetRemoteEnetAutoRptFlag,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Enet Autonomous Report Flag not available from CPE user interface\n" );
#endif
}

void
uiGetRemoteTxPower( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteTxPower[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteTxPower[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteTxPower[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteTxPower;
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = REMOTE_EXT_STATUS;
    *(pEocMsg++) = TX_POWER;
    *(pEocMsg++) = IE_NO_INFO;		/* terminate list of subtypes */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteTxPower[ 0 ];
	lenGetRemoteTxPower = pEocMsg - pEocBase;
	getRemoteTxPower[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteTxPower;
	iposEocCmdCoreSend( pid,
			   &getRemoteTxPower[ 0 ], lenGetRemoteTxPower,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Tx Power not available from CPE user interface\n" );
#endif
}
void
uiGetRemoteGPIOPin( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteGPIOPin[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteGPIOPin[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteGPIOPin[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteGPIOPin;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = GPIO_PIN_LIST;
	*(pEocMsg++) = GPIO_PIN_NO;
	*(pEocMsg++) = GPIO_PIN_MASK;
	*(pEocMsg++) = GPIO_PIN_VALUE;
  	*(pEocMsg++) = NOT_A_REGISTER;		/* terminate list of GPIO pins */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteGPIOPin[ 0 ];
	lenGetRemoteGPIOPin = pEocMsg - pEocBase;
	getRemoteGPIOPin[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteGPIOPin;

	iposEocCmdCoreSend( pid,
			   &getRemoteGPIOPin[ 0 ], lenGetRemoteGPIOPin,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote GPIO Pins not available from CPE user interface\n" );
#endif
}
void
uiGetRemoteModemId( ipos_port_id pid )
{
#ifdef VTU_O
	U8		 getRemoteModemId[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &getRemoteModemId[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &getRemoteModemId[ 0 ];
	U8		 ieLen = 0;
	int		 lenGetRemoteModemId;

	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = LIST_RMM_IE_TYPES;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = MODEM_ID_INFO;
	*(pEocMsg++) = BME_ID_INFO;
	*(pEocMsg++) = IFE_ID_INFO;
	*(pEocMsg++) = AFE_ID_INFO;
    *(pEocMsg++) = NETWORK_INTERFACE_INFO;
	*(pEocMsg++) = VENDOR_ID_INFO;
	*(pEocMsg++) = MANUFATURING_ID_INFO;
    *(pEocMsg++) = MODEL_NUMBER_INFO;
	*(pEocMsg++) = SERIAL_NUMBER_INFO;
	*(pEocMsg++) = BOOTLOADER_VERSION_INFO;
  	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of Sub Types */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;		/* no more IE types */

	pEocBase = &getRemoteModemId[ 0 ];
	lenGetRemoteModemId = pEocMsg - pEocBase;
	getRemoteModemId[ IPOS_MSGHDR_MSGLEN ] = lenGetRemoteModemId;

   
	iposEocCmdCoreSend( pid,
			   &getRemoteModemId[ 0 ], lenGetRemoteModemId,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteIeTypes
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Modem Id not available from CPE user interface\n" );
#endif
}
void
uiRemoteReboot( ipos_port_id pid, U8 firmwareChoice )
{
#ifdef VTU_O
	U8			rebootMsg[ MAX_MSG_SIZE ];
	int			lenRebootMsg;
	rmm_reboot_firmware	rebootStruct;

	iposEocCmdSetCtrlHdr(
		&rebootStruct.ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	rebootStruct.firmwareChoice = firmwareChoice;
	lenRebootMsg = RMMStruct2Msg(
		       &rebootStruct, IPOSRMM_SET, &rebootMsg[ 0 ]
	);
	if (lenRebootMsg < 1) {
		printf( "\nProgramming problem with RMMStruct2Msg in uiRemoteReboot\n" );
		return;
	}
	iposEocCmdCoreSend( pid,
			   &rebootMsg[ 0 ], lenRebootMsg,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRebootStatus
	);
#endif
#ifdef VTU_R
	printf( "\nRemote Reboot not available from CPE user interface\n" );
#endif
}

void
uiSetRemoteEthernetLb( ipos_port_id pid, U8 lbOption )
{
#ifdef VTU_O
	U8		 setRemoteEthernetLb[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setRemoteEthernetLb[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setRemoteEthernetLb[ 0 ];
	int		 lenSetRemoteEthernetLb;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = SET_PHY_LOOPBACK_LEVEL;
	*(pEocMsg++) = 1;			/* IE length always 1 */
	*(pEocMsg++) = lbOption;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */

	pEocBase = &setRemoteEthernetLb[ 0 ];
	lenSetRemoteEthernetLb = pEocMsg - pEocBase;
	setRemoteEthernetLb[ IPOS_MSGHDR_MSGLEN ] = lenSetRemoteEthernetLb;

	iposEocCmdCoreSend( pid,
			   &setRemoteEthernetLb[ 0 ], lenSetRemoteEthernetLb,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Ethernet Status not available from CPE user interface\n" );
#endif
}

void
uiSetRemoteMDIOReg( ipos_port_id pid, U8 mdioReg_no, U16 mdioReg_value)
{
#ifdef VTU_O
	U8		 setRemoteMDIOReg[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setRemoteMDIOReg[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setRemoteMDIOReg[ 0 ];
	int		 lenSetRemoteMDIOReg;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	*(pEocMsg++) = MDIO_REGISTER_VALUES;
	*(pEocMsg++) = 3;			/* IE length always 3 */
	*(pEocMsg++) = mdioReg_no;
    *(pEocMsg++) = ((mdioReg_value & 0x0000ff00) >> 8);
	*(pEocMsg++) = (mdioReg_value & 0x000000ff);
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	pEocBase = &setRemoteMDIOReg[ 0 ];
	lenSetRemoteMDIOReg = pEocMsg - pEocBase;
	setRemoteMDIOReg[ IPOS_MSGHDR_MSGLEN ] = lenSetRemoteMDIOReg;
	iposEocCmdCoreSend( pid,
			   &setRemoteMDIOReg[ 0 ], lenSetRemoteMDIOReg,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nSet Remote MDIO Register not available from CPE user interface\n" );
#endif
}

void
uiSetRemoteFpgaMDIOReg( ipos_port_id pid, U16 mdioReg_no, U16 mdioReg_value)
{
#ifdef VTU_O
	U8		 setRemoteFpgaMDIOReg[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setRemoteFpgaMDIOReg[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setRemoteFpgaMDIOReg[ 0 ];
	int		 lenSetRemoteFpgaMDIOReg;
	ipos_ctrl_hdr	 ctrlHdr;

  iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	
  *(pEocMsg++) = MDIO_FPGA_REGISTER_VALUES;
	*(pEocMsg++) = 6;			/* IE length always 6 */
  
  /* The FPGA have two direct registers which are in turn used to access
   * the set of Indirect Registers.The two Direct Registers are Address 
   * Register and Data Register. 
   *
   * Address Register = 0x13h
   * Data Register = 0x14h
   *
   * Usage: For setting a Register 0x18h with a Value of 0x06h  
   * Write the Address of Indirect Register 0x18h in Direct Regiser
   * 0x13h and the Value 0x14h in Data Register 0x14h
   *
   * Write now not using the concept of Bank in FPGA.As there are only
   * two Register to be accessed the Bank is always 0
   * */
  

  *(pEocMsg++) = FPGA_DIRECT_ADDRESS_REGISTER ;
  *(pEocMsg++) = ((mdioReg_no & 0xff00) >> 8);
  *(pEocMsg++) = (mdioReg_no & 0x000ff);
  *(pEocMsg++) = FPGA_DIRECT_DATA_REGISTER ;
  *(pEocMsg++) = ((mdioReg_value & 0xff00) >> 8);
	*(pEocMsg++) = (mdioReg_value & 0x00ff);
  *(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */

  pEocBase = &setRemoteFpgaMDIOReg[ 0 ];
	lenSetRemoteFpgaMDIOReg = pEocMsg - pEocBase;
	setRemoteFpgaMDIOReg[ IPOS_MSGHDR_MSGLEN ] = lenSetRemoteFpgaMDIOReg;
	iposEocCmdCoreSend( pid,
			   &setRemoteFpgaMDIOReg[ 0 ], lenSetRemoteFpgaMDIOReg,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nSet Remote FPGA MDIO Register not available from CPE user interface\n" );
#endif
}


void
uiSetRemoteEthernetFlow( ipos_port_id pid, U8 flowCtrlOption )
{
#ifdef VTU_O
	U8		 setRemoteEnetFlowCtrl[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setRemoteEnetFlowCtrl[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setRemoteEnetFlowCtrl[ 0 ];
	int		 lenSetRemoteEnetFlowCtrl;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = SET_ENET_FLOW_CTRL;
	*(pEocMsg++) = 1;			/* IE length always 1 */
	*(pEocMsg++) = flowCtrlOption;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */

	pEocBase = &setRemoteEnetFlowCtrl[ 0 ];
	lenSetRemoteEnetFlowCtrl = pEocMsg - pEocBase;
	setRemoteEnetFlowCtrl[ IPOS_MSGHDR_MSGLEN ] = lenSetRemoteEnetFlowCtrl;

	iposEocCmdCoreSend( pid,
			   &setRemoteEnetFlowCtrl[ 0 ], lenSetRemoteEnetFlowCtrl,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nGet Remote Ethernet Status not available from CPE user interface\n" );
#endif
}
void
uiSetAutoEnetStatusRpt( ipos_port_id pid, U8 reportEn)
{
#ifdef VTU_O
	U8		 setAutoEnetStatusRpt[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setAutoEnetStatusRpt[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setAutoEnetStatusRpt[ 0 ];
	int		 lenSetAutoEnetStatusRpt;
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	*(pEocMsg++) = SET_AUTOENET_STATUS_RPT;
	*(pEocMsg++) = 1;			/* IE length always 1 */
	*(pEocMsg++) = reportEn; /* 0 = Disable; 1 = Enable */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */
	pEocBase = &setAutoEnetStatusRpt[ 0 ];
	lenSetAutoEnetStatusRpt = pEocMsg - pEocBase;
	setAutoEnetStatusRpt[ IPOS_MSGHDR_MSGLEN ] = lenSetAutoEnetStatusRpt;
	iposEocCmdCoreSend( pid,
			   &setAutoEnetStatusRpt[ 0 ], lenSetAutoEnetStatusRpt,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nSet Clear Remote Counters not available from CPE user interface\n" );
#endif
}
void
uiSetClearRemoteCounters( ipos_port_id pid)
{
#ifdef VTU_O
	U8		 setClearRemoteCounters[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setClearRemoteCounters[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setClearRemoteCounters[ 0 ];
	int		 lenSetClearRemoteCounters;
	
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );

	*(pEocMsg++) = CLEAR_REMOTE_COUNTERS;
	*(pEocMsg++) = 1;			/* IE length always 1 */
	*(pEocMsg++) = 0; /* Only Option 0 - All Counters is Used */
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of types for the CPE to get */

	pEocBase = &setClearRemoteCounters[ 0 ];
	lenSetClearRemoteCounters = pEocMsg - pEocBase;
	setClearRemoteCounters[ IPOS_MSGHDR_MSGLEN ] = lenSetClearRemoteCounters;
	

	iposEocCmdCoreSend( pid,
			   &setClearRemoteCounters[ 0 ], lenSetClearRemoteCounters,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nSet Clear Remote Counters not available from CPE user interface\n" );
#endif
}
void
uiSetRemotePhyParams( ipos_port_id pid)
{
#ifdef VTU_O
	U8		 setRemotePhyParams[ MAX_MSG_SIZE ];
	U8		*pEocMsg = &setRemotePhyParams[ IPOS_MSGHDR_DATA ];
	U8		*pEocBase = &setRemotePhyParams[ 0 ];
	int		 lenSetRemotePhyParams, ieLen;
	
	ipos_ctrl_hdr	 ctrlHdr;
	iposEocCmdSetCtrlHdr(
		&ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_CMD, 0
	);
	iposEocEncodeCtrlHdr( &ctrlHdr, &pEocBase );
	
	
	*(pEocMsg++) = SET_PHY_PARAMS;
	pEocMsg++;				/* place for length */
	pEocBase = pEocMsg;
	*(pEocMsg++) = AUTO_NEGOTIATION;
    *(pEocMsg++) = 1;
	*(pEocMsg++) = enetPhyParams.autoNego;
	*(pEocMsg++) = ETHERNET_SPEED;
	*(pEocMsg++) = 1;
	*(pEocMsg++) = enetPhyParams.enetSpeed;
	*(pEocMsg++) = ETHERNET_LINK;
	*(pEocMsg++) = 1;
	*(pEocMsg++) = enetPhyParams.enetLink;
    *(pEocMsg++) = ETHERNET_AGC;
	*(pEocMsg++) = 1;
	*(pEocMsg++) = enetPhyParams.enetAGC;
	*(pEocMsg++) = ETHERNET_FLOW_CTRL;
	*(pEocMsg++) = 1;
	*(pEocMsg++) = enetPhyParams.enetFlowCtrl;
	*(pEocMsg++) = ETHERNET_LPBACK;
	*(pEocMsg++) = 1;
	*(pEocMsg++) = enetPhyParams.enetLpBack;
	*(pEocMsg++) = IE_NO_INFO;		/* terminate list of subtypes for the CPE to set */
	*(pEocMsg++) = IE_NO_INFO;      /* terminate list of types for the CPE to set */
	ieLen = pEocMsg - pEocBase;
	*(pEocMsg - (ieLen + 1)) = ieLen;	/* length of LIST_RMM_IE_TYPES */
	*(pEocMsg++) = IE_NO_INFO;          /* no more IE Types */

	pEocBase = &setRemotePhyParams[ 0 ];
	lenSetRemotePhyParams = pEocMsg - pEocBase;
	setRemotePhyParams[ IPOS_MSGHDR_MSGLEN ] = lenSetRemotePhyParams;

    
	iposEocCmdCoreSend( pid,
			   &setRemotePhyParams[ 0 ], lenSetRemotePhyParams,
			    0,
			    IPOS_NO_RESEND, RMM_RESEND_INTERVAL1,
			    uiReportRemoteSetStatus
	);
#endif
#ifdef VTU_R
	printf( "\nSet Clear Remote Counters not available from CPE user interface\n" );
#endif
}
#ifdef VTU_O
static void
coRMMHandler( ipos_port_id pid, int status, void *pEocMsg, int dataLen )
{
	int		msgClass = iposEocGetMsgClass( pEocMsg );	

	if (msgClass == IPOS_MSG_RESPONSE)
	{
		iposEocCmdCoreResp( pid, EOC_RMM_PROTOCOL, pEocMsg, dataLen );
	}
	else 
	  printf( "\nRMM protocol received a message of unrecognized class %d\n", msgClass );
}
#endif

/*
 * Get firmware info maintains 3 counters.
 * 1) Count of bytes parsed in the source message - sizeSource
 *    This is returned to the calling program
 * 2) Count of bytes for individual subtypes - sizeIeSubtype
 * 3) Overall count of bytes for all subtypes - sizeIeType
 *    This is returned implicitly by comparing address whose address
 *    is in pPResp with base address pRespBase
 *
 */

#ifdef VTU_R

static int
cpeRMMReportError( U8 *pRespBase, U8 **pPResp, U8 problem )
{
	pRespBase[ IPOS_MSGHDR_DATA ] = IE_SEVERE_ERROR;
	pRespBase[ IPOS_MSGHDR_DATA + 1 ] = IE_SEVERE_ERROR_LEN;
	pRespBase[ IPOS_MSGHDR_DATA + 2 ] = problem;
	pRespBase[ IPOS_MSGHDR_DATA + 3 ] = IE_NO_INFO;

	pRespBase[ EOC_LEN_B ] = IPOS_MSGHDR_DATA + 4;
	*pPResp = pRespBase + (IPOS_MSGHDR_DATA + 4);

	return( IPOS_MSGHDR_DATA + 4 );
}

static int
cpeRMMCompleteReturnedIeType( U8 **pPResp, int sizeIeType, int sizeSource )
{
	sizeSource++;		/* skip over subtype of 0 (IE_NO_INFO) */
	**pPResp = IE_NO_INFO;
	(*pPResp)++;
	sizeIeType++;
	*(*pPResp - (sizeIeType + 1)) = sizeIeType;	/* ie length */

	return( sizeSource );
}

#ifdef BME_CPE_20
static int
cpeRMMCompleteRetRegIeType( U8 **pPResp, int sizeIeType, int sizeSource )
{
	sizeSource++;		/* skip over subtype of 0 (IE_NO_INFO) */
	**pPResp = NOT_A_REGISTER;
	(*pPResp)++;
	sizeIeType++;
	*(*pPResp - (sizeIeType + 1)) = sizeIeType;	/* ie length */

	return( sizeSource );
}
#ifdef INI_SUPPORT
static int
  cpeRMMGetEnetAddrFilt ( int lineNum, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{
	U8	 reqIeSubtype;
	S16	 sizeSource = 0, sizeIeType = 0;
	U8	*pEocBase = pEocMsg;

  U8	 proceed = 1;

	**pPResp = ENET_ADDRESS_FILTERING;
	*pPResp += 2;

	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO) )
	{
		reqIeSubtype = *(pEocMsg++);
		sizeSource++;

		switch (reqIeSubtype)
		{
		  case LEARNED_ADDRESS:
#if defined(CPE_30)
{
      int i;
      S16 sizeIeSubtype = 0;
			  
        **pPResp = reqIeSubtype;
			  *pPResp += 2;

        for(i = 0; i < 32; i++)
        {
          U8 abMacAddr[6];

          if (HOST_INI_NO_ERROR == iposPtmfReadLearnedAddr(i, abMacAddr))
          {
			      if ((*pPResp - pRespBase) + 6 >= MAX_MSG_SIZE)
			      {
				      cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				      return( -1 );
			      }

            **pPResp = abMacAddr[0];
            *pPResp += 1;
            **pPResp = abMacAddr[1];
            *pPResp += 1;
            **pPResp = abMacAddr[2];
            *pPResp += 1;
            **pPResp = abMacAddr[3];
            *pPResp += 1;
            **pPResp = abMacAddr[4];
            *pPResp += 1;
            **pPResp = abMacAddr[5];
            *pPResp += 1;

			      sizeIeSubtype += 6;
          }
        }

        *(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
			  sizeIeType += (sizeIeSubtype + 2);
//        printf ("\nRead Remote Learned Ethernet Address %d-%d", sizeIeType, sizeIeSubtype);
}
        break;
#endif //#if defined (CPE_30)


		  case STATIC_ADDRESS:
		  default:
        proceed = 0;
        break;
		}

		if (proceed)
		{
			if ((*pPResp - pRespBase) + sizeof( U32 ) >= MAX_MSG_SIZE)
			{
				cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				return( -1 );
			}

		}
	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteReturnedIeType( pPResp, sizeIeType, sizeSource );
	}

	return( sizeSource );
}
//eRMMCompleteRetRegIeTyp
#endif
#endif

#ifdef INI_SUPPORT


static int
cpeRMMGetEthernetInfo( int lineNum, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{
	U8	 reqIeSubtype;
	S16	 sizeSource = 0, sizeIeType = 0, sizeIeSubtype = 0;
	U8	*pEocBase = pEocMsg;
	int	 ptmfIndex;
	U8	 proceed = 1;

	getIniPhy( lineNum, &ptmfIndex );

	**pPResp = ETHERNET_STATUS_INFO;
	*pPResp += 2;

	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO) )
	{
		eIposPtmfCounterType	eCounterType = RX_ENET_PAUSE_FRAMES;
		eIposPtmfParamType	eParamType = ENET_LINK_EN;
		eIniRetCode		eRetCode = HOST_INI_NO_ERROR;
		U32			value32;
		U8			value8;
		ieEncoder		ourEncoder = NULL;

		reqIeSubtype = *(pEocMsg++);
		sizeSource++;

		ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, reqIeSubtype );
		if (ourEncoder == NULL)
		{
		    printf( "\nNo encoder for GetErrored Seconds, subtype %d\n", reqIeSubtype );
			continue;
		}

		switch (reqIeSubtype)
		{
		  case LINK_STATUS:
			eParamType = ENET_LINK_EN;
			break;

		  case DUPLEX_STATUS:
			eParamType = ENET_LINK_DUPLEX;
			break;

		  case TRANSMISSION_SPEED:
			eParamType = ENET_LINK_SPEED;
			break;

		  case PAUSE_FRAME_STATUS:
			eParamType = ENET_LINK_FLOW_CONTROL;
			break;

		  case COUNT_PAUSE_FRAMES:
			eCounterType = RX_ENET_PAUSE_FRAMES;
			break;

		  default:
			proceed = 0;
			break;
		}

		switch (reqIeSubtype)
		{
		  case LINK_STATUS:
		  case DUPLEX_STATUS:
		  case TRANSMISSION_SPEED:
		  case PAUSE_FRAME_STATUS:

		/* although the returned value is only 8 bits,
		   the PTMF interface program returns 32 bits */

			eRetCode = iposPtmfGetConfigParam( ptmfIndex, eParamType, &value32 );
			if (eRetCode != HOST_INI_NO_ERROR)
			  value8 = UNKNOWN_STATUS;
			else
			  value8 = (value32 & 0xff);
			break;

		  case COUNT_PAUSE_FRAMES:
			eRetCode = iposPtmfGetCounter( ptmfIndex, eCounterType, &value32 );
			if (eRetCode != HOST_INI_NO_ERROR)
			  value32 = 0;
			break;

		  default:
			proceed = 0;
			break;
		}

		if (proceed)
		{
			if ((*pPResp - pRespBase) + sizeof( U32 ) >= MAX_MSG_SIZE)
			{
				cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				return( -1 );
			}

			**pPResp = reqIeSubtype;
			*pPResp += 2;
			if (reqIeSubtype == COUNT_PAUSE_FRAMES)
			  sizeIeSubtype = ourEncoder( &value32, pPResp, sizeof( U32 ) );
			else
			  sizeIeSubtype = ourEncoder( &value8, pPResp, sizeof( U8 ) );
			*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
			sizeIeType += (sizeIeSubtype + 2);
		}
	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteReturnedIeType( pPResp, sizeIeType, sizeSource );
	}

	return( sizeSource );
}

#endif

static int
cpeRMMGetErroredSeconds( int lineNum, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{
	U8	 reqIeSubtype;
	S16	 sizeSource = 0, sizeIeType = 0, sizeIeSubtype = 0;
	U8	*pEocBase = pEocMsg;

	**pPResp = ERRORED_SECONDS_INFO;
	*pPResp += 2;

	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO) )
	{
		eErroredSecondsType	eEST;
		ieEncoder		ourEncoder = NULL;

		reqIeSubtype = *(pEocMsg++);
		sizeSource++;

		ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, reqIeSubtype );
		if (ourEncoder == NULL)
		{
		    printf( "\nNo encoder for Get Errored Seconds, subtype %d\n", reqIeSubtype );
			continue;
		}

		switch (reqIeSubtype)
		{
		  case SECONDS_WITH_CRC:
			eEST = eSecondsWithCRC_F;
			break;

		  case SECONDS_WITH_LOS:
			eEST = eSecondsWithLOS;
			break;

		  case SECONDS_WITH_SEF:
			eEST = eSecondsWithSEF;
			break;

		  case SECONDS_WITH_LOF:
			eEST = eSecondsWithLOF;
			break;

		  default:
			eEST = eSecondsNotSupported;
			break;
		}

		if (eEST != eSecondsNotSupported)
		{
			U32	erroredSeconds = getErroredSeconds( lineNum, eEST );

			if ((*pPResp - pRespBase) + sizeof( U32 ) >= MAX_MSG_SIZE)
			{
				cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				return( -1 );
			}

			**pPResp = reqIeSubtype;
			*pPResp += 2;
			sizeIeSubtype = ourEncoder( &erroredSeconds, pPResp, sizeof( U32 ) );
			*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
			sizeIeType += (sizeIeSubtype + 2);
		}
	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteReturnedIeType( pPResp, sizeIeType, sizeSource );
	}

	return( sizeSource );
}
#ifdef BME_CPE_20

#ifdef INI_SUPPORT
static int
cpeRMMGetMDIORegs( int lineNum, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{
	U8	 reqIeSubtype;
	S16	 sizeSource = 0, sizeIeType = 0, sizeIeSubtype = 0;
	U8	*pEocBase = pEocMsg;
	U16	MDIO_REGValue;
	int ptmfIndex;
	**pPResp = MDIO_REGISTER_VALUES;
	*pPResp += 2;
	getIniPhy( lineNum, &ptmfIndex );
	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != NOT_A_REGISTER))
	{
		ieEncoder		ourEncoder = NULL;
		eIniRetCode		eRetCode = HOST_INI_NO_ERROR;

		reqIeSubtype = *(pEocMsg++);
		sizeSource++;
		ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, MDIO_REGISTER_LIST, NOT_A_REGISTER );
		if (ourEncoder == NULL)
		{
		    printf( "\nNo encoder for Get MDIO Regs, subtype %d\n", reqIeSubtype );
			continue;
		}

            eRetCode = iposMdioRegRead(ptmfIndex, reqIeSubtype, &MDIO_REGValue);
			
			if( eRetCode != HOST_INI_NO_ERROR)
				MDIO_REGValue = 0; 

			if ((*pPResp - pRespBase) + sizeof( U16 ) >= MAX_MSG_SIZE)
			{
				cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				return( -1 );
			}

			**pPResp = reqIeSubtype;
			*pPResp += 2;
			sizeIeSubtype = ourEncoder( &MDIO_REGValue, pPResp, sizeof( U16 ) );
			*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
			sizeIeType += (sizeIeSubtype + 2);

	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteRetRegIeType( pPResp, sizeIeType, sizeSource );
	}
 
	return( sizeSource );
}
#endif

static int
cpeRMMGetEnetAutoRptFlag( int lineNum, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{
	S16	 sizeSource = 0, sizeIeType = 0/*, sizeIeSubtype = 0*/;
    U8	*pEocBase = pEocMsg;

    **pPResp = GET_AUTOENET_RPT_FLAG;
	*pPResp += 2;
	**pPResp = autoEnetRptEnable;
	sizeIeType = 1;
	
	*pPResp += 1;


	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteReturnedIeType( pPResp, sizeIeType, sizeSource );
	}
 	return( sizeSource );
}

static int
cpeRMMGetGPIOPins( int lineNum, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{

	U8	 reqIeSubtype;
	S16	 sizeSource = 0, sizeIeType = 0, sizeIeSubtype = 0;
	U8	*pEocBase = pEocMsg;
	int	numLines = 8; /* Hard Coded Value */
	int  pinDir;
	int  pinValue;
	U8  encValue;


	**pPResp = GPIO_PIN_LIST;
	*pPResp += 2;



	iposBmeGpioMaskRead(1, (U32*)&pinDir);
	pinValue = iposBmeGpioRead(1, 0);

/*	readGPIOStatus ( &numLines, &pinDir, &pinValue); */

	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != NOT_A_REGISTER))
	{
		ieEncoder		ourEncoder = NULL;
   		reqIeSubtype = *(pEocMsg++);
		sizeSource++;

		ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, GPIO_PIN_LIST, NOT_A_REGISTER );
		if (ourEncoder == NULL)
		{
		    printf( "\nNo encoder for Get MDIO Regs, subtype %d\n", reqIeSubtype );
			continue;
		}
        
		if (reqIeSubtype == GPIO_PIN_NO)
		encValue = (U8 ) numLines;
		if (reqIeSubtype == GPIO_PIN_MASK)
		encValue = (U8 ) pinDir; 
		if (reqIeSubtype == GPIO_PIN_VALUE)
		encValue = (U8 ) pinValue; 
            			
			if ((*pPResp - pRespBase) + sizeof( U8 ) >= MAX_MSG_SIZE)
			{
				cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				return( -1 );
			}

			**pPResp = reqIeSubtype;
			*pPResp += 2;
			sizeIeSubtype = ourEncoder( &encValue, pPResp, sizeof( U8 ) );
			*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
			sizeIeType += (sizeIeSubtype + 2);
			

	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteRetRegIeType( pPResp, sizeIeType, sizeSource );
	}
 	return( sizeSource );
}
#endif

static int
cpeRMMGetFirmwareInfo( U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen )
{
	U8	 reqIeSubtype;
	S16	 sizeSource = 0, sizeIeType = 0, sizeIeSubtype = 0;
	U8	*pEocBase = pEocMsg;

	**pPResp = FIRMWARE_VERSION_INFO;
	*pPResp += 2;

	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO) )
	{
		eDeviceChoice	thisDevice;
		ieEncoder	ourEncoder = NULL;

		reqIeSubtype = *(pEocMsg++);
		sizeSource++;

		ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, reqIeSubtype );
		if (ourEncoder == NULL)
		{
		    printf( "\nNo encoder for Firmware Version, subtype %d\n", reqIeSubtype );
			continue;
		}

		switch (reqIeSubtype) 
		{
		  case HOST_VERSION_INFO:
			thisDevice = eHOST_VERISON;
			break;

		  case BME_VERSION_INFO:
			thisDevice = eBME_FW_VERSION;
			break;

		  case AFE_VERSION_INFO:
			thisDevice = eAFE_VERSION;
			break;

		  case IFE_VERSION_INFO:
			thisDevice = eIFE_VERSION;
			break;

		  case BME_HW_VERSION_INFO:
			thisDevice = eBME_HW_VERSION;
			break;

		  default:
			thisDevice = eNO_DEVICE;
			break;
		}

		if (thisDevice != eNO_DEVICE)
		{
			const char	*thisVersion = getDeviceVersion( 1, thisDevice );

		  /* Here the CPE proposes to copy thisVersion into the response message
		     Be sure there is room for the NUL character ... */

			if (((*pPResp - pRespBase) + strlen( thisVersion ) + 1) >= MAX_MSG_SIZE)
			{
				cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
				return( -1 );
			}

			**pPResp = reqIeSubtype;
			*pPResp += 2;
			sizeIeSubtype = ourEncoder( thisVersion, pPResp, strlen( thisVersion ) + 1 );
			*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
			sizeIeType += (sizeIeSubtype + 2);
		}
	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteReturnedIeType( pPResp, sizeIeType, sizeSource );
	}

	return( sizeSource );
}


static int
cpeRMMGetTxPower( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen)
{
	U8	 reqIeSubtype;
	U16 txPwr = 0;
	S16	 sizeSource = 0, sizeIeType = 0, sizeIeSubtype = 0;
	U8	*pEocBase = pEocMsg;

    txPwr = (U16 )BmeStruct[pid.bmeNum].Port[pid.portNum].PortParms.PortStatusExtParms.TransmitPower;

	**pPResp = REMOTE_EXT_STATUS;
	*pPResp += 2;

	while ( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO))
	{
		ieEncoder		ourEncoder = NULL;
		
		reqIeSubtype = *(pEocMsg++);
		sizeSource++;
		ourEncoder = appEocGetEncoder( EOC_RMM_PROTOCOL, REMOTE_EXT_STATUS, reqIeSubtype );
		if (ourEncoder == NULL)
		{
		    printf( "\nNo encoder for Get MDIO Regs, subtype %d\n", reqIeSubtype );
			continue;
		}

        if ((*pPResp - pRespBase) + sizeof( U16 ) >= MAX_MSG_SIZE)
		{
			cpeRMMReportError( pRespBase, pPResp, OUTPUT_OVERFLOW );
			return( -1 );
		}

		**pPResp = reqIeSubtype;
		*pPResp += 2;
		sizeIeSubtype = ourEncoder( &txPwr, pPResp, sizeof( U16 ) );
		
		*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
		sizeIeType += (sizeIeSubtype + 2);

	}

	if ((pEocMsg - pEocBase) >= ieLen)
	{
		cpeRMMReportError( pRespBase, pPResp, INPUT_OVERFLOW );
		sizeSource = -1;				/* prepare to return error */
	}
	else
	{
		sizeSource = cpeRMMCompleteReturnedIeType( pPResp, sizeIeType, sizeSource );
	}

	return( sizeSource );
}


static int
cpeRMMGetListIeTypes( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 *pEocMsg, U8 ieLen)
{
	U8	 reqIeType;
	U8	*pEocBase = pEocMsg;
	int	 lineNum, size = 0;

	getLineNum( pid, &lineNum );
	while( ((pEocMsg - pEocBase) < ieLen) && (*pEocMsg != IE_NO_INFO) )
	{
		reqIeType = *(pEocMsg++);

		switch (reqIeType)
		{
		  case FIRMWARE_VERSION_INFO:
			size = cpeRMMGetFirmwareInfo( pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase) );
			break;

		  case ETHERNET_STATUS_INFO:
#ifdef INI_SUPPORT
			size = cpeRMMGetEthernetInfo( lineNum, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase) );
#else
			cpeRMMReportError( pRespBase, pPResp, FEATURE_NOT_SUPPORTED );
			size = -1;
#endif
			break;

		  case ERRORED_SECONDS_INFO:
			size = cpeRMMGetErroredSeconds( lineNum, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase) );
			break;
		  case REMOTE_EXT_STATUS:
			size = cpeRMMGetTxPower( pid, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase) );
			break;
#ifdef BME_CPE_20

		  case MDIO_REGISTER_LIST:
#ifdef INI_SUPPORT
			size = cpeRMMGetMDIORegs( lineNum, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase));
#else
			cpeRMMReportError( pRespBase, pPResp, FEATURE_NOT_SUPPORTED );
			size = -1;
#endif
      break;

      case ENET_ADDRESS_FILTERING:
#ifdef INI_SUPPORT
      size = cpeRMMGetEnetAddrFilt( lineNum, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase) );
#else
			cpeRMMReportError( pRespBase, pPResp, FEATURE_NOT_SUPPORTED );
			size = -1;
#endif
			break;

		  case GET_AUTOENET_RPT_FLAG:
            size = cpeRMMGetEnetAutoRptFlag( lineNum, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase));
            break;

		  case GPIO_PIN_LIST:
			size = cpeRMMGetGPIOPins( lineNum, pRespBase, pPResp, pEocMsg, ieLen - (pEocMsg - pEocBase));
            break;
#endif
            
		  default:
			printf( "\nUnrecognized requested IE type %d\n", reqIeType );
			cpeRMMReportError( pRespBase, pPResp, FEATURE_NOT_SUPPORTED );
			size = -1;
			printf (PROMPT);
			break;
		}

	   /* get out if problem */

		if (size < 0)
		  return( -1 );

		pEocMsg += size;
	}
	**pPResp = IE_NO_INFO;
	(*pPResp)++;

	pEocMsg++;	/* move past the end of the list of requested IE types */

	return( pEocMsg - pEocBase );
}

static void
cpeRMMGetEventHandler( pIposEocPerPort pRMMPerPort, U8 *pEocMsg, int msgLen )
{
	U8		 response[ MAX_MSG_SIZE ];
	U8		*pResp = &response[ 0 ];
	U8		*pEocBase = pEocMsg;
	U8		 ieType, ieLen;
	int		 sizeSource = 0, sizeResp = 0;
	ipos_ctrl_hdr	 ctrlHdr;
    
	iposEocDecodeCtrlHdr( pEocMsg, &ctrlHdr );
	iposEocCmdSetCtrlHdr( &ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_GET, IPOS_ACK_ACK, ctrlHdr.uid );
	sizeSource = iposEocEncodeCtrlHdr( &ctrlHdr, &pResp );
	pEocMsg += IPOS_MSGHDR_DATA;

	while( ((pEocMsg - pEocBase) < msgLen) && (*pEocMsg != IE_NO_INFO) )
	{
		ieType = *pEocMsg++;
		ieLen = *pEocMsg++;

		if (ieType == LIST_RMM_IE_TYPES)
		{
			sizeSource = cpeRMMGetListIeTypes(
					 pRMMPerPort->pid,
					&response[ 0 ],		/* base address for response message */
					&pResp,			/* updating address for response message */
					 pEocMsg, ieLen
			);
			if (sizeSource < 0)			/* if problem, get out */
			  break;
			pEocMsg += sizeSource;
		}
		else {
			printf( "\nUnrecognized ie type %d for protocol EOC_RMM_PROTOCOL\n", ieType );
		}
	}

	sizeResp = (pResp - &response[ 0 ]);
	response[ EOC_LEN_B ] = sizeResp;

#ifdef SHOW_CPE_RESPONSE
	printf( "CPE RMM Get Event Handler, message now has %d bytes\n", sizeResp );
	{
		U8	*pResp_2 = &response[ 0 ];

		for (; pResp_2 < pResp; pResp_2++)
		  printf( "%d ", *pResp_2 );
		printf( "\n" );
	}
#endif
    
	iposEocSendDataStream( pRMMPerPort->pid, sizeResp, &response[ 0 ], 0, 0, NULL );
}

#if defined(BME_CPE_20) && defined(INI_SUPPORT)
static void
cpeRMMSetPhyLbEventHandler( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 lbOption )
{
	U8	 	sizeIeSubtype = 1, setPhyLbStatus = IPOS_SUCCESS;
	eIniRetCode	eRetCode = HOST_INI_NO_ERROR;
	int	 	lineNum, ptmfIndex;
	U32		uiParam = lbOption;

	getLineNum( pid, &lineNum );
	getIniPhy( lineNum, &ptmfIndex );

	printf( "\ncpeRMMSetPhyLbEventHandler, lb option is %d, line number is %d, PTMF index is %d\n", lbOption, lineNum, ptmfIndex );

	eRetCode = iposPtmfSetConfigParam( ptmfIndex, ENET_LOOPBACK, uiParam);
	if (eRetCode != HOST_INI_NO_ERROR)
	  setPhyLbStatus = IPOS_ERROR;

	**pPResp = SET_PHY_LOOPBACK_STATUS;
	*pPResp += 2;
	**pPResp = setPhyLbStatus;
	*pPResp += 1;
	*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
	**pPResp = IE_NO_INFO;
	*pPResp += 1;
}

static void
cpeRMMSetAutoEnetStatusRptHandler( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 reportEn )
{
	U8	 	sizeIeSubtype = 1, setAutoRptStatus = IPOS_SUCCESS;
	autoEnetRptEnable = reportEn;
	**pPResp = SET_AUTOENET_STATUS_RPT;
	*pPResp += 2;
	**pPResp = setAutoRptStatus;
	*pPResp += 1;
	*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
	**pPResp = IE_NO_INFO;
	*pPResp += 1;
}
static void
cpeRMMSetMDIORegHandler( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 mdioReg, U16 regValue)
{
	U8	 	sizeIeSubtype = 1, setMdioRegStatus = IPOS_SUCCESS;
	eIniRetCode	eRetCode = HOST_INI_NO_ERROR;
	int	 	lineNum, ptmfIndex;
	
	getLineNum( pid, &lineNum );
	getIniPhy( lineNum, &ptmfIndex );
    eRetCode = iposMdioRegWrite(ptmfIndex, mdioReg, &regValue);
	if (eRetCode != HOST_INI_NO_ERROR)
	{
		setMdioRegStatus = IPOS_ERROR;
		if(eRetCode == HOST_INI_ILLEGAL_MDIO_REG)
			setMdioRegStatus = IPOSRMM_ILLEGAL_REG;
	}
	**pPResp = SET_MDIOREG_STATUS;
	*pPResp += 2;
	**pPResp = setMdioRegStatus;
	*pPResp += 1;
	*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
	**pPResp = IE_NO_INFO;
	*pPResp += 1;
}

#endif
/*
 * self contained.  either it works and the system is rebooted
 * or it fails and reports an error to the CO
 *
 */

static void
cpeRMMRebootEventHandler( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 firmwareChoice )
{
	rmm_reboot_status	rebootStatus;
	U8			rebootSystem = 0;
	int			msgLen = 0, errCode = IPOS_SUCCESS;

	iposEocCmdSetCtrlHdr( &rebootStatus.ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_ACK, 0 );

/*
 * for now, only allow choice == 0
 * future: choice = 1 or choice = 2   ===>  reboot selected firmware in flash
 *         choice = 255               ===>  reboot "other" firmware in flash
 */

	if (firmwareChoice == 0)
	{
		if (bootloadInfo()==0)		/* bootloader is compatiable */
		{
			rebootStatus.status = REBOOT_OK;
			rebootSystem = 1;
		}
		else
		{
			rebootStatus.status = INCOMPATIBLE_BOOTLOADER;
		}
	}
	else
	{
		rebootStatus.status = INVALID_FIRMWARE;
	}

	msgLen = RMMStruct2Msg( &rebootStatus, IPOSRMM_SET, pRespBase );
	if (msgLen > 0)
	{
		errCode = iposEocSendDataStream( pid, msgLen, pRespBase, 0, 0, NULL );
	}
	else {
		printf( "\nCPE RMM reboot event handler had problem preparing EOC response message\n" );
	}

	if (rebootSystem)
	{
		printf( "\nThis system will reboot in 1 second\n" );
		iposTaskDelay( CLOCKS_PER_SEC );
		reboot( 0 );
	}
}

static void
cpeRMMSetClearCountersHandler( ipos_port_id pid, U8 *pRespBase, U8 **pPResp, U8 counter)
{
	U8	 	sizeIeSubtype = 1, setClearStatus = IPOS_SUCCESS;
#ifdef INI_SUPPORT
	eIniRetCode	eRetCode = HOST_INI_NO_ERROR;
       	U32		uiParam = 0;
        int	 	lineNum, ptmfIndex;
#endif
	static char pTlStr[512];
	//int	 	lineNum, ptmfIndex;
	//U32		uiParam = 0;
    pTlStr[0] = '\0';

	
    sprintf (pTlStr,"clrcntr:0:%d:%d;", pid.bmeNum,pid.portNum);
    if (strlen(pTlStr))
        ReceiveTLCommand (pTlStr);
	else
		printf("\n Invalid Clear Command");
#ifdef INI_SUPPORT	
	getLineNum( pid, &lineNum );
	getIniPhy( lineNum, &ptmfIndex );
//	printf( "\ncpeRMMSetClearCountersHandler, counter option is %d, line number is %d, PTMF index is %d\n", counter, lineNum, ptmfIndex );
	eRetCode = iposPtmfSetCounter( ptmfIndex, ALL_COUNTERS, uiParam);
	if (eRetCode != HOST_INI_NO_ERROR)
	  setClearStatus = IPOS_ERROR;
#endif

	**pPResp = CLEAR_REMOTE_CNT_STATUS;
	*pPResp += 2;
	**pPResp = setClearStatus;
	*pPResp += 1;
	*(*pPResp - (sizeIeSubtype + 1)) = sizeIeSubtype;	/* subtype length */
	**pPResp = IE_NO_INFO;
	*pPResp += 1;
}
static void
cpeRMMSetEventHandler( pIposEocPerPort pRMMPerPort, U8 *pEocMsg, int msgLen )
{
	U8		*pEocBase = pEocMsg;
	U8		 ieType, ieLen;
	U8		 response[ MAX_RMM_SET_RESPONSE ];
	U8		*pResp = &response[ 0 ];
	int		 sizeSource = 0, sizeResp = 0;
	ipos_ctrl_hdr	 ctrlHdr;

	iposEocDecodeCtrlHdr( pEocMsg, &ctrlHdr );
	iposEocCmdSetCtrlHdr( &ctrlHdr, EOC_RMM_PROTOCOL, IPOSRMM_SET, IPOS_ACK_ACK, ctrlHdr.uid );
	sizeSource = iposEocEncodeCtrlHdr( &ctrlHdr, &pResp );
	pEocMsg += IPOS_MSGHDR_DATA;

	while( ((pEocMsg - pEocBase) < msgLen) && (*pEocMsg != IE_NO_INFO) )
	{
		ieType = *pEocMsg++;
		ieLen = *pEocMsg++;

		if ((ieType == REBOOT_FIRMWARE_INFO) || (ieType == SET_PHY_LOOPBACK_LEVEL) || 
			(ieType == SET_ENET_FLOW_CTRL) || (ieType == CLEAR_REMOTE_COUNTERS) ||
			(ieType == MDIO_REGISTER_VALUES) || (ieType == SET_PHY_PARAMS) ||
			(ieType == SET_AUTOENET_STATUS_RPT))
		{
			
			ieDecoder	ourDecoder = NULL;

			ourDecoder = appEocGetDecoder( EOC_RMM_PROTOCOL, ieType, IE_NO_INFO );
			if (ourDecoder == NULL)
			{
				printf(
			   "\nNo decoder for protocol EOC_RMM_PROTOCOL, ie type %d, skipping\n",
			      ieType
				);
                printf( PROMPT );
			}
			else if (ieType == REBOOT_FIRMWARE_INFO)
			{
				U8		firmwareChoice;
				ourDecoder( pEocMsg, &firmwareChoice, ieLen );
				cpeRMMRebootEventHandler(
					pRMMPerPort->pid, &response[ 0 ], &pResp, firmwareChoice
				);

			  /* If the reboot event was accepted, the system gets rebooted and control
			     never comes here.  If the event was not accepted, the remote CO was
			     notified a problem occurred.  Processing for this event is now complete. */

				return;
			}
			else if (ieType == CLEAR_REMOTE_COUNTERS)
			{
			    U8 cntrOption;
				ourDecoder( pEocMsg, &cntrOption, ieLen );
				cpeRMMSetClearCountersHandler(
					pRMMPerPort->pid, &response[ 0 ], &pResp, cntrOption
				);
			}
#if defined(BME_CPE_20) && defined(INI_SUPPORT)
			else if (ieType == MDIO_REGISTER_VALUES)
			{

				U8   mdioReg_no;
				U16  mdioReg_value;
				mdioReg_no = *pEocMsg++;
				ourDecoder( pEocMsg, &mdioReg_value, 2);
				cpeRMMSetMDIORegHandler(pRMMPerPort->pid, &response[ 0 ], &pResp, mdioReg_no,
				mdioReg_value);
			}
			else if (ieType == SET_AUTOENET_STATUS_RPT)
			{
				U8	rptEnable;
                ourDecoder( pEocMsg, &rptEnable, ieLen );
				cpeRMMSetAutoEnetStatusRptHandler(
					pRMMPerPort->pid, &response[ 0 ], &pResp, rptEnable
				);
			}
#endif
			else			/* ieType == SET_PHY_LOOPBACK_LEVEL */
			{
#if defined(BME_CPE_20) && defined(INI_SUPPORT)
				U8	lbOption;

				ourDecoder( pEocMsg, &lbOption, ieLen );
				cpeRMMSetPhyLbEventHandler(
					pRMMPerPort->pid, &response[ 0 ], &pResp, lbOption
				);
#endif
			}
			pEocMsg += ieLen;
		}
/* NOT IMPLEMENTED: IE types with a variable number of parameters could be handled here */

		else
		{
			printf( "\nIE type: %d, length: %d, *pEocMsg: %d\n", ieType, ieLen, *pEocMsg );
			pEocMsg += ieLen;
		}
	}

		sizeResp = (pResp - &response[ 0 ]);
	response[ EOC_LEN_B ] = sizeResp;

#ifdef SHOW_CPE_RESPONSE
	printf( "CPE RMM Set Event Handler, message now has %d bytes\n", sizeResp );
	{
		U8	*pResp_2 = &response[ 0 ];

		for (; pResp_2 < pResp; pResp_2++)
		  printf( "%d ", *pResp_2 );
		printf( "\n" );
	}
#endif

	iposEocSendDataStream( pRMMPerPort->pid, sizeResp, &response[ 0 ], 0, 0, NULL );
}

static void
cpeRMMEventHandler( pIposEocPerPort pRMMPerPort, U8 *pEocMsg, int msgLen )
{
	U8	msgType = pEocMsg[ EOC_TYPE_B ];

	if (msgType == IPOSRMM_SET)
	{
		cpeRMMSetEventHandler( pRMMPerPort, pEocMsg, msgLen );
	}
	else if (msgType == IPOSRMM_GET)
	{
		cpeRMMGetEventHandler( pRMMPerPort, pEocMsg, msgLen );
	}
}

static void
cpeRMMHandler( ipos_port_id pid, int status, void *pEocMsg, int msgLen )
{
	int		msgClass = iposEocGetMsgClass( pEocMsg );	
	pIposEocPerPort pRMMPerPort = iposEocGetPerPort( pid, EOC_RMM_PROTOCOL );

	if (pRMMPerPort == NULL) {
		printf( "\nError in RMM protocol handler, no per port object for b%dp%d\n",
			   pid.bmeNum, pid.portNum
		);
		return;
	}

/* EOC Protocol Version on the CPE only responds to commands from the CO */

	if (msgClass == IPOS_MSG_COMMAND)
	{
		cpeRMMEventHandler( pRMMPerPort, pEocMsg, msgLen );
	}
	else 
	  printf( "\nRMM received a message of unrecognized class %d\n", msgClass );
}
#endif

void
appRMMInit( void )
{
#ifdef VTU_O
	iposEocRegHandler(  EOC_RMM_PROTOCOL, 0, coRMMHandler );
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, REBOOT_FIRMWARE_INFO, IE_NO_INFO, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, REBOOT_STATUS_INFO, IE_NO_INFO, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, HOST_VERSION_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, BME_VERSION_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, AFE_VERSION_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, IFE_VERSION_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, LINK_STATUS, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, DUPLEX_STATUS, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, TRANSMISSION_SPEED, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, PAUSE_FRAME_STATUS, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, COUNT_PAUSE_FRAMES, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_CRC, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_LOS, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_SEF, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_LOF, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MDIO_REGISTER_VALUES, NOT_A_REGISTER, NULL, decode16Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GPIO_PIN_LIST, GPIO_PIN_NO, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GPIO_PIN_LIST, GPIO_PIN_MASK, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GPIO_PIN_LIST, GPIO_PIN_VALUE, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, BME_ID_INFO, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, IFE_ID_INFO, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, AFE_ID_INFO, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, NETWORK_INTERFACE_INFO, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, VENDOR_ID_INFO, NULL, decode32Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, MANUFATURING_ID_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, MODEL_NUMBER_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, SERIAL_NUMBER_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MODEM_ID_INFO, BOOTLOADER_VERSION_INFO, NULL, decodeString
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GET_ENET_CFG, AUTO_NEGOTIATION, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GET_ENET_CFG, ETHERNET_SPEED, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GET_ENET_CFG, ETHERNET_LINK, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GET_ENET_CFG, ETHERNET_AGC, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GET_ENET_CFG, ETHERNET_FLOW_CTRL, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GET_ENET_CFG, ETHERNET_LPBACK, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, REMOTE_EXT_STATUS, TX_POWER, NULL, decode16Bits
	);
#endif
#ifdef VTU_R
	iposEocRegHandler(  EOC_RMM_PROTOCOL, 0, cpeRMMHandler );
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, REBOOT_FIRMWARE_INFO, IE_NO_INFO, NULL, decodeOneByte
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, REBOOT_STATUS_INFO, IE_NO_INFO, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, HOST_VERSION_INFO, encodeString, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, BME_VERSION_INFO, encodeString, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, AFE_VERSION_INFO, encodeString, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, FIRMWARE_VERSION_INFO, IFE_VERSION_INFO, encodeString, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, LINK_STATUS, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, DUPLEX_STATUS, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, TRANSMISSION_SPEED, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, PAUSE_FRAME_STATUS, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ETHERNET_STATUS_INFO, COUNT_PAUSE_FRAMES, encode32Bits, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_CRC, encode32Bits, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_LOS, encode32Bits, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_SEF, encode32Bits, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, ERRORED_SECONDS_INFO, SECONDS_WITH_LOF, encode32Bits, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, REMOTE_EXT_STATUS, TX_POWER, encode16Bits, NULL
	);
#ifdef	BME_CPE_20
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MDIO_REGISTER_LIST, NOT_A_REGISTER, encode16Bits, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, SET_PHY_LOOPBACK_LEVEL, IE_NO_INFO, NULL, decodeOneByte
	);
    appEocRegIeParsers(
		EOC_RMM_PROTOCOL, GPIO_PIN_LIST, NOT_A_REGISTER, encodeOneByte, NULL
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, MDIO_REGISTER_VALUES, IE_NO_INFO, NULL, decode16Bits
	);
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, SET_AUTOENET_STATUS_RPT, IE_NO_INFO, NULL, decodeOneByte
	);
#endif
	appEocRegIeParsers(
		EOC_RMM_PROTOCOL, CLEAR_REMOTE_COUNTERS, IE_NO_INFO, NULL, decodeOneByte
	);
#endif
}

void
uiEnetPhyCfgMenu( void)
{
  int MenuSelect;
  unsigned char phyMenu[8];
  int tempChar;
  
  while (1)
  {
    phyMenu[0] = '\0';
    MenuSelect = 0;
    
    printf ("\n ------------------------------------------");
    printf ("\n Ethernet Port Specific Configuration    \n");
    printf ("\n    1) Auto-Negotiate                      ");
    printf ("\n    2) Ethernet Link Duplex                ");
    printf ("\n    3) Ethernet Speed                      ");
    printf ("\n    4) Ethernet AGC Control                ");
	printf ("\n    5) Ethernet Flow Control               ");
	printf ("\n    6) Ethernet Loopback Mode              ");
    printf ("\n    7) EXIT                                ");
    printf ("\n\n Enter Selection: ");

    gets (phyMenu);
    sscanf (phyMenu, "%i", &MenuSelect);
    
    // Break out of Ethernet PHY Configuration sub-menu
    if (MenuSelect == 7)
      break;
	if (MenuSelect == 1)
	{
	   printf ("\n Valid Options: 0 - Fixed Mode, 1 - Auto - Negotiate ON\n");
       phyMenu[0] = '\0';
	   printf(" Enter Selection: ");
	   gets( phyMenu);
	   sscanf (phyMenu,"%d", &tempChar);
       enetPhyParams.autoNego = tempChar;
	}
	if (MenuSelect == 2)
	{
	   printf ("\n Valid Options: 0 - Full Duplex, 1 - Half Duplex\n");
	   phyMenu[0] = '\0';
	   printf(" Enter Selection: ");
	   gets( phyMenu);
	   sscanf (phyMenu,"%d", &tempChar);
       enetPhyParams.enetLink = tempChar;
	}
	if (MenuSelect == 3)
	{
	  printf ("\n Valid Options: 0 - 100 Mbps, 1 - 10 Mbps\n");
	  phyMenu[0] = '\0';
	  printf(" Enter Selection: ");
	  gets( phyMenu);
	  sscanf (phyMenu,"%d", &tempChar);
      enetPhyParams.enetSpeed = tempChar;
	}
    if (MenuSelect == 4)
	{
	   printf ("\n Valid Options: 0 - OFF, 1 - ON\n");
	   phyMenu[0] = '\0';
	   printf(" Enter Selection: ");
	   gets( phyMenu);
	   sscanf (phyMenu,"%d", &tempChar);
       enetPhyParams.enetAGC = tempChar;
	}
	if (MenuSelect == 5)
	{
	   printf ("\n Valid Options: 0 - OFF, 1 - Full Duplex, 2 - Half Duplex, 3 - BOTH\n");
	   phyMenu[0] = '\0';
	   printf(" Enter Selection: ");
	   gets( phyMenu);
	   sscanf (phyMenu,"%d", &tempChar);
       enetPhyParams.enetFlowCtrl = tempChar;
	}
	if (MenuSelect == 6)
	{
	   printf ("\n Valid Options: 0 - OFF, 1 - Enet PHY Loopback, 2 - INI Loopback@xMII\n");
	   phyMenu[0] = '\0';
	   printf(" Enter Selection: ");
	   gets( phyMenu);
	   sscanf (phyMenu,"%d", &tempChar);
       enetPhyParams.enetLpBack = tempChar;
	}
  }
}
void
uiRMMMenu( void )
{
	int	rmmCmd = 0;
	char	str[ 82 ];
	

#ifdef VTU_O
	ipos_port_id    pid;
        int lpBkOption;
	int rptEnable, flowCtrlOption;

	printf( "\n   1) Get remote EOC protocol version" );
	printf( "\n   2) Get remote ethernet status" );
	printf( "\n   3) Get remote errored seconds" );
	printf( "\n   4) Get remote BME firmware version" );
	printf( "\n   5) Reboot remote system" );
	printf( "\n   6) Get Remote MDIO Registers");
	printf( "\n   7) Set Remote PHY LoopBack");
	printf( "\n   8) Get Remote GPIO Pins");
	printf( "\n   9) Get Remote Modem ID");
    printf( "\n  10) Set Ethernet Flow Control");
    printf( "\n  11) Clear Remote Counters");
	printf( "\n  12) Set Remote Ethernet Configuration");
    printf( "\n  13) Get Remote Ethernet Configuration");
	printf( "\n  14) Set Remote PHY Register");
	printf( "\n  15) Get Remote Transmit Power");
    printf( "\n  16) Set Autonomous Ethernet Status Report");
	printf( "\n  17) Get Autonomous Ethernet Status Report Flag");
	printf( "\n  18) Set Remote FPGA Register");
	printf( "\n  19) Get Remote FPGA Register");
	printf( "\n  99) Exit from menu" );
	printf( "\n\nSelect RMM option: ");
	gets( str );
	if (strlen( str ) < 1)
	{
		return;
	}
	sscanf( str,"%i", &rmmCmd ); 
	str[ 0 ] = '\0';
#define MAX_RMM_OPTIONS    20    

	if ((rmmCmd > 0 ) && (rmmCmd< MAX_RMM_OPTIONS))
	{
		if (getPortNum(&pid) < 0)
	    return;
		else
		{
			if (oampGetPortState(pid) != uSHOWTIME)
			{
				printf("\nPort %d is not in showtime.", pid.portNum);
				return;
			}
		}
	}

	switch (rmmCmd)
	{
	  	  
	  case 1:
			sprintf( &str[ 0 ], "getreoc::%d:%d;", pid.bmeNum, pid.portNum );
		break;

	  case 2:
			  sprintf( &str[ 0 ], "getrenet::%d:%d;", pid.bmeNum, pid.portNum );
		break;

	  case 3:
		     sprintf( &str[ 0 ], "getrerrs::%d:%d;", pid.bmeNum, pid.portNum );
		break;

	  case 4:
		     sprintf( &str[ 0 ], "getrver::%d:%d;", pid.bmeNum, pid.portNum );
		break;

	  case 5:
		     sprintf( &str[ 0 ], "rebootcpe::%d:%d;", pid.bmeNum, pid.portNum );
		break;

	  case 6:
		     sprintf( &str[ 0 ], "getrmdio::%d:%d;", pid.bmeNum, pid.portNum );
		break;

	  case 7:
            printf ("\n Loopback Option: 0 - Stop Loopback, 1 - Start PhyLb, 2 - Start xMII Loopback \n");
		    scanf ("%d", &lpBkOption);
            sprintf( &str[ 0 ], "setrphylb::%d:%d:%d;", pid.bmeNum, pid.portNum, lpBkOption );
		break;
	  case 8:
		     sprintf( &str[ 0 ], "getrgpio::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  case 9:
             sprintf( &str[ 0 ], "getrmodid::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  case 10:
             printf("\n  0) Flow Control OFF");
		     printf("\n  1) Full Duplex ON");
		     printf("\n  2) Half Duplex ON");
		     printf("\n  3) Both Full and Half Duplex ON");
             printf( "\nSelect Flow Control option: ");
		     scanf ("%d", &flowCtrlOption);
             sprintf( &str[ 0 ], "seteflow::%d:%d:%d;", pid.bmeNum, pid.portNum, flowCtrlOption );
		break;
	  case 11:
			  sprintf( &str[ 0 ], "clrrcntr::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  case 12:
		     uiEnetPhyCfgMenu();
		     sprintf( &str[ 0 ], "setrenetcfg::%d:%d;", pid.bmeNum, pid.portNum );
		  break;
	  case 13: 
		     sprintf( &str[ 0 ], "getrenetcfg::%d:%d;", pid.bmeNum, pid.portNum );
		  break;
	  case 14:
		      sprintf( &str[ 0 ], "setrmdio::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  case 15:
		      sprintf( &str[ 0 ], "getrtxpwr::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  case 16:
		     printf("\nSelect Enable(1)/Disable(0) [%d]: ",remEnetStatRptFlag[pid.portNum]);
             scanf ("%d", &rptEnable);
		     sprintf( &str[ 0 ], "setaenetrpt::%d:%d:%d;", pid.bmeNum, pid.portNum,rptEnable);
		     remEnetStatRptFlag[pid.portNum] = rptEnable;
		break;
	  case 17:
		     sprintf( &str[ 0 ], "getrenetrptflag::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  
          case 18:
		      sprintf( &str[ 0 ], "setrfpgamdio::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  case 19:
		     sprintf( &str[ 0 ], "getrfpgamdio::%d:%d;", pid.bmeNum, pid.portNum );
		break;
	  
	  default:
			printf( "%d: invalid choice\n", rmmCmd );
			/* Fall thru */
	  case 99:
			str[ 0 ] = '\0';
		break;
	}

	if (str[ 0 ] != '\0')
	  ReceiveTLCommand( &str[ 0 ] );
#endif
#ifdef VTU_R
	printf( "\n   1) Show local EOC protocol version" );
	printf( "\n   2) Show local ethernet status" );
	printf( "\n   3) Show local errored seconds" );
#ifdef DEBUG_DEVICE_VERSIONS
	printf( "\n   4) Show local BME firmware version" );
#endif
	printf( "\n   99) Exit from menu" );
	printf( "\n\nSelect RMM option: ");
	gets( str );
	if (strlen( str ) < 1)
	{
		return;
	}
	sscanf( str,"%i", &rmmCmd ); 
	str[ 0 ] = '\0';

	switch (rmmCmd)
	{
	  case 1:
		printf( "Local protocol version is %d, vendor ID is %s\n",
			 uiGetEocProtocolVersion(), uiGetVendorID()
		);
		break;

	  case 2:
		sprintf( &str[ 0 ], "showenet::1:1;" );
		break;

	  case 3:
		sprintf( &str[ 0 ], "showerrs::1:1;" );
		break;

#ifdef DEBUG_DEVICE_VERSIONS
	  case 4:
		sprintf( &str[ 0 ], "showdver::1;" );	/* only BME, not the port */
		break;
#endif

	  default:
			printf( "%d: invalid choice\n", rmmCmd );
			/* Fall thru */
	  case 99:
			str[ 0 ] = '\0';
		break;
	}

	if (str[ 0 ] != '\0')
	  ReceiveTLCommand( &str[ 0 ] );
#endif
}
