/*******************************************************************************
 * (c) Copyright 2015 Microsemi Corporation.  All rights reserved.
 *
 *
 *
 * SVN $Revision: $
 * SVN $Date: $
 */

#include <api_oam_sdk/common/constants/inc/mr_constants.h>
#include <api_oam_sdk/common/error_codes/inc/mr_error_codes.h>
#include <api_oam_sdk/continuity_check/inc/cc.h>
#include <api_oam_sdk/loopback/src/lb_support.h>
#include <api_oam_sdk/mep/src/mep_types.h>
#include <api_oam_sdk/metroam_hal/inc/mr_hal.h>
#include <api_oam_sdk/performance_monitoring/src/dm.h>
#include <api_oam_sdk/performance_monitoring/src/pm_config.h>
#include <api_oam_sdk/service_evc/src/svc_evc_types.h>
#include <api_oam_sdk/table_access/inc/table_access_constants.h>
#include <api_oam_sdk/table_access/inc/table_types.h>
#include <stdio.h>
#include <string.h>

#include "egl_assert.h"
#include "egl_log.h"
#include "osal.h"
extern int print_reg;
// Global Variables
#if EAGLE_INCLUDE_EFM
	extern	uint16_t	efmLMepNum;
#endif

// Static Variables
static uint16_t		log_handle				= 0;						// handle used to log messages for this module

/*
 * This function should be called at device initialisation. Its primary
 * function is to initialise logging for this module
 */
void tableAccessInit(void)
{
	log_init();

	// Get a log handle if we don't already have one
	if (log_handle == 0)
		log_handle = log_register("TBL_ACCESS");
}

/*
 * This function is used to change the lowest level severity to log for
 * this module. Values of eLOG_LEVEL_DEBUG (lowest) to eLOG_LEVEL_ERROR
 * can be selected. Levels with greater severity than eLOG_LEVEL_ERROR
 * will default to eLOG_LEVEL_ERROR since severity of eLOG_LEVEL_ERROR
 * and higher are non maskable.
 */
void setTableAccessLogLevel(log_level_t logLevel)
{
	setModuleLogLevel(log_handle,logLevel);
}

/* ----------------------------------------------------------------------------------------------------------------------------------*/
/* Define Hardware Table Read and Write functions*/
/* ----------------------------------------------------------------------------------------------------------------------------------*/

int	readRawRMepDB(uint32_t addr,uint32_t *rdPtr)
{
	mrHalRamRead((addr) + MR_BA_RMEP_DB, EXT_SRAM_SEL, rdPtr);
	return (NO_ERR);
}

int writeRawRMepDB(uint32_t addr,uint32_t wrData)
{
	mrHalRamWrite((addr) + MR_BA_RMEP_DB, EXT_SRAM_SEL, wrData);
	return (NO_ERR);
}

int readRawLMepTbl(uint32_t addr,uint32_t *rdPtr)
{
	mrHalRamRead((addr) + MR_BA_LMEP_TBL, EXT_SRAM_SEL, rdPtr);
	return (NO_ERR);
}

int writeRawLMepTbl(uint32_t addr,uint32_t wrData)
{
	mrHalRamWrite((addr) + MR_BA_LMEP_TBL, EXT_SRAM_SEL, wrData);
	return (NO_ERR);
}

int readRawRMepTbl(uint32_t addr,uint32_t *rdPtr)
{
	mrHalRamRead((addr) + MR_BA_RMEP_TBL, RMEP_MAP_RAM_SEL, rdPtr);
	return (NO_ERR);
}

int writeRawRMepTbl(uint32_t addr,uint32_t wrData)
{
	mrHalRamWrite((addr) + MR_BA_RMEP_TBL, RMEP_MAP_RAM_SEL, wrData);
	return (NO_ERR);
}

int readRawRxLMepNumRam(uint32_t addr,uint32_t *rdPtr)
{
	mrHalRamRead((addr), RX_LMEP_MAP_SEL, rdPtr);
	return (NO_ERR);
}

int writeRawRxLMepNumRam(uint32_t addr,uint32_t wrData)
{
	mrHalRamWrite((addr), RX_LMEP_MAP_SEL, wrData);
	return (NO_ERR);
}

int readRawRxLMepNumRamLower(uint32_t addr,uint32_t *rdPtr,iFace_t iFace)
{
	//mrHalRamRead(((addr)<<1) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, rdPtr);
	mrHalRamRead(((addr)<<1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, rdPtr);
	return (NO_ERR);
}

int writeRawRxLMepNumRamLower(uint32_t addr,uint32_t wrData,iFace_t iFace)
{
	//mrHalRamWrite(((addr)<<1) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, wrData);
	mrHalRamWrite(((addr)<<1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, wrData);
	return (NO_ERR);
}

int readRawRxLMepNumRamUpper(uint32_t addr,uint32_t *rdPtr,iFace_t iFace)
{
	//mrHalRamRead((((addr)<<1) + 1)  + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, rdPtr);
	mrHalRamRead((((addr)<<1) + 1)  + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, rdPtr);
	return (NO_ERR);
}

int writeRawRxLMepNumRamUpper(uint32_t addr,uint32_t wrData,iFace_t iFace)
{
	//mrHalRamWrite((((addr)<<1)+ 1) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, wrData);
	mrHalRamWrite((((addr)<<1)+ 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, wrData);
	return (NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Read an entry from the rMep Table
// -----------------------------------------------------------------------------------------------------
int readRMepTbl(uint32_t entryIdx, uint16_t *rMepID, rMepNum_t	*rMepNum)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MR_RMEP_TBL_SIZE/RMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_RMEP_TBL + (entryIdx * RMEP_ENTRY_SIZE), RMEP_MAP_RAM_SEL, &data);

	*rMepID 	= (uint16_t) ((data & RMEP_TBL_RAM_MEPID_MASK) >> RMEP_TBL_RAM_MEPID_OFFSET);
	*rMepNum 	= (rMepNum_t) ((data & RMEP_TBL_RAM_RMEP_NUM_MASK) >> RMEP_TBL_RAM_RMEP_NUM_OFFSET);

	//VRts_printf("readRMepTbl:Index 0x%0x => rMepID=%d,rMepNum=%d", entryIdx, *rMepID,*rMepNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Write an entry to the rMep Table
// -----------------------------------------------------------------------------------------------------
int writeRMepTbl(uint32_t entryIdx, uint16_t rMepID, rMepNum_t	rMepNum)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MR_RMEP_TBL_SIZE/RMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	data = ((((uint32_t) rMepID ) << RMEP_TBL_RAM_MEPID_OFFSET) & RMEP_TBL_RAM_MEPID_MASK) |
			((((uint32_t) rMepNum ) << RMEP_TBL_RAM_RMEP_NUM_OFFSET) & RMEP_TBL_RAM_RMEP_NUM_MASK);

	mrHalRamWrite(MR_BA_RMEP_TBL + (entryIdx * RMEP_ENTRY_SIZE), RMEP_MAP_RAM_SEL, data);

	//VRts_printf("writeRMepTbl:Index 0x%0x => rMepID=%d,rMepNum=%d", entryIdx, rMepID,rMepNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Check is the selected entry available for use
// -----------------------------------------------------------------------------------------------------
int isFreeRMepTbl(uint32_t entryIdx)
{
	uint32_t	data;

	// Ensure that the requested entryIdx is in the valid RAM address range
	if(entryIdx > (MR_RMEP_TBL_SIZE/RMEP_ENTRY_SIZE))
		return(false);

	mrHalRamRead(MR_BA_RMEP_TBL + (entryIdx * RMEP_ENTRY_SIZE), RMEP_MAP_RAM_SEL, &data);

	if ((data & RMEP_TBL_NOT_IN_USE_MASK) == 0)
		return(true);

	return(false);
}

// -----------------------------------------------------------------------------------------------------
// Mark the selected entry as available for use
// -----------------------------------------------------------------------------------------------------
int clrRMepTblInUse(uint32_t entryIdx)
{
	EGL_ASSERT(entryIdx <= (MR_RMEP_TBL_SIZE/RMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	mrHalRamWrite(MR_BA_RMEP_TBL + (entryIdx * RMEP_ENTRY_SIZE), RMEP_MAP_RAM_SEL, 0);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Read an entry from the RMepDB Table
// -----------------------------------------------------------------------------------------------------
int readRMepDB(uint32_t entryIdx, rMepDbTblEntry_t *rMepDbTblEntry)
{
	uint32_t	data;
	uint32_t	i;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 0, EXT_SRAM_SEL,&data);
	rMepDbTblEntry->remoteMepID = (uint16_t) ((data & RMEP_DB_RAM_MEPID_MASK)	>> RMEP_DB_RAM_MEPID_OFFSET); 				//dbEntry[31:19];
	rMepDbTblEntry->rMepIdx		= (uint16_t) ((data  & RMEP_DB_RAM_RMEP_IDX_MASK)	>> RMEP_DB_RAM_RMEP_IDX_OFFSET);

	// Read back the 2nd dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 1, EXT_SRAM_SEL,&data);
	rMepDbTblEntry->seqNum		= (data & RMEP_DB_RAM_SEQ_NUM_MASK) >> RMEP_DB_RAM_SEQ_NUM_OFFSET;												//dbEntry[63:32];

	// Read back the 3rd dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 2, EXT_SRAM_SEL,&data);
	rMepDbTblEntry->SA[0]		= 	(uint8_t) ((data  >> 24)	& 0x000000FF);			//dbEntry[111:64];
	rMepDbTblEntry->SA[1]		= 	(uint8_t) ((data  >> 16)	& 0x000000FF);
	rMepDbTblEntry->SA[2]		= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
	rMepDbTblEntry->SA[3]		= 	(uint8_t) (data 			& 0x000000FF);

	// Read back the 4th dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3, EXT_SRAM_SEL,&data);
	rMepDbTblEntry->SA[4]		= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
	rMepDbTblEntry->SA[5]		= 	(uint8_t) (data 			& 0x000000FF);

	// Read back the remaining dwords and extract the individual fields
	for (i = 0; i < RMEP_DB_RAM_TLV_DWORD_SIZE; i++)
	{
		//
		mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 4 + i, EXT_SRAM_SEL,&data);
		rMepDbTblEntry->tlv[3 + 4*i]	= 	(uint8_t) ((data  >> 24)	& 0x000000FF);	// dbEntry[535:128] ;
		rMepDbTblEntry->tlv[2 + 4*i]	= 	(uint8_t) ((data  >> 16)	& 0x000000FF);
		rMepDbTblEntry->tlv[1 + 4*i]	= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
		rMepDbTblEntry->tlv[0 + 4*i]	= 	(uint8_t) (data 			& 0x000000FF);
	}

#if 0 // REMOVED FOR V2
	// Read all the line counter values for each priority
	for (i=0;i<4;i++)
	{
		// Read the line counter values for the specified priority...
		mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 4 + RMEP_DB_RAM_TLV_DWORD_SIZE + i, EXT_SRAM_SEL,&data);
		rMepDbTblEntry->lc[i].lcNum	= (uint16_t) ((data  & RMEP_DB_RAM_PRIO_0_LC_MASK) >> RMEP_DB_RAM_PRIO_0_LC_OFFSET);
		rMepDbTblEntry->lc[i].lcValid	= (uint16_t) ((data  & RMEP_DB_RAM_PRIO_0_LC_VAL_MASK) >> RMEP_DB_RAM_PRIO_0_LC_VAL_OFFSET);
		rMepDbTblEntry->lc[i+1].lcNum	= (uint16_t) ((data  & RMEP_DB_RAM_PRIO_1_LC_MASK) >> RMEP_DB_RAM_PRIO_1_LC_OFFSET);
		rMepDbTblEntry->lc[i+1].lcValid	= (uint16_t) ((data  & RMEP_DB_RAM_PRIO_1_LC_VAL_MASK) >> RMEP_DB_RAM_PRIO_1_LC_VAL_OFFSET);
	}
#endif
	//VRts_printf("readRMepDB:Index 0x%0x (Addr=0x%0x),remoteMepID=%0x",entryIdx,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE),rMepDbTblEntry->remoteMepID);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Mark the selected entry as available for use
// Bit[127] of every DB entry is used by SW to manage free entries.
// If bit[127] = 0 the entry is in use.
// If bit[127] = 1 then the entry is available to use.
// This function writes a 1 to bit[127] to mark it as available.
// -----------------------------------------------------------------------------------------------------
int clrRMepDBInUse(uint32_t entryIdx)
{
	EGL_ASSERT(entryIdx <= MAX_NUM_MEPS,ERR_INVALID_ADDRESS);

	// Set the RMEP_DB_NOT_IN_USE_MASK bit and also set the lMep number to a null value
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3, EXT_SRAM_SEL,RMEP_DB_NOT_IN_USE_MASK | (INVALID_MEP_NUM<<RMEP_DB_RAM_RMEP_IDX_OFFSET));

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Mark the selected entry as 'in use'.
// Bit[127] of every DB entry is used by SW to manage free entries.
// If bit[127] = 0 the entry is in use.
// If bit[127] = 1 then the entry is available to use.
// This function writes a 0 to bit[127] to mark it as available.
// -----------------------------------------------------------------------------------------------------
int setRMepDBInUse(uint32_t entryIdx)
{
	uint32_t	rdData;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3,EXT_SRAM_SEL,&rdData);

	// Clear the RMEP_DB_NOT_IN_USE_MASK bit and also set the lMep number to a null value
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3,EXT_SRAM_SEL, rdData & ~RMEP_DB_NOT_IN_USE_MASK);

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// Check is the selected entry available for use.
// Bit[127] of every DB entry is used by SW to manage free entries.
// If bit[127] = 0 the entry is in use.
// If bit[127] = 1 then the entry is available to use.
// This function checks bit[127] to determine if the entry is available. It returns true of it is
// and false if it is not.
// -----------------------------------------------------------------------------------------------------
int isFreeRMepDB(uint32_t entryIdx)
{
	uint32_t	rdData;

	if (entryIdx > (MAX_NUM_RMEPS))
		return(false);

	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3, EXT_SRAM_SEL,&rdData);

	if (rdData & RMEP_DB_NOT_IN_USE_MASK)
		return(true);

	return(false);
}


// -----------------------------------------------------------------------------------------------------
// writeRMepDB(uint32_t entryIdx, rMepDbTblEntry_t *rMepDbTblEntry)
// -----------------------------------------------------------------------------------------------------
int writeRMepDB(uint32_t entryIdx, rMepDbTblEntry_t *rMepDbTblEntry)
{
	uint32_t	data;
	uint32_t	i;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// assemble the individual fields for the 1st Dword and write it
	data = 	((((uint32_t) rMepDbTblEntry->rMepIdx) << RMEP_DB_RAM_RMEP_IDX_OFFSET) & RMEP_DB_RAM_RMEP_IDX_MASK) |
			((((uint32_t) rMepDbTblEntry->remoteMepID) << RMEP_DB_RAM_MEPID_OFFSET) & RMEP_DB_RAM_MEPID_MASK);
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 0, EXT_SRAM_SEL,data);

	// assemble the individual fields for the 2nd Dword and write it
	data  = rMepDbTblEntry->seqNum;												//dbEntry[63:32]
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 1, EXT_SRAM_SEL,data);

	// assemble the individual fields for the 3rd Dword and write it
	data = (((uint32_t) rMepDbTblEntry->SA[0]) << 24) +							//dbEntry[95:64]
		(((uint32_t) rMepDbTblEntry->SA[1]) << 16) +
		(((uint32_t) rMepDbTblEntry->SA[2]) << MR_BYTE1_OFFSET) +
		((uint32_t) rMepDbTblEntry->SA[3]);
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 2, EXT_SRAM_SEL,data);

	// assemble the individual fields for the 4th Dword and write it
	data = RMEP_DB_NOT_IN_USE_MASK |				// initially set this bit...it must be cleared later
		(((uint32_t) rMepDbTblEntry->SA[4]) << MR_BYTE1_OFFSET) |
		((uint32_t) rMepDbTblEntry->SA[5]);
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3, EXT_SRAM_SEL,data);

	// assemble the individual fields for the remaining 14 Dwords and write them
	for (i = 0; i < RMEP_DB_RAM_TLV_DWORD_SIZE; i++)
	{
		data = (((uint32_t) rMepDbTblEntry->tlv[3 + 4*i]) 	<< MR_BYTE3_OFFSET) +			// dbEntry[575:128];
			(((uint32_t) rMepDbTblEntry->tlv[2 + 4*i]) 		<< MR_BYTE2_OFFSET) +
			(((uint32_t) rMepDbTblEntry->tlv[1 + 4*i]) 		<< MR_BYTE1_OFFSET) +
			((uint32_t) rMepDbTblEntry->tlv[0 + 4*i]);
		mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 4 + i, EXT_SRAM_SEL,data);
	}
#if 0 // REMOVED FOR V2
	// write all the line counter values for each priority
	for (i=0;i<4;i++)
	{
		// Read the line counter values for the specified priority...
		data = ((((uint32_t)rMepDbTblEntry->lc[i<<1].lcNum) << RMEP_DB_RAM_PRIO_0_LC_OFFSET) & RMEP_DB_RAM_PRIO_0_LC_MASK)
		| ((((uint32_t)rMepDbTblEntry->lc[i<<1].lcValid) << RMEP_DB_RAM_PRIO_0_LC_VAL_OFFSET) & RMEP_DB_RAM_PRIO_0_LC_VAL_MASK)
		| ((((uint32_t)rMepDbTblEntry->lc[(i<<1)+1].lcNum) << RMEP_DB_RAM_PRIO_1_LC_OFFSET) & RMEP_DB_RAM_PRIO_1_LC_MASK)
		| ((((uint32_t)rMepDbTblEntry->lc[(i<<1)+1].lcValid)	<< RMEP_DB_RAM_PRIO_1_LC_VAL_OFFSET) & RMEP_DB_RAM_PRIO_1_LC_VAL_MASK);
		mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 4 + RMEP_DB_RAM_TLV_DWORD_SIZE + i, EXT_SRAM_SEL,data);
	}
#endif
	//VRts_printf("writeRMepDB:Index 0x%0x => rMepID=%0x (Addr=0x%0x)",entryIdx,rMepDbTblEntry->remoteMepID,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE));
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRMepIDInRMepDB
// -----------------------------------------------------------------------------------------------------
int readRMepIDInRMepDB(uint32_t entryIdx, uint16_t *remoteMepID)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB, EXT_SRAM_SEL,&data);

	*remoteMepID = (uint16_t) ((data & RMEP_DB_RAM_MEPID_MASK) >> RMEP_DB_RAM_MEPID_OFFSET); 				//dbEntry[31:19];

	//VRts_printf("readRMepIDInRMepDB:Index 0x%0x => rMepID=%0x (Addr=0x%0x)",entryIdx,*remoteMepID,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE));
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRMepIdxInRMepDB
// -----------------------------------------------------------------------------------------------------
int readRMepIdxInRMepDB(uint32_t entryIdx, uint16_t *rMepIdx)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the 4th dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 0, EXT_SRAM_SEL,&data);
	*rMepIdx = (uint16_t) ((data  & RMEP_DB_RAM_RMEP_IDX_MASK)>> RMEP_DB_RAM_RMEP_IDX_OFFSET);

	//VRts_printf("readRMepIdxInRMepDB:Index 0x%0x => rMepIdx=%0x (Addr=0x%0x)",entryIdx,*rMepIdx,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 3);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeRMepIdxInRMepDB
// -----------------------------------------------------------------------------------------------------
int writeRMepIdxInRMepDB(uint32_t entryIdx, uint16_t rMepIdx)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the 4th dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 0, EXT_SRAM_SEL,&data);

	// update only the rMepIdx
	data &= ~RMEP_DB_RAM_RMEP_IDX_MASK;
	data |= ((((uint32_t)rMepIdx) << RMEP_DB_RAM_RMEP_IDX_OFFSET) & RMEP_DB_RAM_RMEP_IDX_MASK);
	mrHalRamWrite((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 0, EXT_SRAM_SEL,data);

	//VRts_printf("writeRMepIdxInRMepDB:Index 0x%0x => rMepIdx=0x%0x (Addr=0x%0x)",entryIdx,rMepIdx,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 3);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readSeqNumInRMepDB
// -----------------------------------------------------------------------------------------------------
int readSeqNumInRMepDB(uint32_t entryIdx, uint32_t *seqNum)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the 2nd dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 1, EXT_SRAM_SEL,&data);
	*seqNum		= ((data & RMEP_DB_RAM_SEQ_NUM_MASK) >> RMEP_DB_RAM_SEQ_NUM_OFFSET);

	//VRts_printf("readSeqNumInRMepDB:Index 0x%0x => seqNum=0x%0x (Addr=0x%0x)",*seqNum,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 1);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readSAInRMepDB
// -----------------------------------------------------------------------------------------------------
int readSAInRMepDB(uint32_t entryIdx, uint8_t SA[6])
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the 3rd dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 2, EXT_SRAM_SEL,&data);
	SA[0]		= 	(uint8_t) ((data  >> 24)	& 0x000000FF);			//dbEntry[111:64];
	SA[1]		= 	(uint8_t) ((data  >> 16)	& 0x000000FF);
	SA[2]		= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
	SA[3]		= 	(uint8_t) (data 			& 0x000000FF);

	// Read back the 4th dword and extract the individual fields
	mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 3, EXT_SRAM_SEL,&data);
	SA[4]		= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
	SA[5]		= 	(uint8_t) (data 			& 0x000000FF);
	//rMepDbTblEntry->lMepNum		= (uint16_t) ((data  >> 16)	& 0x00003FFF);			//dbEntry[125:112];

	//VRts_printf("readSAInRMepDB:Index 0x%0x => SA=%02x-%02x-%02x-%02x-%02x-%02x (Addr=0x%0x)",SA[0],SA[1],SA[2],SA[3],SA[4],SA[5],MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 2);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readTlvInRMepDB(uint32_t entryIdx, uint8_t tlv[])
// -----------------------------------------------------------------------------------------------------
int readTlvInRMepDB(uint32_t entryIdx, uint8_t tlv[56])
{
	uint32_t	data;
	uint8_t	i;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	// Read back the tlv dwords and extract the individual fields
	for (i = 0; i < (sizeof(ccmTlvByteArray_t)/4); i++)
	{
		//
		mrHalRamRead((entryIdx*DB_ENTRY_SIZE) + MR_BA_RMEP_DB + 4 + i, EXT_SRAM_SEL,&data);
		tlv[3 + 4*i]	= 	(uint8_t) ((data  >> 24)	& 0x000000FF);	// dbEntry[535:128] ;
		tlv[2 + 4*i]	= 	(uint8_t) ((data  >> 16)	& 0x000000FF);
		tlv[1 + 4*i]	= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
		tlv[0 + 4*i]	= 	(uint8_t) (data 			& 0x000000FF);
	}

	//VRts_printf("readTlvInRMepDB:Index 0x%0x => TLV=%02x (Addr=0x%0x)",*tlv,MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 4);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readProbeStore(uint8_t packetBuffer[])
// -----------------------------------------------------------------------------------------------------
int	readProbeStore(uint8_t packetBuffer[])
{
	uint32_t	data;
	int		i;

	for (i=0; i < PROBE_STORE_RAM_DEPTH; i++)
	{
		mrHalRamRead(i, PROBE_STORE_SEL,&data);
		packetBuffer[i*4+0] = (uint8_t) (data & 0xFF);
		packetBuffer[i*4+1] = (uint8_t) ((data >> 8) & 0xFF);
		packetBuffer[i*4+2] = (uint8_t) ((data >> 16) & 0xFF);
		packetBuffer[i*4+3] = (uint8_t) ((data >> 24) & 0xFF);
	}
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readXConnStore(uint8_t packetBuffer[])
// -----------------------------------------------------------------------------------------------------
int	readXConnStore(uint8_t packetBuffer[])
{
	uint32_t	data;
	int		i;

	for (i=0;i<XCONN_STORE_RAM_DEPTH;i++)
	{
		mrHalRamRead(i, XCONN_STORE_SEL,&data);
		packetBuffer[i*4+0] = (uint8_t) (data & 0xFF);
		packetBuffer[i*4+1] = (uint8_t) ((data >> 8) & 0xFF);
		packetBuffer[i*4+2] = (uint8_t) ((data >> 16) & 0xFF);
		packetBuffer[i*4+3] = (uint8_t) ((data >> 24) & 0xFF);
	}
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRMepErrStore(uint8_t packetBuffer[])
// -----------------------------------------------------------------------------------------------------
int	readRMepErrStore(uint8_t packetBuffer[])
{
	uint32_t	data;
	int		i;

	for (i=0;i<RMEP_ERR_STORE_RAM_DEPTH;i++)
	{
		mrHalRamRead(i, RMEP_ERR_STORE_SEL,&data);
		packetBuffer[i*4+0] = (uint8_t) (data & 0xFF);
		packetBuffer[i*4+1] = (uint8_t) ((data >> 8) & 0xFF);
		packetBuffer[i*4+2] = (uint8_t) ((data >> 16) & 0xFF);
		packetBuffer[i*4+3] = (uint8_t) ((data >> 24) & 0xFF);
	}
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readLMepTbl(uint32_t entryIdx, lMepTblEntry_t *lMepTblEntry)
// -----------------------------------------------------------------------------------------------------
int readLMepTbl(uint32_t entryIdx,lMepTblEntry_t *lMepTblEntry)
{
	uint32_t	data;
	uint32_t	i;

	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL + 0, EXT_SRAM_SEL,&data);
	lMepTblEntry->lMepID 	= 	(uint16_t) ((data & LMEP_RAM_MEPID_MASK) >> LMEP_RAM_MEPID_OFFSET);
	lMepTblEntry->interval 	= 	(interval_t) ((data & LMEP_RAM_INTERVAL_MASK) >> LMEP_RAM_INTERVAL_OFFSET);
	lMepTblEntry->mdNum 	= 	(mdNum_t) ((data & LMEP_RAM_MD_NUM_MASK) >> LMEP_RAM_MD_NUM_OFFSET);
	lMepTblEntry->maNum 	= 	(maNum_t) ((data & LMEP_RAM_MA_NUM_MASK) >> LMEP_RAM_MA_NUM_OFFSET);

	for (i = 0; i < (sizeof(lMepTblEntry->maid)/4); i++)
	{
		// The Maid is stored in BigEndian Format in the Table i.e.
		// bits 535:128 === B0,B1,...,B46,B47
		// In this loop the first iteration reads B44,B45,B46,B47
		// and stores them in the maid array locations 44,45,46,47 respectively
		mrHalRamRead((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL + 1 + i, EXT_SRAM_SEL,&data);
		lMepTblEntry->maid[(0 + 4*i)]	= 	(uint8_t) ((data  >> 24)	& 0x000000FF);	// tblEntry[415:32]=== B0:B47;
		lMepTblEntry->maid[(1 + 4*i)]	= 	(uint8_t) ((data  >> 16)	& 0x000000FF);
		lMepTblEntry->maid[(2 + 4*i)]	= 	(uint8_t) ((data  >> 8)	& 0x000000FF);
		lMepTblEntry->maid[(3 + 4*i)]	= 	(uint8_t) (data 			& 0x000000FF);
	}

	//VRts_printf("readLMepTbl:Index 0x%0x,lMepID=%d (Addr=0x%0x)", entryIdx,lMepTblEntry->lMepID,MR_BA_LMEP_TBL + (entryIdx * LMEP_ENTRY_SIZE));
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeLMepTbl(uint32_t uint32_t entryIdx, lMepTblEntry_t *lMepTblEntry)
// -----------------------------------------------------------------------------------------------------
int writeLMepTbl(uint32_t entryIdx,lMepTblEntry_t *lMepTblEntry)
{
	uint32_t	data;
	uint32_t	i;

	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// assemble the individual fields for the 1st Dword and write it
	data  = ((((uint32_t) lMepTblEntry->lMepID) << LMEP_RAM_MEPID_OFFSET) & LMEP_RAM_MEPID_MASK) |
		((((uint32_t) lMepTblEntry->interval) << LMEP_RAM_INTERVAL_OFFSET) & LMEP_RAM_INTERVAL_MASK) |
		((((uint32_t) lMepTblEntry->maNum) << LMEP_RAM_MA_NUM_OFFSET) & LMEP_RAM_MA_NUM_MASK) |
		((((uint32_t) lMepTblEntry->mdNum) << LMEP_RAM_MD_NUM_OFFSET) & LMEP_RAM_MD_NUM_MASK);

	mrHalRamWrite((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL + 0, EXT_SRAM_SEL,data);

	for (i = 0; i < (sizeof(lMepTblEntry->maid)/4); i++)
	{
		// The Maid is stored in BigEndian Format in the Table i.e.
		// bits 535:128 === B47,B46,...,B1,B0
		// In this loop the first iteration assembles bytes from the maid array locations 0,1,2,3
		// and writes them to the entryIdx used to store the bytes B0,B1,B2,B3 respectively
		data = (((uint32_t) lMepTblEntry->maid[(0 + 4*i)])  << 24) +	// tblEntry[415:32]=== B0:B47;
			(((uint32_t) lMepTblEntry->maid[(1 + 4*i)]) << 16) +
			(((uint32_t) lMepTblEntry->maid[(2 + 4*i)]) << 8) +
			((uint32_t) lMepTblEntry->maid[(3 + 4*i)]);

		mrHalRamWrite((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL + 1 + i, EXT_SRAM_SEL, data);
	}

	//VRts_printf("writeLMepTbl:Index 0x%0x,lMepID=%d (Addr=0x%0x)", entryIdx,lMepTblEntry->lMepID,MR_BA_LMEP_TBL + (entryIdx * LMEP_ENTRY_SIZE));
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// clrLMepInUse(uint32_t entryIdx)
// Bit[31] of every LMep entry is used by SW to manage free entries.
// If bit[31] = 0 the entry is in use.
// If bit[31] = 1 then the entry is available to use.
// This function writes a 1 to bit[31] to mark it as available.
// -----------------------------------------------------------------------------------------------------
int clrLMepInUse(uint32_t entryIdx)
{
	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// Set the RMEP_DB_NOT_IN_USE_MASK bit and also set the lMep number to a null value
	mrHalRamWrite((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL, EXT_SRAM_SEL,LMEP_NOT_IN_USE_MASK);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// setLMepInUse(uint32_t entryIdx)
// If the contents of the first D-word of the entry is not = LMEP_NOT_IN_USE_MASK the entry is in use
// There is no need to do anything to set In use as adding a mepID will ensure this is the case.
// -----------------------------------------------------------------------------------------------------
int setLMepInUse(uint32_t entryIdx)
{
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// isFreeLMep(uint32_t entryIdx)
// Bit[31] of every Local MEP entry is used by SW to manage free entries.
// If bit[31] = 0 the entry is in use.
// If bit[31] = 1 then the entry is available to use.
// This function checks bit[31] to determine if the entry is available. It returns true of it is
// and false if it is not.
// -----------------------------------------------------------------------------------------------------
int isFreeLMep(uint32_t entryIdx)
{
	uint32_t	rdData;
	if (entryIdx > (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE))
		return(false);

	mrHalRamRead((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL, EXT_SRAM_SEL,&rdData);

	if ((rdData & LMEP_NOT_IN_USE_MASK) == LMEP_NOT_IN_USE_MASK)
		return(true);

	return(false);
}

// -----------------------------------------------------------------------------------------------------
// write1stDwdInLMepTbl
// -----------------------------------------------------------------------------------------------------
int write1stDwdInLMepTbl(uint32_t entryIdx,uint16_t lMepID, ccmInterval_t interval, mdNum_t mdNum, maNum_t maNum)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// assemble the individual fields for the 1st Dword and write it
	data  = ((((uint32_t) lMepID) << LMEP_RAM_MEPID_OFFSET) & LMEP_RAM_MEPID_MASK) |
		((((uint32_t) interval) << LMEP_RAM_INTERVAL_OFFSET) & LMEP_RAM_INTERVAL_MASK) |
		((((uint32_t) maNum) << LMEP_RAM_MA_NUM_OFFSET) & LMEP_RAM_MA_NUM_MASK) |
		((((uint32_t) mdNum) << LMEP_RAM_MD_NUM_OFFSET) & LMEP_RAM_MD_NUM_MASK);


	mrHalRamWrite((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL , EXT_SRAM_SEL,data);

	//VRts_printf("write1stDwdInLMepTbl:Index 0x%0x,lMepID=%d,int=%d,mdNum=%d,maNum=%d (Addr=0x%0x)", entryIdx, lMepID,interval,mdNum,maNum, MR_BA_LMEP_TBL + (entryIdx * LMEP_ENTRY_SIZE));
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeMaidInLMepTbl(uint32_t uint32_t entryIdx, lMepTblEntry_t *lMepTblEntry)
// -----------------------------------------------------------------------------------------------------
int writeMaidInLMepTbl(uint32_t entryIdx,simpleMaid_t maid)
{
	uint32_t	data;
	uint32_t	i;

	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	for (i = 0; i < (sizeof(simpleMaid_t)/4); i++)
	{
		// The Maid is stored in BigEndian Format in the Table i.e.
		// bits 535:128 === B47,B46,...,B1,B0
		// In this loop the first iteration assembles bytes from the maid array locations 0,1,2,3
		// and writes them to the entryIdx used to store the bytes B0,B1,B2,B3 respectively
		data = (((uint32_t) maid[(0 + 4*i)])  << 24) +	// tblEntry[415:32]=== B0:B47;
			(((uint32_t) maid[(1 + 4*i)]) << 16) +
			(((uint32_t) maid[(2 + 4*i)]) << 8) +
			((uint32_t) maid[(3 + 4*i)]);

		mrHalRamWrite((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL + 1 + i, EXT_SRAM_SEL, data);
	}

	//VRts_printf("writeMaidInLMepTbl:Index 0x%0x (Addr=0x%0x)", entryIdx, MR_BA_LMEP_TBL + (entryIdx * LMEP_ENTRY_SIZE) + 1);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// readMepIDInLMepTbl
// -----------------------------------------------------------------------------------------------------
int readMepIDInLMepTbl(uint32_t entryIdx,uint16_t *lMepID)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL , EXT_SRAM_SEL,&data);

	*lMepID = (uint16_t) ((data & LMEP_RAM_MEPID_MASK) >> LMEP_RAM_MEPID_OFFSET);

	//VRts_printf("readMepIDInLMepTbl:Index 0x%0x, mepID=%d(Addr=0x%0x)", entryIdx, *lMepID, MR_BA_LMEP_TBL + (entryIdx * LMEP_ENTRY_SIZE));
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// read1stDwdInLMepTbl
// -----------------------------------------------------------------------------------------------------
int read1stDwdInLMepTbl(uint32_t entryIdx,uint16_t *lMepID, ccmInterval_t *interval, mdNum_t *mdNum,maNum_t *maNum)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MR_LMEP_TBL_SIZE/LMEP_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((entryIdx*LMEP_ENTRY_SIZE) + MR_BA_LMEP_TBL , EXT_SRAM_SEL,&data);
	*lMepID 	= 	(uint16_t) ((data & LMEP_RAM_MEPID_MASK) >> LMEP_RAM_MEPID_OFFSET);
	*interval 	= 	(ccmInterval_t) ((data & LMEP_RAM_INTERVAL_MASK) >> LMEP_RAM_INTERVAL_OFFSET);
	*mdNum 	= 	(mdNum_t) ((data & LMEP_RAM_MD_NUM_MASK) >> LMEP_RAM_MD_NUM_OFFSET);
	*maNum 	= 	(maNum_t) ((data & LMEP_RAM_MA_NUM_MASK) >> LMEP_RAM_MA_NUM_OFFSET);

	//VRts_printf("read1stDwdInLMepTbl:Index 0x%0x => lMepID=%d,int=%d,mdNum=%d,maNum=%d (Addr=0x%0x)", entryIdx, lMepID,interval,mdNum,maNum, MR_BA_LMEP_TBL + (entryIdx * LMEP_ENTRY_SIZE));
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRxLMepNumRam(entryIdx,rxLMepNumRamEntry);
// -----------------------------------------------------------------------------------------------------
int readRxLMepNumRam(uint32_t entryIdx, rxLMepNumRamEntry_t *rxLMepNumRamEntry,iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx < (MAX_NUM_MEPS * MR_LVL_ROWS),ERR_INVALID_ADDRESS);

	//mrHalRamRead((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, &data);
	mrHalRamRead((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, &data);
	rxLMepNumRamEntry->mpType 		= (valid_t) ((data & RX_LMEP_MP_TYPE_MASK) >> RX_LMEP_MP_TYPE_OFFSET);
	rxLMepNumRamEntry->idmPrio		= (uint8_t) ((data & RX_LMEP_NUM_RAM_IDM_PRIO_MASK) >> RX_LMEP_NUM_RAM_IDM_PRIO_OFFSET);
	rxLMepNumRamEntry->levelMask	= (uint8_t) ((data & RX_LMEP_NUM_LVL_MASK_MASK) >> RX_LMEP_NUM_LVL_MASK_OFFSET);

	//mrHalRamRead(((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, &data);
	mrHalRamRead(((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, &data);
	rxLMepNumRamEntry->rxLMepNum	= (lMepNum_t) ((data & RX_LMEP_NUM_RAM_LMEP_NUM_MASK) >> RX_LMEP_NUM_RAM_LMEP_NUM_OFFSET);
	rxLMepNumRamEntry->idmPmNum 	= (pmNum_t) ((data & RX_LMEP_NUM_RAM_IDM_PM_NUM_MASK) >> RX_LMEP_NUM_RAM_IDM_PM_NUM_OFFSET);

	//VRts_printf("readRxLMepNumRam:Index 0x%0x => rxLMepNum=0x%0x\n",entryIdx,rxLMepNumRamEntry->rxLMepNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeRxLMepNumRam(entryIdx,rxLMepNumRamEntry);
// -----------------------------------------------------------------------------------------------------
int writeRxLMepNumRam(uint32_t entryIdx, rxLMepNumRamEntry_t *rxLMepNumRamEntry,iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx < (MAX_NUM_MEPS * MR_LVL_ROWS),ERR_INVALID_ADDRESS);

	data = ((((uint32_t) rxLMepNumRamEntry->mpType) << RX_LMEP_MP_TYPE_OFFSET) & RX_LMEP_MP_TYPE_MASK) |
			((((uint32_t) rxLMepNumRamEntry->idmPrio) << RX_LMEP_NUM_RAM_IDM_PRIO_OFFSET) & RX_LMEP_NUM_RAM_IDM_PRIO_MASK) |
			((((uint32_t) rxLMepNumRamEntry->levelMask) << RX_LMEP_NUM_LVL_MASK_OFFSET) & RX_LMEP_NUM_LVL_MASK_MASK);
	//mrHalRamWrite((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, data);
	mrHalRamWrite((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, data);

	data = ((((uint32_t) rxLMepNumRamEntry->rxLMepNum) << RX_LMEP_NUM_RAM_LMEP_NUM_OFFSET) & RX_LMEP_NUM_RAM_LMEP_NUM_MASK) |
			((((uint32_t) rxLMepNumRamEntry->idmPmNum) << RX_LMEP_NUM_RAM_IDM_PM_NUM_OFFSET) & RX_LMEP_NUM_RAM_IDM_PM_NUM_MASK);
	//mrHalRamWrite(((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, data);
	mrHalRamWrite(((entryIdx * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, data);

	//VRts_printf("writeRxLMepNumRam:Index 0x%0x => rxLMepNum=0x%0x\n",entryIdx,rxLMepNumRamEntry->rxLMepNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// isFreeRxLMepNumRam(entryIdx);
// -----------------------------------------------------------------------------------------------------
int isFreeRxLMepNumRam(uint32_t entryIdx,iFace_t iFace)
{
	uint32_t	rdData;

	// Ensure that the requested entryIdx is in the valid RAM address range
	if(entryIdx > (MAX_NUM_MEPS))
		return(false);

	// entryIdx is x16 (each entry is 2xDword and there are 8 such entries in a cluster)
	//mrHalRamRead((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, &rdData);
	mrHalRamRead((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, &rdData);
	//ts_printf("isFreeRxLMepNumRam:MAX_NUM_MEPS=%d,RX_LMEP_NUM_ENTRY_SIZE=%d,rdData=%d\n\r",MAX_NUM_MEPS,RX_LMEP_NUM_ENTRY_SIZE,rdData);
	//ts_printf("isFreeRxLMepNumRam:RX_LMEP_MP_TYPE_MASK=%d,RX_LMEP_MP_TYPE_MASK=%d,rdData=%d\n\r",RX_LMEP_MP_TYPE_MASK,mp_tableEmpty,rdData);

if ((rdData & RX_LMEP_MP_TYPE_MASK) == mp_tableEmpty)
	{
    //VRts_printf("isFreeRxLMepNumRam:RX_LMEP_MP_TYPE_MASK=%d,RX_LMEP_MP_TYPE_MASK=%d,rdData=%d\n\r",RX_LMEP_MP_TYPE_MASK,mp_tableEmpty,rdData);

		return(true);
	}
    //return(true);
	return(false);
}

// -----------------------------------------------------------------------------------------------------
// clrRxLMepNumRamInUse(entryIdx);
// -----------------------------------------------------------------------------------------------------
int clrRxLMepNumRamInUse(uint32_t entryIdx,iFace_t iFace)
{
    EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS * MR_LVL_ROWS * RX_LMEP_NUM_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	//mrHalRamWrite((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, mp_tableEmpty);
	mrHalRamWrite((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, mp_tableEmpty);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// setRxLMepNumRamInUse(entryIdx);
// -----------------------------------------------------------------------------------------------------
int setRxLMepNumRamInUse(uint32_t entryIdx,iFace_t iFace)
{
	uint32_t	rdData;

	EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS * MR_LVL_ROWS * RX_LMEP_NUM_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	//mrHalRamRead((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, &rdData);
	mrHalRamRead((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, &rdData);
	// It's possible that the MP Type (which shares it's location with 'NOT_IN_USE') was set to
	// MIP(2'b10) or MEP(2'b01) in which case no further action is required.
	if ((rdData & RX_LMEP_MP_TYPE_MASK) == mp_tableEmpty)
	{
		rdData &= ~RX_LMEP_MP_TYPE_MASK;		// quick way to set MP type to 'mp_tableInUse' i.e. =0
		//mrHalRamWrite((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (iFace == wanPort ? RX_LMEP_NUM_TBL_PORT_0_BA : RX_LMEP_NUM_TBL_PORT_1_BA), RX_LMEP_MAP_SEL, rdData);
		mrHalRamWrite((entryIdx * (RX_LMEP_NUM_ENTRY_SIZE * MR_LVL_ROWS)) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, rdData);
	}
	return(NO_ERR);
}

void readRawVlanTbl(uint32_t entryIdx, uint32_t *rdData, iFace_t iFace)
{
	mrHalRamRead((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL, rdData);
}

void writeRawVlanTbl(uint32_t entryIdx, uint32_t wrData, iFace_t iFace)
{
	mrHalRamWrite((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL, wrData);
}

// -----------------------------------------------------------------------------------------------------
// readVlanTbl(uint32_t entryIdx, vlanTblEntry_t vlanTblEntry)
// -----------------------------------------------------------------------------------------------------
int readVlanTbl(uint32_t entryIdx, vlanTblEntry_t *vlanTblEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MR_MAX_VLANS),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL,&data);
	vlanTblEntry->evcIdx 			= 		(uint16_t) ((data & VLAN_INFO_RAM_EVC_IDX_MASK) >> VLAN_INFO_RAM_EVC_IDX_OFFSET);
	vlanTblEntry->cfmIdx 			= 		(uint8_t) ((data & VLAN_INFO_RAM_CFM_IDX_MASK) >> VLAN_INFO_RAM_CFM_IDX_OFFSET);
	vlanTblEntry->cfmValid 			= 		(uint8_t) ((data & VLAN_INFO_RAM_CFM_VALID_MASK) >> VLAN_INFO_RAM_CFM_VALID_OFFSET);
	vlanTblEntry->vlanFilt 			= 		(bool) ((data & VLAN_INFO_RAM_VLAN_FILT_MASK) >> VLAN_INFO_RAM_VLAN_FILT_OFFSET);
	vlanTblEntry->vLanFiltRestore	= 		(bool) ((data & VLAN_INFO_RAM_VLAN_FILT_RESTORE_MASK) >> VLAN_INFO_RAM_VLAN_FILT_RESTORE_OFFSET);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: readVlanTbl - Reading VLan info from location %d, port %d:\n", entryIdx, iFace);
	ts_printf("INFO: readVlanTbl - Reading VLan info from location %d, port %d:\n", entryIdx, iFace);
	ts_printf("INFO:readVlanTbl    cfmValid = %d,evcIdx = 0x%04X,vLanFilt=%d\n",vlanTblEntry->cfmValid,vlanTblEntry->evcIdx,vlanTblEntry->vlanFilt);

	ts_printf( "INFO:            cfmValid = %d,evcIdx = 0x%04X,vLanFilt=%d\n",vlanTblEntry->cfmValid,vlanTblEntry->evcIdx,vlanTblEntry->vlanFilt);
#endif
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeVlanTbl(uint32_t entryIdx, vlanTblEntry_t vlanTblEntry)
// -----------------------------------------------------------------------------------------------------
int writeVlanTbl(uint32_t entryIdx, vlanTblEntry_t *vlanTblEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= MR_MAX_VLANS,ERR_INVALID_ADDRESS);

	// assemble the individual fields for the 1st Dword and write it

	data = ((((uint32_t)vlanTblEntry->evcIdx)				<< VLAN_INFO_RAM_EVC_IDX_OFFSET) & VLAN_INFO_RAM_EVC_IDX_MASK) |
			((((uint32_t)vlanTblEntry->cfmIdx)				<< VLAN_INFO_RAM_CFM_IDX_OFFSET) & VLAN_INFO_RAM_CFM_IDX_MASK) |
			((((uint32_t)vlanTblEntry->cfmValid )			<< VLAN_INFO_RAM_CFM_VALID_OFFSET ) & VLAN_INFO_RAM_CFM_VALID_MASK) |
			((((uint32_t)vlanTblEntry->vlanFilt )			<< VLAN_INFO_RAM_VLAN_FILT_OFFSET ) & VLAN_INFO_RAM_VLAN_FILT_MASK) |
			((((uint32_t)vlanTblEntry->vLanFiltRestore )	<< VLAN_INFO_RAM_VLAN_FILT_RESTORE_OFFSET ) & VLAN_INFO_RAM_VLAN_FILT_RESTORE_MASK);
	mrHalRamWrite((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeVlanTbl - Writing VLan info to location %d, port %d:\n", entryIdx, iFace);
	ts_printf( "INFO:            cfmValid = %d,evcIdx = 0x%04X,vLanFilt=%d\n",vlanTblEntry->cfmValid,vlanTblEntry->evcIdx,vlanTblEntry->vlanFilt);
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRawVlanPortTbl(uint32_t offset, *rdData)
// -----------------------------------------------------------------------------------------------------
int readRawVlanPortTbl(uint32_t offset, uint32_t* rdData, iFace_t iFace)
{

    EGL_ASSERT(offset <= (VLAN_PORT_ENTRY_SIZE*MR_MAX_VLANS),ERR_INVALID_ADDRESS);

	// Read back the dword at the offset specified
	mrHalRamRead(offset + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL,rdData);

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeRawVlanPortTbl(uint32_t offset, *rdData)
// -----------------------------------------------------------------------------------------------------
int writeRawVlanPortTbl(uint32_t offset, uint32_t wrData, iFace_t iFace)
{

    EGL_ASSERT(offset <= (VLAN_PORT_ENTRY_SIZE*MR_MAX_VLANS),ERR_INVALID_ADDRESS);

	// Read back the dword at the offset specified
	mrHalRamWrite(offset + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL,wrData);

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeValidInVlanPortTbl
// -----------------------------------------------------------------------------------------------------
int writeValidInVlanPortTbl(uint32_t entryIdx, uint8_t cfmValid, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= MR_MAX_VLANS,ERR_INVALID_ADDRESS);

	// Read back the first dword
	mrHalRamRead((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL,&data);

	// set/clear the valid bit
	if (cfmValid == 0)
		data = data & (~VLAN_INFO_RAM_CFM_VALID_MASK);				// clear the valid bit
	else
		data = data | VLAN_INFO_RAM_CFM_VALID_MASK;					// set the valid bit

	// Write the updated valid bit back into RAM
	print_reg = 1;
	mrHalRamWrite((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeVlanTbl - Writing VLan info to location %d :\n", entryIdx);
	ts_printf( "INFO: \tcfmValid = %d\n",cfmValid);
#endif

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeClearVlanPortTbl
// -----------------------------------------------------------------------------------------------------
int writeClearVlanPortTbl(uint32_t entryIdx, iFace_t iFace)
{

    EGL_ASSERT(entryIdx <= MR_MAX_VLANS,ERR_INVALID_ADDRESS);

	// Write MR_NULL_EVC_IDX to the first dword..this clears the entry.
	// If evcIdx=MR_NULL_EVC_IDX this indicates a null value hence an empty entry
	mrHalRamWrite((entryIdx*VLAN_PORT_ENTRY_SIZE) + (iFace == wanPort ? VLAN_PORT_0_BA : VLAN_PORT_1_BA), VLAN_INFO_RAM_SEL, PORT_ASSIGNED_EVC << VLAN_INFO_RAM_EVC_IDX_OFFSET);
#ifdef DEBUG_PRINT_L2
		ts_printf( "INFO: writeVlanTbl - Clearing VLan info at location %d:\n", entryIdx);
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readTxTempl(uint32_t entryIdx, txTemplateEntry_t *txTemplateEntry, templateType_t templType,uint16_t *tlvLength,uint8_t tlv[])
// -----------------------------------------------------------------------------------------------------
int readTxTempl(uint32_t entryIdx, txTemplateEntry_t *txTemplateEntry, templateType_t templType, uint16_t *tlvLength,uint8_t tlv[])
{

	uint8_t	proHdrPres;
	uint8_t	cfmTLVPres;
	uint16_t	basePktLen;
	uint8_t	hdrDwrdLen;
	uint16_t	pktLen;			//[7:0]
	uint8_t	hdrLen;			//[3:0]
	uint8_t	sTag;
	uint8_t	cTag;
	uint32_t	data;
	uint16_t	cfmTLVLen;
	uint16_t	cfmTLVLenTmp;
	uint8_t	proHdrLen;
	uint8_t	proHdrLenTmp;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	int 	i;
	uint32_t	j;
	int		k;
#ifdef DEBUG_PRINT_L2
	ts_printf("readTxTempl:\n\r");
#endif
	switch(templType)
	{
		case CCM_TEMPL:
		{
			basePktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:	//PM_TEMPL:
		{
			basePktLen = 31;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case DELAY_TEMPL:		//PM_DMM_TEMPL:
		{
			basePktLen = 51;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LB_TEST_TLV_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEMPL:
		{
			basePktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// The 'flags' nibble is saved in the last location for the entry and must be read first
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	txTemplateEntry->cTagPresent = (uint8_t) ((data >> 2) & 0x00000001);
	txTemplateEntry->sTagPresent = (uint8_t) ((data >> 3) & 0x00000001);
	// NOTE: The following fields are expected to be formated in the follwing manner:
	//      DA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	//		SA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	// 		proHdr	 = 128'h00112233_44556677_8899aabb_ccddeeff ; where 00 is byte0, 11 is byte 1,  etc.
	//		comCfmHdr = 32'h00112233 ; where 00 is byte0, 11 is byte 1,  etc.
	j = 0;			// this is used to progress the location in memory that is read

	if (templType != CCM_TEMPL)
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + j, EXT_SRAM_SEL,&data);

		if ((templType == LOSS_TEMPL) || (templType == LB_TEMPL) || (templType == LB_TEST_TLV_TEMPL))
			txTemplateEntry->pktLen  = (uint16_t)((data & TX_TEMPL_RAM_LOSS_PKT_SIZE_MASK) >> TX_TEMPL_RAM_LOSS_PKT_SIZE_OFFSET); // extract the loss packet size

		if (templType == DELAY_TEMPL)
			txTemplateEntry->pktLen  = (uint16_t)((data & TX_TEMPL_RAM_DELAY_PKT_SIZE_MASK) >> TX_TEMPL_RAM_DELAY_PKT_SIZE_OFFSET); 		// extract the delay packet size

		txTemplateEntry->hdrLen = (uint8_t)(data >> TX_TEMPL_RAM_HDR_SIZE_OFFSET);
		j = 1;			// this is used to progress the location in memory that is read
	}

	k = 0;			// this is used to progress the cfmTLV array index to which values are written
	for (i = 0; i < CCM_TX_TEMPL_ENTRY_SIZE; i++)
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + j, EXT_SRAM_SEL, &data);
		j = j + 1;

		switch (i)
		{
			case 0:
			{
				txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
				txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
				if (templType == CCM_TEMPL)
				{
					txTemplateEntry->hdrLen = (uint8_t) ((data >> 16) & 0x0000000F);
					txTemplateEntry->pktLen = (uint16_t) ((data >> 20) & 0x00000FFF);

					cTag = txTemplateEntry->cTagPresent;
					sTag = txTemplateEntry->sTagPresent;
					hdrLen = txTemplateEntry->hdrLen;
					pktLen = txTemplateEntry->pktLen;

					proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
					proHdrLenTmp = proHdrLen;
					cfmTLVLen = pktLen - (proHdrLen *4) - (4 * sTag) - (4 * cTag) - basePktLen ;
					cfmTLVLenTmp = cfmTLVLen;
				}
				else
				{
					cTag = txTemplateEntry->cTagPresent;
					sTag = txTemplateEntry->sTagPresent;
					hdrLen = txTemplateEntry->hdrLen;
					pktLen = txTemplateEntry->pktLen;

					proHdrLen = 0;
					proHdrLenTmp = 0;
					cfmTLVLen = 0 ;
					cfmTLVLenTmp = 0;
				}

				txTemplateEntry->proHdrLen = proHdrLen;
				*tlvLength = cfmTLVLen;
				txTemplateEntry->cfmTLVLen = cfmTLVLen;

				break;
			}

			case 1:
			{
				txTemplateEntry->DA[2] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->DA[3] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->DA[4] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->DA[5] = (uint8_t) (data & 0x000000FF);
				break;
			}

			case 2:
			{
				txTemplateEntry->SA[0] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->SA[1] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->SA[2] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->SA[3] = (uint8_t) (data & 0x000000FF);
				break;
			}

			case 3:
			{
				if (!sTag && !cTag) // i.e. 2'b00
				{
					txTemplateEntry->SA[4] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->SA[5] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->eType[1] = (uint8_t) (data & 0x000000FF);
					i = i + 2;
					if (!proHdrPres)
						i = i + 4;
				}
				else if (!sTag && cTag) // i.e. 2'b01
				{
					txTemplateEntry->SA[4] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->SA[5] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->cTagTPID[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->cTagTPID[1] = (uint8_t) (data & 0x000000FF);
				}
				else if (sTag && !cTag) // i.e. 2'b10
				{
					txTemplateEntry->SA[4] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->SA[5] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->sTagTPID[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->sTagTPID[1] = (uint8_t) (data & 0x000000FF);
				}
				else //(sTag && cTag)  i.e. 2'b11
				{
					txTemplateEntry->SA[4] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->SA[5] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->sTagTPID[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->sTagTPID[1] = (uint8_t) (data & 0x000000FF);
				}
				break;
			}

			case 4:
			{
				if (!sTag && !cTag) // i.e. 2'b00
				{
					// nothing
				}
				else if (!sTag && cTag) // i.e. 2'b01
				{
					txTemplateEntry->cTagVID[0] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->cTagVID[1] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->eType[1] = (uint8_t) (data & 0x000000FF);
					i = i + 1;
					if (!proHdrPres)
						i = i + 4;
				}
				else if (sTag && !cTag) // i.e. 2'b10
				{
					txTemplateEntry->sTagVID[0] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->sTagVID[1] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->eType[1] = (uint8_t) (data & 0x000000FF);
					i = i + 1;
					if (!proHdrPres)
						i = i + 4;
				}
				else //(sTag && cTag)  i.e. 2'b11
				{
					txTemplateEntry->sTagVID[0] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->sTagVID[1] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->cTagTPID[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->cTagTPID[1] = (uint8_t) (data & 0x000000FF);
				}
				break;
			}
			case 5:
			{
				if (!sTag && !cTag) // i.e. 2'b00
				{
					//nothing
				}
				else if (!sTag && cTag) // i.e. 2'b01
				{
					//nothing
				}
				else if (sTag && !cTag) // i.e. 2'b10
				{
					//nothing
				}
				else //(sTag && cTag)  i.e. 2'b11
				{
					txTemplateEntry->cTagVID[0] = (uint8_t) ((data >> 24) & 0x000000FF);
					txTemplateEntry->cTagVID[1] = (uint8_t) ((data >> 16) & 0x000000FF);
					txTemplateEntry->eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
					txTemplateEntry->eType[1] = (uint8_t) (data & 0x000000FF);
					if (!proHdrPres)
						i = i + 4;
				}
				break;
			}

			case 6:
			{
				txTemplateEntry->proHdr[0] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->proHdr[1] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->proHdr[2] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->proHdr[3] = (uint8_t) (data & 0x000000FF);
				proHdrLen = proHdrLen - 1;
				if (proHdrLen == 0)
					i = 9;
				break;
			}

			case 7:
			{
				txTemplateEntry->proHdr[4] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->proHdr[5] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->proHdr[6] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->proHdr[7] = (uint8_t) (data & 0x000000FF);
				proHdrLen = proHdrLen - 1;
				if (proHdrLen == 0)
					i = 9;
				break;
			}

			case 8:
			{
				txTemplateEntry->proHdr[8] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->proHdr[9] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->proHdr[10] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->proHdr[11] = (uint8_t) (data & 0x000000FF);
				proHdrLen = proHdrLen - 1;
				if (proHdrLen == 0)
					i = 9;
				break;
			}

			case 9:
			{
				txTemplateEntry->proHdr[12] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->proHdr[13] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->proHdr[14] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->proHdr[15] = (uint8_t) (data & 0x000000FF);
				break;
			}

			case 10:
			{
				txTemplateEntry->comCfmHdr[0] = (uint8_t) ((data >> 24) & 0x000000FF);
				txTemplateEntry->comCfmHdr[1] = (uint8_t) ((data >> 16) & 0x000000FF);
				txTemplateEntry->comCfmHdr[2] = (uint8_t) ((data >> 8) & 0x000000FF);
				txTemplateEntry->comCfmHdr[3] = (uint8_t) (data & 0x000000FF);
				break;
			}

			case 11:
			{
				if ((templType == DELAY_TEMPL) || (templType == LOSS_TEMPL))		// PM packets end here!
				{
					txTemplateEntry->mepID = (uint16_t)(data >> 16);
					i = 24;
				}
				else
				{
					txTemplateEntry->seqNum = data;
				}

				break;
			}

			case 12:
			{
				if (templType == LB_TEMPL)
				{
					// Loopback is a special case since it's TLV can be 1500 bytes!!
					if (cfmTLVPres)
					{
						if (cfmTLVLen >= 4)
						{
							tlv[k+0] = (uint8_t) ((data >> 24) & 0x000000FF);
							tlv[k+1] = (uint8_t) ((data >> 16) & 0x000000FF);
							tlv[k+2] = (uint8_t) ((data >> 8) & 0x000000FF);
							tlv[k+3] = (uint8_t) (data & 0x000000FF);
							cfmTLVLen = cfmTLVLen - 4;
							k += 4;
							i = 11;
						}
						else
						{
							switch (cfmTLVLen)
							{
								case 3:
								{
									tlv[k+0] = (uint8_t) ((data >> 24) & 0x000000FF);
									tlv[k+1] = (uint8_t) ((data >> 16) & 0x000000FF);
									tlv[k+2] = (uint8_t) ((data >> 8) & 0x000000FF);
									txTemplateEntry->eTLV = (uint8_t) (data & 0x000000FF);
									break;
								}

								case 2:
								{
									tlv[k+0] = (uint8_t) ((data >> 24) & 0x000000FF);
									tlv[k+1] = (uint8_t) ((data >> 16) & 0x000000FF);
									txTemplateEntry->eTLV = (uint8_t) ((data >> 8) & 0x000000FF);
									break;
								}

								case 1:
								{
									tlv[k+0] = (uint8_t) ((data >> 24) & 0x000000FF);
									txTemplateEntry->eTLV = (uint8_t) ((data >> 16) & 0x000000FF);
									break;
								}

								case 0:
								{
									txTemplateEntry->eTLV = (uint8_t) ((data >> 24) & 0x000000FF);
									break;
								}
							}
							cfmTLVLen = 0;
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
						}
					}
					else
					{
						data = (((uint32_t) txTemplateEntry->eTLV) << 24);
						i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
					}

				}
				else
				{
					if (cfmTLVPres)
					{
						if (cfmTLVLen >= 2)
						{
							txTemplateEntry->mepID = (uint16_t) ((data >> 16) & 0x0000FFFF);
							tlv[0] = (uint8_t) ((data >> 8) & 0x000000FF);
							tlv[1] = (uint8_t) (data & 0x000000FF);
							cfmTLVLen = cfmTLVLen - 2;
						}
						else
						{
							txTemplateEntry->mepID = (uint16_t) ((data >> 16) & 0x0000FFFF);
							tlv[0] = (uint8_t) ((data >> 8) & 0x000000FF);
							txTemplateEntry->eTLV = (uint8_t) (data & 0x000000FF);
							cfmTLVLen = cfmTLVLen - 1;
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
						}
					}
					else
					{
						txTemplateEntry->mepID = (uint16_t) ((data >> 16) & 0x0000FFFF);
						txTemplateEntry->eTLV = (uint8_t) ((data >> 8) & 0x000000FF);
						i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
					}
				}
				break;
			}

			case 13:
			case 14:
			case 15:
			case 16:
			case 17:
			case 18:
			case 19:
			case 20:
			case 21:
			case 22:
			case 23:
			case 24:
			{
				if (cfmTLVLen >= 4)
				{
					tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
					tlv[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
					tlv[4+k] = (uint8_t) ((data >> 8) & 0x000000FF);
					tlv[5+k] = (uint8_t) (data & 0x000000FF);
					cfmTLVLen = cfmTLVLen - 4;
				}
				else
				{
					switch (cfmTLVLen)
					{
						case 3:
						{
							tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
							tlv[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
							tlv[4+k] = (uint8_t) ((data >> 8) & 0x000000FF);
							txTemplateEntry->eTLV = (uint8_t) (data & 0x000000FF);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}

						case 2:
						{
							tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
							tlv[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
							txTemplateEntry->eTLV = (uint8_t) ((data >> 8) & 0x000000FF);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}

						case 1:
						{
							tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
							txTemplateEntry->eTLV = (uint8_t) ((data >> 16) & 0x000000FF);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}

						case 0:
						{
							txTemplateEntry->eTLV = (uint8_t) ((data >> 24) & 0x000000FF);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}
					}
				}
				k = k + 4;
				break;
			}

			case 25:
			{
				switch (cfmTLVLen)
				{
					case 3:
					{
						tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
						tlv[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
						tlv[4+k] = (uint8_t) ((data >> 8) & 0x000000FF);
						txTemplateEntry->eTLV = (uint8_t) (data & 0x000000FF);
						break;
					}

					case 2:
					{
						tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
						tlv[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
						txTemplateEntry->eTLV = (uint8_t) ((data >> 8) & 0x000000FF);
						break;
					}

					case 1:
					{
						tlv[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
						txTemplateEntry->eTLV = (uint8_t) ((data >> 16) & 0x000000FF);
						break;
					}

					case 0:
					{
						txTemplateEntry->eTLV = (uint8_t) ((data >> 24) & 0x000000FF);
						break;
					}
				}
				break;
			}
		}
	}
#ifdef DEBUG_PRINT_L2
	ts_printf("readTxTempl:Index 0x%0x=>lMepID = 0x%0x, seqNum = %d,(Addr = 0x%0x):\n",entryIdx,txTemplateEntry->mepID,txTemplateEntry->seqNum,txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeTxTempl(uint32_t entryIdx, txTemplateEntry_t *txTemplateEntry, templateType_t templType)
// -----------------------------------------------------------------------------------------------------
int writeTxTempl(uint32_t entryIdx, txTemplateEntry_t *txTemplateEntry, templateType_t templType, uint16_t tlvLength,uint8_t tlv[])
{

	uint8_t		proHdrPres;
	uint8_t		cfmTLVPres;
	uint8_t		hdrDwrdLen;		//[3:0]
	uint16_t	pktLen;			//[7:0]
	uint8_t		hdrLen;			//[3:0]
	uint32_t	data;
	uint8_t		sTag;
	uint8_t		cTag;
	uint8_t		proHdrLen;
	uint16_t	cfmTLVLen;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	int 		i;
	uint32_t	j;
	int			k;
#ifdef DEBUG_PRINT_L2
	ts_printf("writeTxTempl:\n\r");
#endif
	switch(templType)
	{
		case CCM_TEMPL:
		{
#ifdef DEBUG_PRINT_L2
		    ts_printf("writeTxTempl:CCM_TEMPL\n\r");
#endif
			// Da(6) + SA(6) + tyep(2) + CFM Hdr(4) + seqNo(4) + mepId(2) + maid(48) + counts(16) + End TLV(1)
			pktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:	//PM_TEMPL:
		{
			pktLen = 31;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case DELAY_TEMPL:	//PM_DMM_TEMPL:
		{
			pktLen = 51;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			// Da(6) + SA(6) + tyep(2) + CFM Hdr(4) + seqNo(4) + End TLV(1)
			pktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	sTag = txTemplateEntry->sTagPresent;
	cTag = txTemplateEntry->cTagPresent;
	proHdrLen = 0;	//txTemplateEntry->proHdrLen;
	proHdrPres = 0;
	cfmTLVLen = tlvLength;

	if (sTag)	// only affects CCMs
	{
		hdrDwrdLen = hdrDwrdLen + 1;
		pktLen += 4;
	}

	if (cTag)	// only affects CCMs
	{
		hdrDwrdLen = hdrDwrdLen + 1;
		pktLen += 4;
	}

	hdrLen = hdrDwrdLen;

	if ((templType != CCM_TEMPL))
		cfmTLVPres = 0;							// for PM packets there is never a TLV
	else
	{
		// if the CFM TLV length is not zero then the TLV field is present
		if (cfmTLVLen > 0)
		{
			cfmTLVPres = 1;
			pktLen = pktLen + cfmTLVLen;
		}
		else
		{
			cfmTLVPres = 0;
		}
	}

	j = 0;			// this is used to progress the location in memory that is read

	if (templType != CCM_TEMPL)
	{
		// If the txTemplateEntry->pktLen is ever greater than MAX_LBM_PKT_SIZE - 4 then
		// the HW can cause a lockup by sending an infinte length packet. Limit absolute max packet size
		if(txTemplateEntry->pktLen > (MAX_LBM_PKT_SIZE - 4))
			txTemplateEntry->pktLen = MAX_LBM_PKT_SIZE - 4;

		// Don't allow creation of a packet less than 64 bytes (i.e. 60 + CRC)
		if (txTemplateEntry->pktLen < 60)
			txTemplateEntry->pktLen = 60;

		// This is a restriction due to the construction of a DMM template with two Tags
		// Pkt sizes of 65 bytes cannot be constructed using a TLV to pad it and padding
		// with 0's is not legal for packets > 64...so 65 byte pkts are rounded down to
		// 64 byte pkts
		// NOTE: packet sizes below exclude the crc so: 61 = 65 - CRC
		if (templType == DELAY_TEMPL)
			if ((txTemplateEntry->pktLen == 61) && sTag && cTag)
				txTemplateEntry->pktLen = 60;

		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + j, EXT_SRAM_SEL,&data);
		if (templType == DELAY_TEMPL)
		{
			data &= TX_TEMPL_RAM_LOSS_PKT_SIZE_MASK; // preserve the loss packet size
			data |= (((uint32_t) hdrLen) << TX_TEMPL_RAM_HDR_SIZE_OFFSET) | ((((uint32_t) txTemplateEntry->pktLen) << TX_TEMPL_RAM_DELAY_PKT_SIZE_OFFSET) & TX_TEMPL_RAM_DELAY_PKT_SIZE_MASK);
		}
		if ((templType == LOSS_TEMPL) || (templType == LB_TEMPL) || (templType == LB_TEST_TLV_TEMPL))
		{
			data &= TX_TEMPL_RAM_DELAY_PKT_SIZE_MASK; // preserve the delay packet size
			// update the header length and the delay packet size
			data |= (((uint32_t) hdrLen) << TX_TEMPL_RAM_HDR_SIZE_OFFSET) | ((((uint32_t) txTemplateEntry->pktLen) << TX_TEMPL_RAM_LOSS_PKT_SIZE_OFFSET) & TX_TEMPL_RAM_LOSS_PKT_SIZE_MASK);
		}
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + j, EXT_SRAM_SEL,data);
		j = 1;			// this is used to progress the location in memory that is read
	}
	// NOTE: The following fields are expected to be formated in the following manner:
	//      DA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	//		SA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	// 		proHdr	 = 128'h00112233_44556677_8899aabb_ccddeeff ; where 00 is byte0, 11 is byte 1,  etc.
	//		comCfmHdr = 32'h00112233 ; where 00 is byte0, 11 is byte 1,  etc.
	k = 0;			// this is used to progress the cfmTLV array index to which values are written
	for (i = 0; i < CCM_TX_TEMPL_ENTRY_SIZE; i++)
	{
		switch (i)
		{
			case 0:
			{
				if (templType == CCM_TEMPL)
				{
				data = (((uint32_t) pktLen) << 20) +
					(((uint32_t) hdrLen) << 16) +
					(((uint32_t) txTemplateEntry->DA[0]) << 8) +
					(((uint32_t) txTemplateEntry->DA[1]));
				}
				else
				{
					data = (((uint32_t) txTemplateEntry->DA[0]) << 8) +
						(((uint32_t) txTemplateEntry->DA[1]));
				}
				break;
			}

			case 1:
			{
				data = (((uint32_t) txTemplateEntry->DA[2]) << 24) +
					(((uint32_t) txTemplateEntry->DA[3]) << 16) +
					(((uint32_t) txTemplateEntry->DA[4]) << 8) +
					(((uint32_t) txTemplateEntry->DA[5]));
				break;
			}

			case 2:
			{
				data = (((uint32_t) txTemplateEntry->SA[0]) << 24) +
					(((uint32_t) txTemplateEntry->SA[1]) << 16) +
					(((uint32_t) txTemplateEntry->SA[2]) << 8) +
					(((uint32_t) txTemplateEntry->SA[3]));
				break;
			}

			case 3:
			{
				if (!sTag && !cTag) // i.e. 2'b00
				{
					data = (((uint32_t) txTemplateEntry->SA[4]) << 24) +
						(((uint32_t) txTemplateEntry->SA[5]) << 16) +
						(((uint32_t) txTemplateEntry->eType[0]) << 8) +
						(((uint32_t) txTemplateEntry->eType[1]));
					i = i + 2;
					if (!proHdrPres)
						i = i + 4;
				}
				else if (!sTag && cTag) // i.e. 2'b01
				{
					data = (((uint32_t) txTemplateEntry->SA[4]) << 24) +
						(((uint32_t) txTemplateEntry->SA[5]) << 16) +
						(((uint32_t) txTemplateEntry->cTagTPID[0]) << 8) +
						(((uint32_t) txTemplateEntry->cTagTPID[1]));
				}
				else if (sTag && !cTag) // i.e. 2'b10
				{
					data = (((uint32_t) txTemplateEntry->SA[4]) << 24) +
						(((uint32_t) txTemplateEntry->SA[5]) << 16) +
						(((uint32_t) txTemplateEntry->sTagTPID[0]) << 8) +
						(((uint32_t) txTemplateEntry->sTagTPID[1]));
				}
				else //(sTag && cTag)  i.e. 2'b11
				{
					data = (((uint32_t) txTemplateEntry->SA[4]) << 24) +
						(((uint32_t) txTemplateEntry->SA[5]) << 16) +
						(((uint32_t) txTemplateEntry->sTagTPID[0]) << 8) +
						(((uint32_t) txTemplateEntry->sTagTPID[1]));
				}
				break;
			}

			case 4:
			{
				if (!sTag && !cTag) // i.e. 2'b00
				{
					data = 0;
				}
				else if (!sTag && cTag) // i.e. 2'b01
				{
					data = (((uint32_t) txTemplateEntry->cTagVID[0]) << 24) +
						(((uint32_t) txTemplateEntry->cTagVID[1]) << 16) +
						(((uint32_t) txTemplateEntry->eType[0]) << 8) +
						(((uint32_t) txTemplateEntry->eType[1]));
					i = i + 1;
					if (!proHdrPres)
						i = i + 4;
				}
				else if (sTag && !cTag) // i.e. 2'b10
				{
					data = (((uint32_t) txTemplateEntry->sTagVID[0]) << 24) +
						(((uint32_t) txTemplateEntry->sTagVID[1]) << 16) +
						(((uint32_t) txTemplateEntry->eType[0]) << 8) +
						(((uint32_t)txTemplateEntry-> eType[1]));
					i = i + 1;
					if (!proHdrPres)
						i = i + 4;
				}
				else //(sTag && cTag)  i.e. 2'b11
				{
					data = (((uint32_t) txTemplateEntry->sTagVID[0]) << 24) +
						(((uint32_t) txTemplateEntry->sTagVID[1]) << 16) +
						(((uint32_t) txTemplateEntry->cTagTPID[0]) << 8) +
						(((uint32_t) txTemplateEntry->cTagTPID[1]));
				}
				break;
			}
			case 5:
			{
				if (!sTag && !cTag) // i.e. 2'b00
				{
					data = 0;
				}
				else if (!sTag && cTag) // i.e. 2'b01
				{
					data = 0;
				}
				else if (sTag && !cTag) // i.e. 2'b10
				{
					data = 0;
				}
				else //(sTag && cTag)  i.e. 2'b11
				{
					data = (((uint32_t) txTemplateEntry->cTagVID[0]) << 24) +
						(((uint32_t) txTemplateEntry->cTagVID[1]) << 16) +
						(((uint32_t) txTemplateEntry->eType[0]) << 8) +
						(((uint32_t) txTemplateEntry->eType[1]));
					if (!proHdrPres)
						i = i + 4;
				}
				break;
			}

			case 6:
			{
				data = (((uint32_t) txTemplateEntry->proHdr[0]) << 24) +
					(((uint32_t) txTemplateEntry->proHdr[1]) << 16) +
					(((uint32_t) txTemplateEntry->proHdr[2]) << 8) +
					(((uint32_t) txTemplateEntry->proHdr[3]));
				proHdrLen = proHdrLen - 1;
				if (proHdrLen == 0)
					i = 9;
				break;
			}

			case 7:
			{
				data = (((uint32_t) txTemplateEntry->proHdr[4]) << 24) +
					(((uint32_t) txTemplateEntry->proHdr[5]) << 16) +
					(((uint32_t) txTemplateEntry->proHdr[6]) << 8) +
					(((uint32_t) txTemplateEntry->proHdr[7]));
				proHdrLen = proHdrLen - 1;
				if (proHdrLen == 0)
					i = 9;
				break;
			}

			case 8:
			{
				data = (((uint32_t) txTemplateEntry->proHdr[8]) << 24) +
					(((uint32_t) txTemplateEntry->proHdr[9]) << 16) +
					(((uint32_t) txTemplateEntry->proHdr[10]) << 8) +
					(((uint32_t) txTemplateEntry->proHdr[11]));
				proHdrLen = proHdrLen - 1;
				if (proHdrLen == 0)
					i = 9;
				break;
			}

			case 9:
			{
				data = (((uint32_t) txTemplateEntry->proHdr[12]) << 24) +
					(((uint32_t) txTemplateEntry->proHdr[13]) << 16) +
					(((uint32_t) txTemplateEntry->proHdr[14]) << 8) +
					(((uint32_t) txTemplateEntry->proHdr[15]));
				break;
			}

			case 10:
			{
				data = (((uint32_t) txTemplateEntry->comCfmHdr[0]) << 24) +
					(((uint32_t) txTemplateEntry->comCfmHdr[1]) << 16) +
					(((uint32_t) txTemplateEntry->comCfmHdr[2]) << 8) +
					(((uint32_t) txTemplateEntry->comCfmHdr[3]));
				break;
			}

			case 11:
			{
				if ((templType == DELAY_TEMPL) || (templType == LOSS_TEMPL))		// PM packets end here!
				{
					data = ((uint32_t)(txTemplateEntry->mepID)) << 16;
					i = 24;
				}
				else
					data = txTemplateEntry->seqNum;

				break;
			}

			case 12:
			{
				if (templType == LB_TEMPL)
				{
					// DATA TLV => type = 3
					// The TLV length is: packet Length - (base + tags + hdr + type(1) + length(2))
					data = 0x03000000 | (((uint32_t)(txTemplateEntry->pktLen - (pktLen + 3))) << 8);
					i = 24;
				}
				else if (templType == LB_TEST_TLV_TEMPL)
				{
					// Test TLV => type = 32 (0x10)
					// The TLV length is: packet Length - (base + tags + hdr + type(1) + length(2))
					data = 0x20000000 | (((uint32_t)(txTemplateEntry->pktLen - (pktLen + 3))) << 8);
					i = 24;
/*
					// Loopback is a special case since it's TLV can be 1500 bytes!!
					if (cfmTLVPres)
					{
						if (cfmTLVLen >= 4)
						{
							data = (((uint32_t) tlv[k+0]) << 24) +
								(((uint32_t) tlv[k+1]) << 16) +
								(((uint32_t) tlv[k+2]) << 8) +
								(((uint32_t) tlv[k+3]));
							cfmTLVLen = cfmTLVLen - 4;
							k += 4;
							i = 11;
						}
						else
						{
							switch (cfmTLVLen)
							{
								case 3:
								{
									data = (((uint32_t) tlv[k+0]) << 24) +
										(((uint32_t) tlv[k+1]) << 16) +
										(((uint32_t) tlv[k+2]) << 8) +
										(((uint32_t) txTemplateEntry->eTLV));
									break;
								}

								case 2:
								{
									data = (((uint32_t) tlv[k+0]) << 24) +
										(((uint32_t) tlv[k+1]) << 16) +
										(((uint32_t) txTemplateEntry->eTLV) << 8);
									break;
								}

								case 1:
								{
									data = (((uint32_t) tlv[k+0]) << 24) +
										(((uint32_t) txTemplateEntry->eTLV) << 16);
									break;
								}

								case 0:
								{
									data = (((uint32_t) txTemplateEntry->eTLV) << 24);
									break;
								}
							}
							cfmTLVLen = 0;
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
						}
					}
					else
					{
						data = (((uint32_t) txTemplateEntry->eTLV) << 24);
						i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
					}
*/
				}
				else
				{
					if (cfmTLVPres)
					{
						if (cfmTLVLen >= 2)
						{
							data = (((uint32_t) txTemplateEntry->mepID) << 16) +
								(((uint32_t) tlv[0]) << 8) +
								(((uint32_t) tlv[1]));
							cfmTLVLen = cfmTLVLen - 2;
						}
						else
						{
							data = (((uint32_t) txTemplateEntry->mepID) << 16) +
								(((uint32_t) tlv[0]) << 8) +
								(((uint32_t) txTemplateEntry->eTLV));
							cfmTLVLen = cfmTLVLen - 1;
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
						}
					}
					else
					{
						data = (((uint32_t) txTemplateEntry->mepID) << 16) +
							(((uint32_t) txTemplateEntry->eTLV) << 8);
						i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
					}
				}
				break;
			}

			case 13:
			case 14:
			case 15:
			case 16:
			case 17:
			case 18:
			case 19:
			case 20:
			case 21:
			case 22:
			case 23:
			case 24:
			{
				if (cfmTLVLen >= 4)
				{
					data = (((uint32_t) tlv[2+k]) << 24) +
						(((uint32_t) tlv[3+k]) << 16) +
						(((uint32_t) tlv[4+k]) << 8) +
						(((uint32_t) tlv[5+k]));
					cfmTLVLen = cfmTLVLen - 4;
				}
				else
				{
					switch (cfmTLVLen)
					{
						case 3:
						{
							data = (((uint32_t) tlv[2+k]) << 24) +
								(((uint32_t) tlv[3+k]) << 16) +
								(((uint32_t) tlv[4+k]) << 8) +
								(((uint32_t) txTemplateEntry->eTLV));
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}

						case 2:
						{
							data = (((uint32_t) tlv[2+k]) << 24) +
								(((uint32_t) tlv[3+k]) << 16) +
								(((uint32_t) txTemplateEntry->eTLV) << 8);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}

						case 1:
						{
							data = (((uint32_t) tlv[2+k]) << 24) +
								(((uint32_t) txTemplateEntry->eTLV) << 16);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}

						case 0:
						{
							data = (((uint32_t) txTemplateEntry->eTLV) << 24);
							i = CCM_TX_TEMPL_ENTRY_SIZE - 1;
							break;
						}
					}
				}
				k = k + 4;
				break;
			}

			case 25:
			{

				switch (cfmTLVLen)
				{
					case 3:
					{
						data = (((uint32_t) tlv[2+k]) << 24) +
							(((uint32_t) tlv[3+k]) << 16) +
							(((uint32_t) tlv[4+k]) << 8) +
							(((uint32_t) txTemplateEntry->eTLV));
						break;
					}

					case 2:
					{
						data = (((uint32_t) tlv[2+k]) << 24) +
							(((uint32_t) tlv[3+k]) << 16) +
							(((uint32_t) txTemplateEntry->eTLV) << 8);
						break;
					}

					case 1:
					{
						data = (((uint32_t) tlv[2+k]) << 24) +
							(((uint32_t) txTemplateEntry->eTLV) << 16);
						break;
					}

					case 0:
					{
						data = (((uint32_t) txTemplateEntry->eTLV) << 24);
						break;
					}
				}
				i = CCM_TX_TEMPL_ENTRY_SIZE;
				break;
			}
		}
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + j, EXT_SRAM_SEL,data);
		j = j + 1;
	}

	// The 'flags' nibble is saved in the last location for the entry and must be updated.
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	data = 	(data & 0xFFFFFF00) |	((((uint32_t) txTemplateEntry->sTagPresent) << 3) +
					(((uint32_t) txTemplateEntry->cTagPresent) << 2) +
					(((uint32_t) proHdrPres) << 1) +
					(((uint32_t) cfmTLVPres) << 0));

	mrHalRamWrite(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL,data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "readTxTempl:Index 0x%0x=>lMepID = 0x%ox, seqNum = %d,(Addr = 0x%0x):\n",entryIdx,txTemplateEntry->mepID,txTemplateEntry->seqNum,txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readDAInTxTempl
// -----------------------------------------------------------------------------------------------------
int readDAInTxTempl(uint32_t entryIdx, uint8_t	DA[6], templateType_t templType)
{

	uint32_t	data;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint8_t	startRow;

	switch(templType)
	{
		case CCM_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_CCM_TEMPL;
			tblEntrySize = CCM_TX_TEMPL_ENTRY_SIZE;
			startRow = 0;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			startRow = 1;
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			startRow = 1;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			startRow = 1;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// NOTE: The following fields are expected to be formated in the following manner:
	//      DA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	//		SA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	// 		proHdr	 = 128'h00112233_44556677_8899aabb_ccddeeff ; where 00 is byte0, 11 is byte 1,  etc.
	//		comCfmHdr = 32'h00112233 ; where 00 is byte0, 11 is byte 1,  etc.

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow, EXT_SRAM_SEL, &data);

	DA[1] = (uint8_t) (data & 0x000000FF);
	DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
	//txTemplateEntry->hdrLen = (uint8_t) ((data >> 16) & 0x0000000F);
	//cfmTLVPres = (uint8_t) ((data >> 20) & 0x00000001);
	//proHdrPres = (uint8_t) ((data >> 21) & 0x00000001);
	//txTemplateEntry->cTag = (uint8_t) ((data >> 22) & 0x00000001);
	//txTemplateEntry->sTag = (uint8_t) ((data >> 23) & 0x00000001);
	//txTemplateEntry->pktLen = (uint8_t) ((data >> 24) & 0x000000FF);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 1, EXT_SRAM_SEL, &data);

	DA[2] = (uint8_t) ((data >> 24) & 0x000000FF);
	DA[3] = (uint8_t) ((data >> 16) & 0x000000FF);
	DA[4] = (uint8_t) ((data >> 8) & 0x000000FF);
	DA[5] = (uint8_t) (data & 0x000000FF);
#ifdef DEBUG_PRINT_L2
	ts_printf( "readDAInTxTempl:Index 0x%0x=> DA=0x02X02X02X02X02X02X (Addr=0x%0x):\n",entryIdx,DA[0],DA[1],DA[2],DA[3],DA[4],DA[5],txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readSAInTxTempl
// -----------------------------------------------------------------------------------------------------
int readSAInTxTempl(uint32_t entryIdx, uint8_t	SA[6], templateType_t templType)
{

	uint32_t	data;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint8_t		startRow=1;

	switch(templType)
	{
		case CCM_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_CCM_TEMPL;
			tblEntrySize = CCM_TX_TEMPL_ENTRY_SIZE;
			startRow = 0;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
		    EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_LB_TEMPL;
			tblEntrySize = LB_TX_TEMPL_ENTRY_SIZE;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// NOTE: The following fields are expected to be formated in the follwing manner:
	//      DA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	//		SA[47:0] = 48'h001122334455 ; where 00 is byte0, 11 is byte 1,  etc.
	// 		proHdr	 = 128'h00112233_44556677_8899aabb_ccddeeff ; where 00 is byte0, 11 is byte 1,  etc.
	//		comCfmHdr = 32'h00112233 ; where 00 is byte0, 11 is byte 1,  etc.

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 2, EXT_SRAM_SEL, &data);

	SA[0] = (uint8_t) ((data >> 24) & 0x000000FF);
	SA[1] = (uint8_t) ((data >> 16) & 0x000000FF);
	SA[2] = (uint8_t) ((data >> 8) & 0x000000FF);
	SA[3] = (uint8_t) (data & 0x000000FF);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 3, EXT_SRAM_SEL, &data);

	SA[4] = (uint8_t) ((data >> 24) & 0x000000FF);
	SA[5] = (uint8_t) ((data >> 16) & 0x000000FF);
#ifdef DEBUG_PRINT_L2
	ts_printf( "readSAInTxTempl:Index 0x%0x=> SA=0x02X02X02X02X02X02X (Addr=0x%0x):\n",entryIdx,SA[0],SA[1],SA[2],SA[3],SA[4],SA[5],txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readTagsInTxTempl
// -----------------------------------------------------------------------------------------------------
int readTagsInTxTempl(
	uint32_t 		entryIdx,
	tag_t			*outerTag,
	tag_t			*innerTag,
	uint8_t			eType[2],
	templateType_t	templType)
{
	uint8_t		inTagPres;
	uint8_t		outTagPres;
	uint32_t	data;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t		startRow=1;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			startRow=0;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	innerTag->present = (uint8_t) ((data >> 2) & 0x00000001);
	outerTag->present = (uint8_t) ((data >> 3) & 0x00000001);

	inTagPres = innerTag->present;
	outTagPres = outerTag->present;

	if (!outTagPres && !inTagPres) // i.e. 2'b00
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 3, EXT_SRAM_SEL, &data);
		eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		eType[1] = (uint8_t) (data & 0x000000FF);
	}

	if (inTagPres) // i.e. 2'b01
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 4, EXT_SRAM_SEL, &data);
		eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		eType[1] = (uint8_t) (data & 0x000000FF);
		data = data >> 16;
		innerTag->vidEntry.vlan = (uint16_t) (data & MR_TAG_VLAN_MASK);
		innerTag->vidEntry.de	= (uint8_t) ((data & MR_TAG_DE_MASK) >> MR_TAG_DE_OFFSET);
		innerTag->vidEntry.prio	= (uint8_t) ((data & MR_TAG_PRIO_MASK) >> MR_TAG_PRIO_OFFSET);
	}

	if (outTagPres && inTagPres)
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 5, EXT_SRAM_SEL, &data);
		eType[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		eType[1] = (uint8_t) (data & 0x000000FF);
		data = data >> 16;
		outerTag->vidEntry.vlan = (uint16_t) (data & MR_TAG_VLAN_MASK);
		outerTag->vidEntry.de	= (uint8_t) ((data & MR_TAG_DE_MASK) >> MR_TAG_DE_OFFSET);
		outerTag->vidEntry.prio	= (uint8_t) ((data & MR_TAG_PRIO_MASK) >> MR_TAG_PRIO_OFFSET);
	}

	EGL_ASSERT((outTagPres && !inTagPres),1);		// Illegal to have an outer tag and no inner tag
#ifdef DEBUG_PRINT_L2
	ts_printf( "readTagsInTxTempl:Index 0x%0x=>TBD (Addr=0x%0x):\n",entryIdx,txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

int writeTagsInTxTempl(
	uint32_t 		entryIdx,
	tagEntry_t		*outerTag,
	tagEntry_t		*innerTag,
	uint8_t			eType[2],
	templateType_t	templType)
{
	uint8_t		outTagPres;
	uint8_t		inTagPres;
	uint32_t	data;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t		startRow=1;
	print_reg = 1;
	switch(templType)
	{
		case CCM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			startRow=0;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	inTagPres = (uint8_t) ((data >> 2) & 0x00000001);
	outTagPres = (uint8_t) ((data >> 3) & 0x00000001);

	EGL_ASSERT (inTagPres == innerTag->present,1);  // Adding or removing a tag is not supported
	EGL_ASSERT (outTagPres == outerTag->present,1);	// Adding or removing a tag is not supported
	EGL_ASSERT((!(outTagPres && !inTagPres)),1);	// Illegal to have an outer tag and no inner tag

	if (!outTagPres && !inTagPres) // i.e. 2'b00
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 3, EXT_SRAM_SEL, &data);
		data &= 0xFFFF0000;
		data |= (((uint32_t) eType[0]) << 8) | ((uint32_t) eType[1]);
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 3, EXT_SRAM_SEL, data);
	}

	if (inTagPres) // i.e. 2'b01
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 4, EXT_SRAM_SEL, &data);
		data = (uint32_t) (innerTag->tagVal);
		data = data << 16;
		data |= (((uint32_t) eType[0]) << 8) | ((uint32_t) eType[1]);
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 4, EXT_SRAM_SEL, data);
	}

	if (outTagPres && inTagPres)
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 5, EXT_SRAM_SEL, &data);
		data = (uint32_t) (outerTag->tagVal);
		data = data << 16;
		data |= (((uint32_t) eType[0]) << 8) | ((uint32_t) eType[1]);
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 5, EXT_SRAM_SEL, data);
	}
#ifdef DEBUG_PRINT_L2
	ts_printf( "writeTagsInTxTempl:Index 0x%0x=>TBD (Addr=0x%0x):\n",entryIdx,txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}
// -----------------------------------------------------------------------------------------------------
// readSeqNumInTxTempl
// -----------------------------------------------------------------------------------------------------
int readSeqNumInTxTempl(uint32_t entryIdx, uint32_t	*seqNum, templateType_t templType)
{

	uint8_t	proHdrPres;
	uint8_t	cfmTLVPres;
	uint16_t	pktLen;			//[7:0]
	uint8_t	hdrLen;			//[3:0]
	uint8_t	sTag;
	uint8_t	cTag;
	uint32_t	data;
	uint16_t	cfmTLVLen;
	uint16_t	cfmTLVLenTmp;
	uint8_t	proHdrLen;
	uint8_t	proHdrLenTmp;
	uint8_t	offset2Field;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t	hdrDwrdLen;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			pktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_CCM_TEMPL;
			tblEntrySize = CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			// There is no Sequence Number in PM frames
			return(ERR_INVALID_PARM_VALUE);
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			// There is no Sequence Number in PM frames
			return(ERR_INVALID_PARM_VALUE);
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			pktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	cTag = (uint8_t) ((data >> 2) & 0x00000001);
	sTag = (uint8_t) ((data >> 3) & 0x00000001);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + 0, EXT_SRAM_SEL, &data);
	if (templType != CCM_TEMPL)
	{
		if (templType == LOSS_TEMPL)
			pktLen  = (uint16_t)((data >> 14) & 0x00003FFF); // extract the loss packet size

		if (templType == DELAY_TEMPL)
			pktLen  = (uint16_t)(data & 0x00003FFF); 		// extract the delay packet size

		hdrLen = (uint8_t)(data >> 28);
	}
	else
	{
		//txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
		//txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		hdrLen 		= (uint8_t) ((data >> 16) & 0x0000000F);
		pktLen 		= (uint8_t) ((data >> 20) & 0x00000FFF);
	}

	proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
	proHdrLenTmp = proHdrLen;
	cfmTLVLen = pktLen - (proHdrLen *4) - (4 * sTag) - (4 * cTag) - 89 ;
	cfmTLVLenTmp = cfmTLVLen;

	if (!sTag && !cTag) // i.e. 2'b00
		offset2Field = 5;
	else if (!sTag && cTag) // i.e. 2'b01
		offset2Field = 6;
	else if (sTag && !cTag) // i.e. 2'b10
		offset2Field = 6;
	else //(sTag && cTag)  i.e. 2'b11
		offset2Field = 7;

	if (templType != CCM_TEMPL)
		offset2Field++;

	if(proHdrPres)
		offset2Field += proHdrLen;

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);

	*seqNum = data;
#ifdef DEBUG_PRINT_L2
	ts_printf( "readSeqNumInTxTempl:Index 0x%0x=> seqNum=%d (Addr=0x%0x):\n",entryIdx,*seqNum, txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeTlvInTxTempl
// -----------------------------------------------------------------------------------------------------
int writeTlvInTxTempl(uint32_t entryIdx, uint16_t tlvLength, uint8_t tlv[], templateType_t templType)
{
	uint8_t		proHdrPres;
	uint8_t		cfmTLVPres;
	uint16_t	pktLen;			//[7:0]
	uint8_t		hdrLen;			//[3:0]
	uint8_t		sTag;
	uint8_t		cTag;
	uint32_t	data;
	uint16_t	k;
	uint16_t	cfmTLVLen;
	uint8_t		proHdrLen;
	uint8_t		proHdrLenTmp;
	uint8_t		offset2Field;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t		hdrDwrdLen;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			pktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:	//PM_TEMPL:
		{
			pktLen = 31;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case DELAY_TEMPL:	//PM_DMM_TEMPL:
		{
			pktLen = 51;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr		= MR_BA_PM_TEMPL;
			tblEntrySize		= PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= PM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			pktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	cTag = (uint8_t) ((data >> 2) & 0x00000001);
	sTag = (uint8_t) ((data >> 3) & 0x00000001);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + 0, EXT_SRAM_SEL, &data);
	if (templType != CCM_TEMPL)
	{
		if (templType == LOSS_TEMPL)
			pktLen  = (uint16_t)((data >> 14) & 0x00003FFF); // extract the loss packet size

		if (templType == DELAY_TEMPL)
			pktLen  = (uint16_t)(data & 0x00003FFF); 		// extract the delay packet size

		hdrLen = (uint8_t)(data >> 28);
	}
	else
	{
		//txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
		//txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		hdrLen 		= (uint8_t) ((data >> 16) & 0x0000000F);
	}

	proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
	proHdrLenTmp = proHdrLen;

	// If it's a CCM re-calc the new pktLen based on the new tlvLength
	// For Non-CCM templates the size doesn't change
	if (templType == CCM_TEMPL)
		pktLen 		=  pktLen + proHdrLen + (4 * sTag) + (4 * cTag) + tlvLength;

	if (!sTag && !cTag) // i.e. 2'b00
		offset2Field = 6;
	else if (!sTag && cTag) // i.e. 2'b01
		offset2Field = 7;
	else if (sTag && !cTag) // i.e. 2'b10
		offset2Field = 7;
	else //(sTag && cTag)  i.e. 2'b11
		offset2Field = 8;

	if (templType != CCM_TEMPL)
		offset2Field++;

	if(proHdrPres)
		offset2Field += proHdrLen;

	if (tlvLength >= 4)
	{
		// This assumes the tlvLength is at least 4 bytes (type(1),length(2),value(1+)
		cfmTLVLen = tlvLength;

		// the first 2 bytes share the location with the 16 bits of the sequence no.
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);
		data &= 0xFFFF0000;
		data |= (((uint32_t) tlv[0]) << 8) + (((uint32_t) tlv[1]));
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);

		cfmTLVLen = cfmTLVLen - 2;
		k = 0;
		while (cfmTLVLen>0)
		{
			// write the remaining bytes as dwords or residue...
			offset2Field++;
			if (cfmTLVLen >= 4)
			{
				data = (((uint32_t) tlv[2+k]) << 24) +
					(((uint32_t) tlv[3+k]) << 16) +
					(((uint32_t) tlv[4+k]) << 8) +
					(((uint32_t) tlv[5+k]));
				cfmTLVLen -= 4;
				k += 4;
				mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);
				if(cfmTLVLen == 0)
				{	// The TLV has been added but now add the end TLV...
					offset2Field++;
					mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);
					data &= 0x00FFFFFF;
					mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);
				}
			}
			else
			{
				switch (cfmTLVLen)
				{
					case 3:
					{
						data = (((uint32_t) tlv[2+k]) << 24) +
							(((uint32_t) tlv[3+k]) << 16) +
							(((uint32_t) tlv[4+k]) << 8);
						break;
					}

					case 2:
					{
						data = (((uint32_t) tlv[2+k]) << 24) +
							(((uint32_t) tlv[3+k]) << 16);
						break;
					}

					case 1:
					{
						data = (((uint32_t) tlv[2+k]) << 24);
						break;
					}

					case 0:
					{
						data = 0;
						break;
					}
				}
				cfmTLVLen -= cfmTLVLen;
				mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);
			}
		}
		cfmTLVPres = 1;
	}
	else
	{
		// If the length passed in is zero then make sure to erase the old TLV
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);
		data &= 0xFFFF0000;
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);
		cfmTLVPres = 0;
	}

	if (templType == CCM_TEMPL)
	{
		// Make sure to update the template length for CCM template
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr, EXT_SRAM_SEL, &data);
		data &= 0x0000FFFF;
		data |= (((uint32_t) pktLen) << 20) + (((uint32_t) hdrLen) << 16);
		mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr, EXT_SRAM_SEL, data);
	}

	// The 'flags' nibble is saved in the last location for the entry and must be updated.
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	data = 	(data & 0xFFFFFFFE) | ((uint32_t) cfmTLVPres);
	mrHalRamWrite(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL,data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "writeTlvInTxTempl:Index 0x%0x (Addr=0x%0x):\n",entryIdx,txTemplBaseAddr + (entryIdx * tblEntrySize) + offset2Field);
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeSeqNumInTxTempl
// -----------------------------------------------------------------------------------------------------
int writeSeqNumInTxTempl(uint32_t entryIdx, uint32_t seqNum, templateType_t templType)
{

	uint8_t		proHdrPres;
	uint8_t		cfmTLVPres;
	uint16_t	pktLen;			//[7:0]
	uint8_t		hdrLen;			//[3:0]
	uint8_t		sTag;
	uint8_t		cTag;
	uint32_t	data;
	uint16_t	cfmTLVLen;
	uint16_t	cfmTLVLenTmp;
	uint8_t		proHdrLen;
	uint8_t		proHdrLenTmp;
	uint8_t		offset2Field;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t		hdrDwrdLen;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			pktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			// There is no Sequence Number in PM frames
			return(ERR_INVALID_PARM_VALUE);
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			// There is no Sequence Number in PM frames
			return(ERR_INVALID_PARM_VALUE);
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			pktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	cTag = (uint8_t) ((data >> 2) & 0x00000001);
	sTag = (uint8_t) ((data >> 3) & 0x00000001);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + 0, EXT_SRAM_SEL, &data);
	if (templType != CCM_TEMPL)
	{
		if (templType == LOSS_TEMPL)
			pktLen  = (uint16_t)((data >> 14) & 0x00003FFF); // extract the loss packet size

		if (templType == DELAY_TEMPL)
			pktLen  = (uint16_t)(data & 0x00003FFF); 		// extract the delay packet size

		hdrLen = (uint8_t)(data >> 28);
	}
	else
	{
		//txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
		//txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		hdrLen 		= (uint8_t) ((data >> 16) & 0x0000000F);
		pktLen 		= (uint8_t) ((data >> 20) & 0x00000FFF);
	}

	proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
	proHdrLenTmp = proHdrLen;
	cfmTLVLen = pktLen - (proHdrLen *4) - (4 * sTag) - (4 * cTag) - 89 ;
	cfmTLVLenTmp = cfmTLVLen;

	if (!sTag && !cTag) // i.e. 2'b00
		offset2Field = 5;
	else if (!sTag && cTag) // i.e. 2'b01
		offset2Field = 6;
	else if (sTag && !cTag) // i.e. 2'b10
		offset2Field = 6;
	else //(sTag && cTag)  i.e. 2'b11
		offset2Field = 7;

	if (templType != CCM_TEMPL)
		offset2Field++;

	if(proHdrPres)
		offset2Field += proHdrLen;

	mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, seqNum);
#ifdef DEBUG_PRINT_L2
	ts_printf( "writeSeqNumInTxTempl:Index 0x%0x=> seqNum=%d (physical entryIdx = 0x%0x):\n",entryIdx,seqNum, txTemplBaseAddr + (entryIdx * tblEntrySize) + offset2Field);
#endif
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeRdiInTxTempl
// -----------------------------------------------------------------------------------------------------
int writeRdiInTxTempl(uint32_t entryIdx, rdiVal_t rdi, templateType_t templType)
{

	uint8_t		proHdrPres;
	uint8_t		cfmTLVPres;
	uint16_t	pktLen;			//[7:0]
	uint8_t		hdrLen;			//[3:0]
	uint8_t		sTag;
	uint8_t		cTag;
	uint32_t	data;
	uint16_t	cfmTLVLen;
	uint16_t	cfmTLVLenTmp;
	uint8_t		proHdrLen;
	uint8_t		proHdrLenTmp;
	uint8_t		offset2Field;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t		hdrDwrdLen;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			pktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			// There is no Rdi bit in PM frames
			return(ERR_INVALID_PARM_VALUE);
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			// There is no Rdi bit in PM frames
			return(ERR_INVALID_PARM_VALUE);
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			pktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	cTag = (uint8_t) ((data >> 2) & 0x00000001);
	sTag = (uint8_t) ((data >> 3) & 0x00000001);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + 0, EXT_SRAM_SEL, &data);
	if (templType != CCM_TEMPL)
	{
		if (templType == LOSS_TEMPL)
			pktLen  = (uint16_t)((data >> 14) & 0x00003FFF); // extract the loss packet size

		if (templType == DELAY_TEMPL)
			pktLen  = (uint16_t)(data & 0x00003FFF); 		// extract the delay packet size

		hdrLen = (uint8_t)(data >> 28);
	}
	else
	{
		//txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
		//txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		hdrLen 		= (uint8_t) ((data >> 16) & 0x0000000F);
		pktLen 		= (uint8_t) ((data >> 20) & 0x00000FFF);
	}

	proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
	proHdrLenTmp = proHdrLen;
	cfmTLVLen = pktLen - (proHdrLen *4) - (4 * sTag) - (4 * cTag) - 89 ;
	cfmTLVLenTmp = cfmTLVLen;

	if (!sTag && !cTag) // i.e. 2'b00
		offset2Field = 4;
	else if (!sTag && cTag) // i.e. 2'b01
		offset2Field = 5;
	else if (sTag && !cTag) // i.e. 2'b10
		offset2Field = 5;
	else //(sTag && cTag)  i.e. 2'b11
		offset2Field = 6;

	if (templType != CCM_TEMPL)
		offset2Field++;

	if(proHdrPres)
		offset2Field += proHdrLen;

	// Read the common CFM header, which includes the RDI bit.
	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);

	data &= ~0x8000;						// first clear the RDI bit
	data |= ((uint32_t) (rdi & 0x1)) << 15;	// Then set it to the new value

	// write back the updated common CFM header with the new RDI value
	print_reg = 1;
	//ts_printf( "INFO: writeRdiInTxTempl\n\r");
	mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeRdiInTxTempl:Index 0x%0x=> rdi=%d (Addr=0x%0x):\n",entryIdx,rdi,txTemplBaseAddr + (entryIdx * tblEntrySize) + offset2Field);
#endif
	return(NO_ERR);
}

int writeCcmIntervalInTxTempl(uint32_t entryIdx, ccmInterval_t ccmInterval)
{

	uint8_t		proHdrPres;
	uint8_t		cfmTLVPres;
	uint16_t	pktLen;			//[7:0]
	uint8_t		hdrLen;			//[3:0]
	uint8_t		sTag;
	uint8_t		cTag;
	uint32_t	data;
	uint16_t	cfmTLVLen;
	uint16_t	cfmTLVLenTmp;
	uint8_t		proHdrLen;
	uint8_t		proHdrLenTmp;
	uint8_t		offset2Field;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t		hdrDwrdLen;

	pktLen = 89;			// This is the base packet length it can grow from this depending on other options
	hdrDwrdLen = 6;

	EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

	txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
	tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
	tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	cTag = (uint8_t) ((data >> 2) & 0x00000001);
	sTag = (uint8_t) ((data >> 3) & 0x00000001);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + 0, EXT_SRAM_SEL, &data);

	//txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
	//txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
	hdrLen 		= (uint8_t) ((data >> 16) & 0x0000000F);
	pktLen 		= (uint8_t) ((data >> 20) & 0x00000FFF);

	proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
	proHdrLenTmp = proHdrLen;
	cfmTLVLen = pktLen - (proHdrLen *4) - (4 * sTag) - (4 * cTag) - 89 ;
	cfmTLVLenTmp = cfmTLVLen;

	if (!sTag && !cTag) // i.e. 2'b00
		offset2Field = 4;
	else if (!sTag && cTag) // i.e. 2'b01
		offset2Field = 5;
	else if (sTag && !cTag) // i.e. 2'b10
		offset2Field = 5;
	else //(sTag && cTag)  i.e. 2'b11
		offset2Field = 6;

	if(proHdrPres)
		offset2Field += proHdrLen;

	// Read the common CFM header, which includes the ccm Interval value.
	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);

	data &= ~0x00000700;						// first clear the current value
	data |= (((uint32_t) (ccmInterval & 0x7)) << 8);	// Then set it to the new value

	// write back the updated common CFM header with the new RDI value
	print_reg = 1;
	//ts_printf( "INFO: writeCcmIntervalInTxTempl:\n\r");
	mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeCcmIntervalInTxTempl:Index 0x%0x=> ccm Interval=%d (Addr=0x%0x):\n",entryIdx,ccmInterval,txTemplBaseAddr + (entryIdx * tblEntrySize) + offset2Field);
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeDAInTxTempl
// -----------------------------------------------------------------------------------------------------
int writeDAInTxTempl(uint32_t entryIdx, macAddress_t macAddress, templateType_t templType)
{

	uint32_t	data;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint32_t	startRow;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_CCM_TEMPL;
			tblEntrySize = CCM_TX_TEMPL_ENTRY_SIZE;
			startRow = 0;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			startRow = 1;
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			startRow = 1;
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			startRow = 1;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow, EXT_SRAM_SEL, &data);
	data &= 0xFFFF0000;		// keep the upper two bytes
	data |= (((uint32_t)macAddress[0]) << 8) | ((uint32_t)macAddress[1]);
	mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow, EXT_SRAM_SEL, data);

	data = (((uint32_t)macAddress[2]) << 24) | (((uint32_t)macAddress[3]) << 16) | (((uint32_t)macAddress[4]) << 8) | ((uint32_t)macAddress[5]);

	//ts_printf( "INFO: writeDAInTxTempl:\n\r");
	print_reg = 1;
	mrHalRamWrite((entryIdx * tblEntrySize) + txTemplBaseAddr + startRow + 1, EXT_SRAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeDAInTxTempl:Index 0x%0x=> DA=%02x:%02x:%02x:%02x:%02x:%02x (Addr=0x%0x):\n",entryIdx,
			macAddress[0],macAddress[1],macAddress[2],macAddress[3],macAddress[4],macAddress[5],
			txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readCfmTlvInTxTempl
// -----------------------------------------------------------------------------------------------------
int readCfmTlvInTxTempl(uint32_t entryIdx, uint8_t	cfmTLV[],uint16_t *tlvLength, templateType_t templType)
{

	uint8_t		proHdrPres;
	uint8_t		cfmTLVPres;
	uint16_t	pktLen;			//[7:0]
	uint8_t		hdrLen;			//[3:0]
	uint8_t		sTag;
	uint8_t		cTag;
	uint32_t	data;
	uint16_t	cfmTLVLen;
	uint16_t	cfmTLVLenTmp;
	uint8_t		proHdrLen;
	uint8_t		proHdrLenTmp;
	uint8_t		offset2Field;
	uint32_t	txTemplBaseAddr;
	uint16_t	tblEntrySize;
	uint16_t	tblPrivateEntryIdx;
	uint8_t 	hdrDwrdLen;
	int			k;
	int			i;

	switch(templType)
	{
		case CCM_TEMPL:
		{
			pktLen = 89;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= ((MAX_NUM_MEPS)),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_CCM_TEMPL;
			tblEntrySize 		= CCM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= CCM_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		case LOSS_TEMPL:         //PM_TEMPL:
		{
			pktLen = 31;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= 0;			// not used but assigned here to avoid compile waring
			break;
		}
		case DELAY_TEMPL:         //PM_DMM_TEMPL:
		{
			pktLen = 51;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 5;

			EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

			txTemplBaseAddr = MR_BA_PM_TEMPL;
			tblEntrySize = PM_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= 0;			// not used but assigned here to avoid compile waring
			break;
		}
		case LB_TEMPL:
		case TST_TEMPL:					// This should never be passed it as a param!
		case LB_TEST_TLV_TEMPL:
		{
			pktLen = 23;			// This is the base packet length it can grow from this depending on other options
			hdrDwrdLen = 6;

			EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

			txTemplBaseAddr 	= MR_BA_LB_TEMPL;
			tblEntrySize 		= LB_TX_TEMPL_ENTRY_SIZE;
			tblPrivateEntryIdx 	= LB_TX_TEMPL_HIGHEST_OSET;
			break;
		}
		default:
		{
			// This is an invalid option
			return(ERR_INVALID_PARM_VALUE);
		}
	}

	// read the flags located in the last address for the entry
	mrHalRamRead(((entryIdx) * tblEntrySize)  + txTemplBaseAddr + tblPrivateEntryIdx, EXT_SRAM_SEL, &data);
	cfmTLVPres = (uint8_t) ((data >> 0) & 0x00000001);
	proHdrPres = (uint8_t) ((data >> 1) & 0x00000001);
	cTag = (uint8_t) ((data >> 2) & 0x00000001);
	sTag = (uint8_t) ((data >> 3) & 0x00000001);

	mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + 0, EXT_SRAM_SEL, &data);
	if (templType != CCM_TEMPL)
	{
		if (templType == LOSS_TEMPL)
			pktLen  = (uint16_t)((data >> 14) & 0x00003FFF); // extract the loss packet size

		if (templType == DELAY_TEMPL)
			pktLen  = (uint16_t)(data & 0x00003FFF); 		// extract the delay packet size

		hdrLen = (uint8_t)(data >> 28);
	}
	else
	{
		//txTemplateEntry->DA[1] = (uint8_t) (data & 0x000000FF);
		//txTemplateEntry->DA[0] = (uint8_t) ((data >> 8) & 0x000000FF);
		hdrLen 		= (uint8_t) ((data >> 16) & 0x0000000F);
		pktLen 		= (uint8_t) ((data >> 20) & 0x00000FFF);
	}

	proHdrLen = hdrLen - hdrDwrdLen - (1 * sTag) - (1 * cTag);
	proHdrLenTmp = proHdrLen;
	cfmTLVLen = pktLen - (proHdrLen *4) - (4 * sTag) - (4 * cTag) - 89 ;
	cfmTLVLenTmp = cfmTLVLen;

	if (!sTag && !cTag) // i.e. 2'b00
		offset2Field = 6;
	else if (!sTag && cTag) // i.e. 2'b01
		offset2Field = 7;
	else if (sTag && !cTag) // i.e. 2'b10
		offset2Field = 7;
	else //(sTag && cTag)  i.e. 2'b11
		offset2Field = 8;

	if (templType != CCM_TEMPL)
		offset2Field++;

	if(proHdrPres)
		offset2Field += proHdrLen;

	if (cfmTLVPres)
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field, EXT_SRAM_SEL, &data);

		if (cfmTLVLen >= 2)
		{
			//mepID = (uint16_t) ((data >> 16) & 0x0000FFFF);
			cfmTLV[0] = (uint8_t) ((data >> 8) & 0x000000FF);
			cfmTLV[1] = (uint8_t) (data & 0x000000FF);
			cfmTLVLen = cfmTLVLen - 2;
		}
		else
		{
			//mepID = (uint16_t) ((data >> 16) & 0x0000FFFF);
			cfmTLV[0] = (uint8_t) ((data >> 8) & 0x000000FF);
			//eTLV = (uint8_t) (data & 0x000000FF);
			cfmTLVLen = cfmTLVLen - 1;
		}
	}

	i = 1;
	k = 0;
	while (cfmTLVLen > 0)
	{
		mrHalRamRead((entryIdx * tblEntrySize) + txTemplBaseAddr + offset2Field + i, EXT_SRAM_SEL, &data);

		if (cfmTLVLen >= 4)
		{
			cfmTLV[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
			cfmTLV[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
			cfmTLV[4+k] = (uint8_t) ((data >> 8) & 0x000000FF);
			cfmTLV[5+k] = (uint8_t) (data & 0x000000FF);
			cfmTLVLen = cfmTLVLen - 4;
			k += 4;
		}
		else
		{
			switch (cfmTLVLen)
			{
				case 3:
				{
					cfmTLV[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
					cfmTLV[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
					cfmTLV[4+k] = (uint8_t) ((data >> 8) & 0x000000FF);
					//txTemplateEntry->eTLV = (uint8_t) (data & 0x000000FF);
					cfmTLVLen = 0;
					break;
				}

				case 2:
				{
					cfmTLV[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
					cfmTLV[3+k] = (uint8_t) ((data >> 16) & 0x000000FF);
					//txTemplateEntry->eTLV = (uint8_t) ((data >> 8) & 0x000000FF);
					cfmTLVLen = 0;
					break;
				}

				case 1:
				{
					cfmTLV[2+k] = (uint8_t) ((data >> 24) & 0x000000FF);
					//txTemplateEntry->eTLV = (uint8_t) ((data >> 16) & 0x000000FF);
					cfmTLVLen = 0;
					break;
				}
			}
		}

		i++;
	}

	if (cfmTLVLenTmp == 0)
	{
		// No Tlv present
		cfmTLV[0] = 0;		// mark the TLV byte array as empty...can;t be sure calling function checks tlvLength!
	}
	*tlvLength = cfmTLVLenTmp;
#ifdef DEBUG_PRINT_L2
	ts_printf( "readCfmTlvInTxTempl:Index 0x%0x (Addr=0x%0x):\n",entryIdx,txTemplBaseAddr + (entryIdx * tblEntrySize));
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readSeqErr(uint32_t entryIdx,uint32_t seqErr)
// -----------------------------------------------------------------------------------------------------
int readSeqErr(uint32_t entryIdx,uint32_t *seqErr)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= ((MR_SEQ_ERR_SIZE/SEQ_ERR_ENTRY_SIZE)),ERR_INVALID_ADDRESS);

	mrHalRamRead((entryIdx * SEQ_ERR_ENTRY_SIZE) + MR_BA_SEQ_ERR, EXT_SRAM_SEL, &data);

	*seqErr = data;
#ifdef DEBUG_PRINT_L2
	ts_printf( "readSeqErr:Index 0x%0x=> seqErr=%d (Addr=0x%0x)\n", entryIdx, *seqErr, (entryIdx * SEQ_ERR_ENTRY_SIZE) + MR_BA_SEQ_ERR);
#endif
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeSeqErr(uint32_t entryIdx,uint32_t seqErr)
// -----------------------------------------------------------------------------------------------------
int writeSeqErr(uint32_t entryIdx,uint32_t seqErr)
{
	EGL_ASSERT(entryIdx <= ((MR_SEQ_ERR_SIZE/SEQ_ERR_ENTRY_SIZE)),ERR_INVALID_ADDRESS);
	//ts_printf( "writeSeqErr:\n\r");
	print_reg = 1;

	mrHalRamWrite((entryIdx * SEQ_ERR_ENTRY_SIZE) + MR_BA_SEQ_ERR, EXT_SRAM_SEL, seqErr);
#ifdef DEBUG_PRINT_L2
	ts_printf( "writeSeqErr:Index 0x%0x=> seqErr=%d (Addr=0x%0x)\n", entryIdx, seqErr, (entryIdx * SEQ_ERR_ENTRY_SIZE) + MR_BA_SEQ_ERR);
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRMepSMRam(uint32_t entryIdx,rMepSMEntry_t rMepSMEntry)
// -----------------------------------------------------------------------------------------------------
int readRMepSMRam(uint32_t entryIdx,rMepSMEntry_t *rMepSMEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead(entryIdx, RMEP_RAM_SEL, &data);
	rMepSMEntry->rdi = (uint8_t) ((data >> 28) & 0x00000001);			//[28]
	rMepSMEntry->enable = (uint8_t) ((data >> 27) & 0x00000001);		//[27]
	rMepSMEntry->goodCount = (uint8_t) ((data >> 16) & 0x00000003);	//[26:25]
	rMepSMEntry->timer = (uint32_t) ((data >> 8) & 0x003FFFFF);		//[24:3]
	rMepSMEntry->state = (uint8_t) (data & 0x00000007);				//[2:0]
#ifdef DEBUG_PRINT_L2
	ts_printf( "readRMepSMRam:Index 0x%0x=> state=0x%0x,enable=0x%0x,timer=0x%0x,goodCount=0x%d,rdi=%d",entryIdx,rMepSMEntry->state,rMepSMEntry->enable,rMepSMEntry->timer,rMepSMEntry->goodCount,rMepSMEntry->rdi);
#endif
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeRMepSMRam(uint32_t entryIdx,uint32_t seqErr)
// -----------------------------------------------------------------------------------------------------
int writeRMepSMRam(uint32_t entryIdx,rMepSMEntry_t *rMepSMEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	data = ((((uint32_t) rMepSMEntry->rdi) & 0x00000001) << 28) +		//[28]
		((((uint32_t) rMepSMEntry->enable) & 0x00000001) << 27) +			//[27]
		((((uint32_t) rMepSMEntry->goodCount) & 0x00000003) << 25) +		//[26:25]
		(((rMepSMEntry->timer) & 0x003FFFFF) << 3) +					//[24:3]
		(((uint32_t) rMepSMEntry->state) & 0x00000007);					//[2:0]

	//VRts_printf( "writeRMepSMRam:\n\r");
	print_reg = 1;
	mrHalRamWrite(entryIdx, RMEP_RAM_SEL, data);

	//VRts_printf( "writeRMepSMRam:Index 0x%0x=> state=0x%0x,enable=0x%0x,timer=0x%0x,goodCount=0x%d,rdi=%d",entryIdx,rMepSMEntry->state,rMepSMEntry->enable,rMepSMEntry->timer,rMepSMEntry->goodCount,rMepSMEntry->rdi);
	return(NO_ERR);
}



// -----------------------------------------------------------------------------------------------------
// readXConnSMRam(uint32_t entryIdx, xConnSMEntry_t *xConnSMEntry);
// -----------------------------------------------------------------------------------------------------
int readXConnSMRam(uint32_t entryIdx, xConnSMEntry_t *xConnSMEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead(entryIdx, XCONN_RAM_SEL, &data);

	xConnSMEntry->enable = (uint8_t) ((data >> 24) & 0x00000001);		//[24]
	xConnSMEntry->timer = (uint32_t) ((data >> 2) & 0x003FFFFF);		//[23:2]
	xConnSMEntry->state = (uint8_t) (data & 0x00000003);				//[1:0]

	//VRts_printf( "readXConnSMRam:Index 0x%0x=> state=0x%0x,enable=0x%0x,timer=0x%0x",entryIdx,xConnSMEntry->state,xConnSMEntry->enable,xConnSMEntry->timer);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeXConnSMRam(uint32_t entryIdx, xConnSMEntry_t *xConnSMEntry);
// -----------------------------------------------------------------------------------------------------
int writeXConnSMRam(uint32_t entryIdx, xConnSMEntry_t *xConnSMEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	data = ((((uint32_t) xConnSMEntry->enable) & 0x00000001)  << 24) +		//[24]
		(((xConnSMEntry->timer) & 0x003FFFFF) << 2) +					//[23:2]
		(((uint32_t) xConnSMEntry->state) & 0x00000003);					//[1:0]
	//VRts_printf( "writeXConnSMRam:\n\r");
	    print_reg = 1;
	mrHalRamWrite(entryIdx, XCONN_RAM_SEL, data);

	//VRts_printf( "writeXConnSMRam:Index 0x%0x=> state=0x%0x,enable=0x%0x,timer=0x%0x",entryIdx,xConnSMEntry->state,xConnSMEntry->enable,xConnSMEntry->timer);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRMepErrSMRam(uint32_t entryIdx, rMepErrSMEntry_t *rMepErrSMEntry)
// -----------------------------------------------------------------------------------------------------
int readRMepErrSMRam(uint32_t entryIdx, rMepErrSMEntry_t *rMepErrSMEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead(entryIdx, RMEP_ERR_RAM_SEL, &data);

	rMepErrSMEntry->enable = (uint8_t) ((data >> 24) & 0x00000001);		//[24]
	rMepErrSMEntry->timer = (uint32_t) ((data >> 2) & 0x003FFFFF);		//[23:2]
	rMepErrSMEntry->state = (uint8_t) (data & 0x00000003);				//[1:0]

	//VRts_printf( "readRMepErrSMRam:Index 0x%0x=> state=0x%0x,enable=0x%0x,timer=0x%0x",entryIdx,rMepErrSMEntry->state,rMepErrSMEntry->enable,rMepErrSMEntry->timer);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeRMepErrSMRam(uint32_t entryIdx, rMepErrSMEntry_t *rMepErrSMEntry)
// -----------------------------------------------------------------------------------------------------
int writeRMepErrSMRam(uint32_t entryIdx, rMepErrSMEntry_t *rMepErrSMEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	data = ((((uint32_t) rMepErrSMEntry->enable) & 0x00000001)  << 24) +		//[24]
		(((rMepErrSMEntry->timer) & 0x003FFFFF) << 2) +						//[23:2]
		(((uint32_t) rMepErrSMEntry->state) & 0x00000003);					//[1:0]
	//VRts_printf( "writeRMepErrSMRam:\n\r");
	        print_reg = 1;
	mrHalRamWrite(entryIdx, RMEP_ERR_RAM_SEL, data);

	//VRts_printf( "writeRMepErrSMRam:Index 0x%0x=> state=0x%0x,enable=0x%0x,timer=0x%0x",entryIdx,rMepErrSMEntry->state,rMepErrSMEntry->enable,rMepErrSMEntry->timer);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// readPVidTable(mrPort_t port, pVidEntry_t *pVidEntry)
// -----------------------------------------------------------------------------------------------------
int	readPVidTable(mrPort_t port, pVidEntry_t *pVidEntry)
{
	uint32_t	data;

	mrHalRegRead(PVID_REG_ADDR, &data);
	switch(port)
	{
		case mrPort0:
			data &= PVID_REG_PORT0_PVID_MASK;
			data = data >> PVID_REG_PORT0_PVID_OFFSET;
			break;
		case mrPort1:
			data &= PVID_REG_PORT1_PVID_MASK;
			data = data >> PVID_REG_PORT1_PVID_OFFSET;
			break;
		default:
			EGL_ASSERT(0,1);		// catch this condition
			break;
	}

	pVidEntry->vlan = (uint16_t) ((data & MR_TAG_VLAN_MASK) >> MR_TAG_VLAN_OFFSET);
	pVidEntry->de 	= (uint8_t) ((data & MR_TAG_DE_MASK) >> MR_TAG_DE_OFFSET);
	pVidEntry->prio = (uint8_t) ((data & MR_TAG_PRIO_MASK) >> MR_TAG_PRIO_OFFSET);

	//VRts_printf( "readPVidTable:Port %d=> Prio=%d, DE=%d, PVid=0x%0x",port,pVidEntry->prio,pVidEntry->de,pVidEntry->vlan);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writePVidTable(mrPort_t port, pVidEntry_t *pVidEntry)
// -----------------------------------------------------------------------------------------------------
int	writePVidTable(mrPort_t port, pVidEntry_t *pVidEntry)
{
	uint32_t	oldData;
	uint32_t	newData;

	newData = ((((uint32_t) pVidEntry->prio) << MR_TAG_PRIO_OFFSET) &  MR_TAG_PRIO_MASK) |
			((((uint32_t) pVidEntry->de) << MR_TAG_DE_OFFSET) & MR_TAG_DE_MASK) |
			((((uint32_t) pVidEntry->vlan) << MR_TAG_VLAN_OFFSET) & MR_TAG_VLAN_MASK);

	mrHalRegRead(PVID_REG_ADDR, &oldData);
	//VRts_printf("writePVidTable print_reg:PVID_REG_ADDR 0x%0x=> oldData=0x%0x , pVidEntry->vlan = 0x%0x\nr",PVID_REG_ADDR,oldData,pVidEntry->vlan);


	switch(port)
	{
		case mrPort0:
			oldData &= PVID_REG_PORT1_PVID_MASK;				// preserve the Port 1 PVID
			newData = newData << PVID_REG_PORT0_PVID_OFFSET;	// Adjust the Port 0 PVID to the correct offset
			break;
		case mrPort1:
			oldData &= PVID_REG_PORT0_PVID_MASK;				// preserve the Port 0 PVID
			newData = newData << PVID_REG_PORT1_PVID_OFFSET;	// Adjust the Port 1 PVID to the correct offset
			break;
		default:
			EGL_ASSERT(0,1);		// catch this condition
			break;
	}
	// Write back the update data
	//VRts_printf("writePVidTable:PVID_REG_ADDR 0x%0x=> oldData|new data=0x%0x, new data = 0x%0x \n\r",PVID_REG_ADDR,(oldData | newData),newData);
	//VRts_printf( "writePVidTable:\n\r");
	            print_reg = 1;
	mrHalRegWrite(PVID_REG_ADDR, oldData | newData);

	//VRts_printf("writePVidTable:Index 0x%l=> Prio=%d, DE=%d, PVid=0x%0x",port,pVidEntry->prio,pVidEntry->de,pVidEntry->vlan);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readTxLMepNumRam(uint32_t txLMepNum,boolean_t *ccmValid,ccmInterval_t *ccmInt,enDis_t *ccmEn);
// -----------------------------------------------------------------------------------------------------
int readTxLMepNumRam(uint32_t txLMepNum,txLMepNumRamEntry_t *txLMepNumRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(txLMepNum <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead(txLMepNum, TX_LMEP_MAP_SEL, &data);

	txLMepNumRamEntry->ccmValid		= ((data & TX_LMEP_NUM_RAM_CCM_VALID_MASK)  >> TX_LMEP_NUM_RAM_CCM_VALID_OFFSET);
	txLMepNumRamEntry->ccmEn 		= ((data & TX_LMEP_NUM_RAM_CCM_EN_MASK) >> TX_LMEP_NUM_RAM_CCM_EN_OFFSET);
	txLMepNumRamEntry->ccmInt		= ((data & TX_LMEP_NUM_RAM_CCM_INT_MASK) >> TX_LMEP_NUM_RAM_CCM_INT_OFFSET);
	txLMepNumRamEntry->aisEn		= ((data & TX_LMEP_NUM_RAM_CCM_AIS_MASK) >> TX_LMEP_NUM_RAM_CCM_AIS_OFFSET);
	txLMepNumRamEntry->lckEn		= ((data & TX_LMEP_NUM_RAM_CCM_LCK_MASK) >> TX_LMEP_NUM_RAM_CCM_LCK_OFFSET);
	txLMepNumRamEntry->iFace		= ((data & TX_LMEP_NUM_RAM_CCM_PORT_MASK) >> TX_LMEP_NUM_RAM_CCM_PORT_OFFSET);

	//VRts_printf( "readTxLMepNumRam:Index 0x%0x=> ccmValid=%d, ccmInt=%d, ccmEn=%d, aisEn=%d, lckEn=%d",txLMepNum,txLMepNumRamEntry->ccmValid,txLMepNumRamEntry->ccmInt,txLMepNumRamEntry->ccmEn,txLMepNumRamEntry->aisEn,txLMepNumRamEntry->lckEn);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeTxLMepNumRam(uint32_t txLMepNum,txLMepNumRamEntry_t *txLMepNumRamEntry);
// -----------------------------------------------------------------------------------------------------
int writeTxLMepNumRam(uint32_t txLMepNum,txLMepNumRamEntry_t *txLMepNumRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(txLMepNum <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	// read the current value
	mrHalRamRead(txLMepNum, TX_LMEP_MAP_SEL, &data);
	//VRts_printf("writeTxLMepNumRam: Read data = %0x, txLMepNum = %d\n\r ",data,txLMepNum);
	// Preserve the PM section only
	data &= TX_LMEP_NUM_RAM_PM_MASK;
	data |=	((((uint32_t) txLMepNumRamEntry->ccmValid) << TX_LMEP_NUM_RAM_CCM_VALID_OFFSET)  & TX_LMEP_NUM_RAM_CCM_VALID_MASK)
			| ((((uint32_t) txLMepNumRamEntry->ccmEn) << TX_LMEP_NUM_RAM_CCM_EN_OFFSET)  & TX_LMEP_NUM_RAM_CCM_EN_MASK)
			| ((((uint32_t) txLMepNumRamEntry->ccmInt) << TX_LMEP_NUM_RAM_CCM_INT_OFFSET)  & TX_LMEP_NUM_RAM_CCM_INT_MASK)
			| ((((uint32_t) txLMepNumRamEntry->aisEn) << TX_LMEP_NUM_RAM_CCM_AIS_OFFSET)  & TX_LMEP_NUM_RAM_CCM_AIS_MASK)
			| ((((uint32_t) txLMepNumRamEntry->lckEn) << TX_LMEP_NUM_RAM_CCM_LCK_OFFSET)  & TX_LMEP_NUM_RAM_CCM_LCK_MASK)
			| ((((uint32_t) txLMepNumRamEntry->iFace) << TX_LMEP_NUM_RAM_CCM_PORT_OFFSET)  & TX_LMEP_NUM_RAM_CCM_PORT_MASK);
	// write back the new value
	//VRts_printf( "writeTxLMepNumRam:\n\r");
	                print_reg = 1;
	mrHalRamWrite(txLMepNum, TX_LMEP_MAP_SEL, data);
	//VRts_printf("writeTxLMepNumRam: before write , TX_LMEP_MAP_SEL = %0x, data = %0x\n\r ",TX_LMEP_MAP_SEL,data);
	mrHalRamRead(txLMepNum, TX_LMEP_MAP_SEL, &data);
	//VRts_printf("writeTxLMepNumRam: after write , Read data = %0x\n\r ",data);
	//VRts_printf( "writeTxLMepNumRam:Index 0x%0x=> ccmValid=%d, ccmInt=%d, ccmEn=%d, aisEn=%d, lckEn=%d",txLMepNum,txLMepNumRamEntry->ccmValid,txLMepNumRamEntry->ccmInt,txLMepNumRamEntry->ccmEn,txLMepNumRamEntry->aisEn,txLMepNumRamEntry->lckEn);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readPmNumRam(pmNum_t pmNum, pmNumRamEntry_t *pmNumRamEntry);
// -----------------------------------------------------------------------------------------------------
int readPmNumRam(pmNum_t pmNum, pmNumRamEntry_t *pmNumRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(pmNum < (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(pmNum, TX_LMEP_MAP_SEL, &data);

	pmNumRamEntry->pmValid		= ((data & PM_NUM_RAM_PM_VALID_MASK)  >> PM_NUM_RAM_PM_VALID_OFFSET);
	pmNumRamEntry->lossTxEn		= ((data & PM_NUM_RAM_LOSS_EN_MASK) >> PM_NUM_RAM_LOSS_EN_OFFSET);
	pmNumRamEntry->delayTxEn	= ((data & PM_NUM_RAM_DELAY_EN_MASK) >> PM_NUM_RAM_DELAY_EN_OFFSET);
	pmNumRamEntry->idmSvcEn		= ((data & PM_NUM_RAM_IDM_SVC_MASK) >> PM_NUM_RAM_IDM_SVC_OFFSET);
	pmNumRamEntry->slmSvcEn		= ((data & PM_NUM_RAM_SLM_SVC_MASK) >> PM_NUM_RAM_SLM_SVC_OFFSET);
	pmNumRamEntry->dmmSvcEn		= ((data & PM_NUM_RAM_DMM_SVC_MASK) >> PM_NUM_RAM_DMM_SVC_OFFSET);
	pmNumRamEntry->lossInt		= ((data & PM_NUM_RAM_LOSS_INT_MASK) >> PM_NUM_RAM_LOSS_INT_OFFSET);
	pmNumRamEntry->delayInt		= ((data & PM_NUM_RAM_DLY_INT_MASK) >> PM_NUM_RAM_DLY_INT_OFFSET);
	pmNumRamEntry->iFace		= ((data & PM_NUM_RAM_PORT_MASK) >> PM_NUM_RAM_PORT_OFFSET);

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writePmNumRam(pmNum_t pmNum, pmNumRamEntry_t *pmNumRamEntry);
// -----------------------------------------------------------------------------------------------------
int writePmNumRam(pmNum_t pmNum,pmNumRamEntry_t *pmNumRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(pmNum <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	// read the current value
	mrHalRamRead(pmNum, TX_LMEP_MAP_SEL, &data);

	// Preserve the PM section only
	data &= TX_LMEP_NUM_RAM_CCM_MASK;
	//ccmData = data;
	data |=	((pmNumRamEntry->pmValid << PM_NUM_RAM_PM_VALID_OFFSET) & PM_NUM_RAM_PM_VALID_MASK)
				| ((pmNumRamEntry->lossTxEn << PM_NUM_RAM_LOSS_EN_OFFSET) & PM_NUM_RAM_LOSS_EN_MASK)
				| ((pmNumRamEntry->delayTxEn << PM_NUM_RAM_DELAY_EN_OFFSET) & PM_NUM_RAM_DELAY_EN_MASK)
				| ((pmNumRamEntry->idmSvcEn << PM_NUM_RAM_IDM_SVC_OFFSET) & PM_NUM_RAM_IDM_SVC_MASK)
				| ((pmNumRamEntry->slmSvcEn << PM_NUM_RAM_SLM_SVC_OFFSET) & PM_NUM_RAM_SLM_SVC_MASK)
				| ((pmNumRamEntry->dmmSvcEn << PM_NUM_RAM_DMM_SVC_OFFSET) & PM_NUM_RAM_DMM_SVC_MASK)
				| ((pmNumRamEntry->lossInt << PM_NUM_RAM_LOSS_INT_OFFSET) & PM_NUM_RAM_LOSS_INT_MASK)
				| ((pmNumRamEntry->delayInt << PM_NUM_RAM_DLY_INT_OFFSET) & PM_NUM_RAM_DLY_INT_MASK)
				| ((pmNumRamEntry->iFace << PM_NUM_RAM_PORT_OFFSET) & PM_NUM_RAM_PORT_MASK);

	// write back the new value
	//VRts_printf( "writePmNumRam:\n\r");
	                    print_reg = 1;
	mrHalRamWrite(pmNum, TX_LMEP_MAP_SEL, data);

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readRawPmTxLMepNumRam(uint32_t entryIdx,uint32_t *rdData);
// -----------------------------------------------------------------------------------------------------
int readRawPmTxLMepNumRam(uint32_t entryIdx,uint32_t *rdData)
{
	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(entryIdx, TX_LMEP_MAP_SEL, rdData);

	//VRts_printf( "readRawPmTxLMepNumRam:Index %d=> value=0x%0x",entryIdx,*rdData);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeRawPmTxLMepNumRam(uint32_t entryIdx,uint32_t wrData);
// -----------------------------------------------------------------------------------------------------
int writeRawPmTxLMepNumRam(uint32_t entryIdx,uint32_t wrData)
{
	EGL_ASSERT(entryIdx <= (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);
	//VRts_printf( "writeRawPmTxLMepNumRam:\n\r");
	                        print_reg = 1;
	mrHalRamWrite(entryIdx, TX_LMEP_MAP_SEL, wrData);

	//VRts_printf( "writeRawPmTxLMepNumRam:Index %d => value=0x%0x",entryIdx,wrData);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// isFreeTxPmNumTbl(uint32_t entryIdx);
// -----------------------------------------------------------------------------------------------------
int isFreeTxPmNumTbl(uint32_t entryIdx)
{
	uint32_t	rdData;

	if(entryIdx > MAX_NUM_PM_SERVICES)
		return(false);

	mrHalRamRead(entryIdx, TX_LMEP_MAP_SEL, &rdData);

	if (rdData & PM_NUM_RAM_PM_VALID_MASK)
		return(false);
	else
		return(true);
}

// -----------------------------------------------------------------------------------------------------
// readLineStatsRam(uint32_t entryIdx,lineStatsEntry_t *lineStatEntry);
// -----------------------------------------------------------------------------------------------------
int readLineStatsRam(uint32_t entryIdx,lineStatsEntry_t *lineStatEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(entryIdx << 1, LINE_STATS_RAM_SEL, &data);
	lineStatEntry->neTx = data;

	mrHalRamRead((entryIdx << 1) + 1, LINE_STATS_RAM_SEL, &data);
	lineStatEntry->neRx = data;

	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeLineStatsRam(uint32_t entryIdx,lineStatsEntry_t *lineStatEntry);
// -----------------------------------------------------------------------------------------------------
int writeLineStatsRam(uint32_t entryIdx,lineStatsEntry_t *lineStatEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	data = lineStatEntry->neTx;
	mrHalRamWrite(entryIdx << 1, LINE_STATS_RAM_SEL, data);

	data = lineStatEntry->neRx;
	//VRts_printf( "writeLineStatsRam:\n\r");
	print_reg = 1;
	mrHalRamWrite((entryIdx << 1) + 1, LINE_STATS_RAM_SEL, data);
	//VRts_printf( "writeLineStatsRam completed:\n\r");
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readPortMacRam(uint32_t entryIdx,macEntry_t *macEntry);
// -----------------------------------------------------------------------------------------------------
int readPortMacRam(mrPort_t port,macAddress_t macEntry)
{
	uint32_t	data;
	uint32_t	lowRegAdr;
	uint32_t	upRegAdr;

	// Data is stored in the format:
	// --- LSB=1 ---|--- LSB=0 ----
	//  15   8|7  0 | 31 24|23 16|15 8|7  0
	//    B0  |  B1 |  B2  |  B3 | B4 | B5
	switch(port)
	{
		case mrPort0:
			lowRegAdr	= PORT_0_MAC_LOW_REG_ADDR;
			upRegAdr	= PORT_0_MAC_UP_REG_ADDR;
			break;
		case mrPort1:
			lowRegAdr	= PORT_1_MAC_LOW_REG_ADDR;
			upRegAdr	= PORT_1_MAC_UP_REG_ADDR;
			break;
		case mrMgntPort:
			lowRegAdr	= CPU_MGNT_MAC_LOW_REG_ADDR;
			upRegAdr	= CPU_MGNT_MAC_UP_REG_ADDR;
			break;
	}

	mrHalRegRead(lowRegAdr, &data);

	macEntry[5] = (uint8_t) (data & 0xFF);
	macEntry[4] = (uint8_t) ((data >> 8) & 0xFF);
	macEntry[3] = (uint8_t) ((data >> 16) & 0xFF);
	macEntry[2] = (uint8_t) ((data >> 24) & 0xFF);

	mrHalRegRead(upRegAdr, &data);

	macEntry[1] = (uint8_t) (data & 0xFF);
	macEntry[0] = (uint8_t) ((data >> 8) & 0xFF);
	//VRts_printf( "readPortMacRam:Index 0x%0x=> MAC=%02x-%02x-%02x-%02x-%02x-%02x",port,
							//VRmacEntry[0],macEntry[1],macEntry[2],macEntry[3],macEntry[4],macEntry[5]);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writePortMacRam(uint32_t entryIdx,macEntry_t *macEntry);
// -----------------------------------------------------------------------------------------------------
int writePortMacRam(mrPort_t port,macAddress_t macEntry)
{
	uint32_t	data;
	uint32_t	lowRegAdr;
	uint32_t	upRegAdr;

	// Data is stored in the format:
	// --- LSB=1 ---|--- LSB=0 ----
	//  15   8|7  0 | 31 24|23 16|15 8|7  0
	//    B0  |  B1 |  B2  |  B3 | B4 | B5
	switch(port)
	{
		case mrPort0:
			lowRegAdr	= PORT_0_MAC_LOW_REG_ADDR;
			upRegAdr	= PORT_0_MAC_UP_REG_ADDR;
			break;
		case mrPort1:
			lowRegAdr	= PORT_1_MAC_LOW_REG_ADDR;
			upRegAdr	= PORT_1_MAC_UP_REG_ADDR;
			break;
		case mrMgntPort:
			lowRegAdr	= CPU_MGNT_MAC_LOW_REG_ADDR;
			upRegAdr	= CPU_MGNT_MAC_UP_REG_ADDR;
			break;
	}
	data = ((uint32_t) macEntry[5]) |
			(((uint32_t) macEntry[4]) << 8) |
			(((uint32_t) macEntry[3]) << 16) |
			(((uint32_t) macEntry[2]) << 24);
	print_reg = 1;
	mrHalRegWrite(lowRegAdr, data);

	data = ((uint32_t) macEntry[1]) |
			(((uint32_t) macEntry[0]) << 8);

	//VRts_printf( "writePortMacRam:\n\r");
	    print_reg = 1;
	mrHalRegWrite(upRegAdr, data);
	//VRts_printf( "writePortMacRam:lowRegAdr = 0x%0x ,upRegAdr = 0x%0x Index 0x%0x=> MAC=%02x-%02x-%02x-%02x-%02x-%02x",lowRegAdr, upRegAdr, port,
							//VRmacEntry[0],macEntry[1],macEntry[2],macEntry[3],macEntry[4],macEntry[5]);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// readMcLbrStore(uint32_t entryIdx,macAddress_t macAddr);
// -----------------------------------------------------------------------------------------------------
int readMcLbrStore(uint32_t entryIdx, macAddress_t macAddr)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MC_LBR_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// Data is stored in the format:
	//  ------ LSB=0 ------ |-- LSB=1 --|
	// 31 24|23 16|15 8|7  0|15  8|7  0 |
	//  B0  |  B1 | B2 | B3 |  B4 | B5

	//mrHalRamRead(entryIdx << 1, MC_LBR_STORE_SEL, &data);
	mrHalRamRead(MR_LB_MC_MAC_OFFSET + (entryIdx<<1), LBR_RAM_SEL, &data);


	macAddr[3] = (uint8_t) (data & 0xFF);
	macAddr[2] = (uint8_t) ((data >> 8) & 0xFF);
	macAddr[1] = (uint8_t) ((data >> 16) & 0xFF);
	macAddr[0] = (uint8_t) ((data >> 24) & 0xFF);

	//mrHalRamRead((entryIdx << 1) + 1, MC_LBR_STORE_SEL, &data);
	mrHalRamRead(MR_LB_MC_MAC_OFFSET + (entryIdx << 1) + 1, LBR_RAM_SEL, &data);

	macAddr[5] = (uint8_t) (data & 0xFF);
	macAddr[4] = (uint8_t) ((data >> 8) & 0xFF);

	//VRts_printf( "readMcLbrStore:Index 0x%0x=> MAC=%02x-%02x-%02x-%02x-%02x-%02x",entryIdx,
	//VRmacAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5]);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeMcLbrStore(uint32_t entryIdx,macAddress_t macAddr);
// -----------------------------------------------------------------------------------------------------
int writeMcLbrStore(uint32_t entryIdx,macAddress_t macAddr)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MC_LBR_ENTRY_SIZE),ERR_INVALID_ADDRESS);

	// Data is stored in the format:
	//  ------ LSB=0 ------ |-- LSB=1 --|
	// 31 24|23 16|15 8|7  0|15  8|7  0 |
	//  B0  |  B1 | B2 | B3 |  B4 | B5

	data = ((uint32_t) macAddr[3]) |
			(((uint32_t) macAddr[2]) << 8) |
			(((uint32_t) macAddr[1]) << 16) |
			(((uint32_t) macAddr[0]) << 24);
	//mrHalRamWrite(entryIdx << 1, MC_LBR_STORE_SEL, data);
	mrHalRamWrite(MR_LB_MC_MAC_OFFSET + (entryIdx<<1), LBR_RAM_SEL, data);

	data = ((uint32_t) macAddr[5]) |
			(((uint32_t) macAddr[4]) << 8);
	//mrHalRamWrite((entryIdx << 1) + 1, MC_LBR_STORE_SEL, data);
	mrHalRamWrite(MR_LB_MC_MAC_OFFSET + (entryIdx << 1) + 1, LBR_RAM_SEL, data);

	//VRts_printf( "writeMcLbrStore:Index 0x%0x=> MAC=%02x-%02x-%02x-%02x-%02x-%02x",entryIdx,
	//VRmacAddr[0],macAddr[1],macAddr[2],macAddr[3],macAddr[4],macAddr[5]);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readLbmStore(uint32_t entryIdx,lbmStoreEntry_t *lbmStoreEntry);
// -----------------------------------------------------------------------------------------------------
int readLbmStore(uint32_t entryIdx,lbmStoreEntry_t *lbmStoreEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

	mrHalRamRead((entryIdx << 1) + (iFace == wanPort ? LBM_STORE_PORT_0_BA : LBM_STORE_PORT_1_BA) , LBM_STORE_SEL, &data);
	lbmStoreEntry->lMepNum = (uint16_t) data;

	mrHalRamRead((entryIdx << 1) + 1 + (iFace == wanPort ? LBM_STORE_PORT_0_BA : LBM_STORE_PORT_1_BA), LBM_STORE_SEL, &data);
	lbmStoreEntry->counter =  data;

	//VRts_printf( "readLbmStore:Index 0x%0x=> lbmCntr=%d,lMepNum=%d",entryIdx,lbmStoreEntry->counter,lbmStoreEntry->lMepNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeLbmStore(uint32_t entryIdx,lbmStoreEntry_t *lbmStoreEntry);
// -----------------------------------------------------------------------------------------------------
int writeLbmStore(uint32_t entryIdx,lbmStoreEntry_t *lbmStoreEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

	data = (uint32_t) lbmStoreEntry->lMepNum;
	mrHalRamWrite((entryIdx << 1) + (iFace == wanPort ? LBM_STORE_PORT_0_BA : LBM_STORE_PORT_1_BA), LBM_STORE_SEL, data);

	data = lbmStoreEntry->counter;
	mrHalRamWrite((entryIdx << 1) + 1  + (iFace == wanPort ? LBM_STORE_PORT_0_BA : LBM_STORE_PORT_1_BA), LBM_STORE_SEL, data);

	//VRts_printf( "writeLbmStore:Index 0x%0x=> lbmCntr=%d,lMepNum=%d",entryIdx,lbmStoreEntry->counter,lbmStoreEntry->lMepNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readPmStatsRam(uint32_t entryIdx,pmStatsRamEntry_t *pmStatsRamEntry);
// -----------------------------------------------------------------------------------------------------
int readPmStatsRam(uint32_t entryIdx,pmStatsRamEntry_t *pmStatsRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FL_THRES_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enFL = (data & PM_STATS_RAM_EN_FL_MASK) ? 1 : 0;
	pmStatsRamEntry->fltDiv128 = (data & PM_STATS_RAM_FLT_DIV_128_MASK) ? 1 : 0;
	pmStatsRamEntry->firstLmr = (data & PM_STATS_RAM_FIRST_LMR_MASK) ? 1 : 0;
	pmStatsRamEntry->fLThres = (data & PM_STATS_RAM_FL_THRES_MASK) >> PM_STATS_RAM_FL_THRES_OFFSET;
	pmStatsRamEntry->dtlPm = (data & PM_STATS_RAM_EN_DTL_PM_MASK) ? 1 : 0;
	pmStatsRamEntry->sESFlg = (data & PM_STATS_RAM_SES_FLAG_MASK) ? 1 : 0;
	pmStatsRamEntry->eSFlg = (data & PM_STATS_RAM_ES_FLAG_MASK) ? 1 : 0;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_TX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastNeTx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_RX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastFeRx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_TX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->neTxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_RX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->feRxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_TX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastFeTx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_RX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastNeRx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_TX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->feTxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_RX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->neRxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SES_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->SESCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ES_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->ESCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enAlm = (data & PM_STATS_RAM_EN_ALM_MASK) ? 1 : 0;
	pmStatsRamEntry->rMepNum = (uint16_t)((data & PM_STATS_RAM_RMEP_NUM_MASK) >> PM_STATS_RAM_RMEP_NUM_OFFSET);
	pmStatsRamEntry->lMepNum = (uint16_t)((data & PM_STATS_RAM_LMEP_NUM_MASK) >> PM_STATS_RAM_LMEP_NUM_OFFSET);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_JITTER_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastJitter = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_DELAY_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastDelay = data & PM_STATS_RAM_LAST_DELAY_MASK;
	pmStatsRamEntry->firstRx = ((data & PM_STATS_RAM_FIRST_RX_MASK) >> PM_STATS_RAM_FIRST_RX_OFFSET) ;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_PKT_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDPktCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_LOW_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumLatLow = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_UPP_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumLatUpp = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_LOW_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumJittLow = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_UPP_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumJittUpp = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_THRES_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enFD = (data & PM_STATS_RAM_EN_FD_MASK) ? 1 : 0;
	pmStatsRamEntry->fDThres = (data & PM_STATS_RAM_FD_THRES_MASK) >> PM_STATS_RAM_FD_THRES_OFFSET;
	pmStatsRamEntry->fD1SErrCntr = data & PM_STATS_RAM_FD_ERR_CNTR_MASK;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_ERR_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDErrCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_THRES_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDVThres = (data & PM_STATS_RAM_FDV_THRES_MASK) >> PM_STATS_RAM_FDV_THRES_OFFSET;
	pmStatsRamEntry->fDV1SErrCntr = data & PM_STATS_RAM_FDV_ERR_CNTR_MASK;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_ERR_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDVErrCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_LAT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->minLat = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_LAT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->maxLat = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_JITT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->minJitt = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_JITT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->maxJitt = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT0_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt0 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT1_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt1 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT2_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt2 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT3_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt3 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT0_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt0 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT1_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt1 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT2_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt2 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT3_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt3 = data;

	//VRts_printf( "readPmStatsRam:PM Channel 0x%0x",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writePmStatsRam(uint32_t entryIdx,pmStatsRamEntry_t *pmStatsRamEntry);
// -----------------------------------------------------------------------------------------------------
int writePmStatsRam(uint32_t entryIdx,pmStatsRamEntry_t *pmStatsRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	data = (((((uint32_t) pmStatsRamEntry->enFL) << PM_STATS_RAM_EN_FL_OFFSET) & PM_STATS_RAM_EN_FL_MASK) |
			((((uint32_t) pmStatsRamEntry->fltDiv128) << PM_STATS_RAM_FLT_DIV_128_OFFSET) & PM_STATS_RAM_FLT_DIV_128_MASK) |
			((((uint32_t) pmStatsRamEntry->firstLmr) << PM_STATS_RAM_FIRST_LMR_OFFSET) & PM_STATS_RAM_FIRST_LMR_MASK) |
			((((uint32_t) pmStatsRamEntry->fLThres ) << PM_STATS_RAM_FL_THRES_OFFSET) & PM_STATS_RAM_FL_THRES_MASK) |
			((((uint32_t) pmStatsRamEntry->dtlPm) << PM_STATS_RAM_EN_DTL_PM_OFFSET) & PM_STATS_RAM_EN_DTL_PM_MASK) |
			((((uint32_t) pmStatsRamEntry->sESFlg) << PM_STATS_RAM_SES_FLAG_OFFSET) & PM_STATS_RAM_SES_FLAG_MASK) |
			((((uint32_t) pmStatsRamEntry->eSFlg) << PM_STATS_RAM_ES_FLAG_OFFSET) & PM_STATS_RAM_ES_FLAG_MASK));
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FL_THRES_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastNeTx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_TX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastFeRx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_RX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->neTxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_TX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->feRxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_RX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastFeTx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_TX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastNeRx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_RX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->feTxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_TX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->neRxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_RX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->SESCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SES_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->ESCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ES_CNTR_ROW, PM_STATS_RAM_SEL, data);

	// This is a readModify write so as to preserve the SW bits at [29:28]
	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, &data);
	data &= ~(PM_STATS_RAM_EN_ALM_MASK | PM_STATS_RAM_RMEP_NUM_MASK | PM_STATS_RAM_LMEP_NUM_MASK);
	data |=  ((((uint32_t)pmStatsRamEntry->enAlm) << PM_STATS_RAM_EN_ALM_OFFSET) & PM_STATS_RAM_EN_ALM_MASK) |
			((((uint32_t)pmStatsRamEntry->rMepNum) << PM_STATS_RAM_RMEP_NUM_OFFSET) & PM_STATS_RAM_RMEP_NUM_MASK) |
			((((uint32_t)pmStatsRamEntry->lMepNum) << PM_STATS_RAM_LMEP_NUM_OFFSET) & PM_STATS_RAM_LMEP_NUM_MASK);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastJitter;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_JITTER_ROW, PM_STATS_RAM_SEL, data);

	data = (((uint32_t) pmStatsRamEntry->firstRx) << PM_STATS_RAM_FIRST_RX_OFFSET) | pmStatsRamEntry->lastDelay;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_DELAY_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->fDPktCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_PKT_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumLatLow;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_LOW_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumLatUpp;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_UPP_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumJittLow;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_LOW_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumJittUpp;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_UPP_ROW, PM_STATS_RAM_SEL, data);


	data =  (((uint32_t) pmStatsRamEntry->enFD) << 26) |
			(((uint32_t) pmStatsRamEntry->fDThres) << 4) |
			((uint32_t) pmStatsRamEntry->fD1SErrCntr);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_THRES_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->fDErrCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_ERR_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = 	(((uint32_t) pmStatsRamEntry->fDVThres) << 4) |
			((uint32_t) pmStatsRamEntry->fDV1SErrCntr);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_THRES_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->fDVErrCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_ERR_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->minLat;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_LAT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->maxLat;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_LAT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->minJitt;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_JITT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->maxJitt;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_JITT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt0;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT0_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt1;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT1_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt2;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT2_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt3;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT3_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt0;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT0_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt1;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT1_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt2;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT2_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt3;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT3_ROW, PM_STATS_RAM_SEL, data);

	//VRts_printf( "writePmStatsRam:PM Channel 0x%0x",entryIdx);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// readPmStatsRamRow(uint32_t entryIdx, uint8_t row, uint32_t *rowValue);
// -----------------------------------------------------------------------------------------------------
int readPmStatsRamRow(uint32_t entryIdx, uint8_t row, uint32_t *rowValue)
{
	EGL_ASSERT(entryIdx <= MAX_NUM_PM_SERVICES,ERR_INVALID_ADDRESS);
	EGL_ASSERT(row <= PM_STATS_ENTRY_SIZE,ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + row, PM_STATS_RAM_SEL, rowValue);

	//VRts_printf( "readPmStatsRamRow:Index = %d, Row = %d, value = 0x%0x",entryIdx, row, *rowValue);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writePmStatsRamRow(uint32_t entryIdx, uint8_t row, uint32_t rowValue);
// -----------------------------------------------------------------------------------------------------
int writePmStatsRamRow(uint32_t entryIdx, uint8_t row, uint32_t rowValue)
{
	EGL_ASSERT(entryIdx <= MAX_NUM_PM_SERVICES,ERR_INVALID_ADDRESS);
	EGL_ASSERT(row <= PM_STATS_ENTRY_SIZE,ERR_INVALID_ADDRESS);

	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + row, PM_STATS_RAM_SEL, rowValue);

	//VRts_printf( "writePmStatsRamRow:Index = %d, Row = %d, value = 0x%0x",entryIdx, row, rowValue);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
int readLmmPmStatsRam(uint32_t entryIdx,pmStatsRamLmmEntry_t *pmStatsRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FL_THRES_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enFL = (data & PM_STATS_RAM_EN_FL_MASK) ? 1 : 0;
	pmStatsRamEntry->fltDiv128 = (data & PM_STATS_RAM_FLT_DIV_128_MASK) ? 1 : 0;
	pmStatsRamEntry->firstLmr = (data & PM_STATS_RAM_FIRST_LMR_MASK) ? 1 : 0;
	pmStatsRamEntry->fLThres = (data & PM_STATS_RAM_FL_THRES_MASK) >> PM_STATS_RAM_FL_THRES_OFFSET;
	pmStatsRamEntry->dtlPm = (data & PM_STATS_RAM_EN_DTL_PM_MASK) ? 1 : 0;
	pmStatsRamEntry->sESFlg = (data & PM_STATS_RAM_SES_FLAG_MASK) ? 1 : 0;
	pmStatsRamEntry->eSFlg = (data & PM_STATS_RAM_ES_FLAG_MASK) ? 1 : 0;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_TX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastNeTx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_RX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastFeRx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_TX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->neTxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_RX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->feRxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_TX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastFeTx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_RX_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastNeRx = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_TX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->feTxCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_RX_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->neRxCntr = data;

//	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SES_CNTR_ROW, PM_STATS_RAM_SEL, &data);
//	pmStatsRamEntry->SESCntr = data;

//	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ES_CNTR_ROW, PM_STATS_RAM_SEL, &data);
//	pmStatsRamEntry->ESCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enAlm = (data & PM_STATS_RAM_EN_ALM_MASK) ? 1 : 0;
	pmStatsRamEntry->rMepNum = (uint16_t)((data & PM_STATS_RAM_RMEP_NUM_MASK) >> PM_STATS_RAM_RMEP_NUM_OFFSET);
	pmStatsRamEntry->lMepNum = (uint16_t)((data & PM_STATS_RAM_LMEP_NUM_MASK) >> PM_STATS_RAM_LMEP_NUM_OFFSET);

	//VRts_printf( "readLmmPmStatsRam:Index = %d",entryIdx);
	return(NO_ERR);
}

int writeLmmPmStatsRam(uint32_t entryIdx,pmStatsRamLmmEntry_t *pmStatsRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	data = (((((uint32_t) pmStatsRamEntry->enFL) << PM_STATS_RAM_EN_FL_OFFSET) & PM_STATS_RAM_EN_FL_MASK) |
			((((uint32_t) pmStatsRamEntry->fltDiv128) << PM_STATS_RAM_FLT_DIV_128_OFFSET) & PM_STATS_RAM_FLT_DIV_128_MASK) |
			((((uint32_t) pmStatsRamEntry->firstLmr) << PM_STATS_RAM_FIRST_LMR_OFFSET) & PM_STATS_RAM_FIRST_LMR_MASK) |
			((((uint32_t) pmStatsRamEntry->fLThres ) << PM_STATS_RAM_FL_THRES_OFFSET) & PM_STATS_RAM_FL_THRES_MASK) |
			((((uint32_t) pmStatsRamEntry->dtlPm) << PM_STATS_RAM_EN_DTL_PM_OFFSET) & PM_STATS_RAM_EN_DTL_PM_MASK) |
			((((uint32_t) pmStatsRamEntry->sESFlg) << PM_STATS_RAM_SES_FLAG_OFFSET) & PM_STATS_RAM_SES_FLAG_MASK) |
			((((uint32_t) pmStatsRamEntry->eSFlg) << PM_STATS_RAM_ES_FLAG_OFFSET) & PM_STATS_RAM_ES_FLAG_MASK));
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FL_THRES_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastNeTx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_TX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastFeRx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_RX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->neTxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_TX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->feRxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_RX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastFeTx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_FE_TX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastNeRx;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_NE_RX_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->feTxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FE_TX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->neRxCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_NE_RX_CNTR_ROW, PM_STATS_RAM_SEL, data);

	// This is a readModify write so as to preserve the SW bits at [29:28]
	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, &data);
	data &= ~(PM_STATS_RAM_EN_ALM_MASK | PM_STATS_RAM_RMEP_NUM_MASK | PM_STATS_RAM_LMEP_NUM_MASK);
	data |=  ((((uint32_t)pmStatsRamEntry->enAlm) << PM_STATS_RAM_EN_ALM_OFFSET) & PM_STATS_RAM_EN_ALM_MASK) |
			((((uint32_t)pmStatsRamEntry->rMepNum) << PM_STATS_RAM_RMEP_NUM_OFFSET) & PM_STATS_RAM_RMEP_NUM_MASK) |
			((((uint32_t)pmStatsRamEntry->lMepNum) << PM_STATS_RAM_LMEP_NUM_OFFSET) & PM_STATS_RAM_LMEP_NUM_MASK);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, data);

	//VRts_printf( "writeLmmPmStatsRam:Index = %d",entryIdx);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------------------------------
int readDmmDelayStats(uint32_t entryIdx, dmStatsEntry_t *dmStatsEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_JITTER_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->lastVar = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_DELAY_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->lastDelay = ((data & PM_STATS_RAM_LAST_DELAY_MASK) >> PM_STATS_RAM_LAST_DELAY_OFFSET);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_PKT_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->fDPktCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_LOW_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->sumFDLow = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_UPP_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->sumFDUpp = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_LOW_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->sumFDVLow = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_UPP_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->sumFDVUpp = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_ERR_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->fDErrCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_ERR_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->fDVErrCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_LAT_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->minFD = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_LAT_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->maxFD = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_JITT_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->minFDV = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_JITT_ROW, PM_STATS_RAM_SEL, &data);
	dmStatsEntry->maxFDV = data;

	//VRts_printf( "readDmmDelayStats:Index = %d",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
//
// -----------------------------------------------------------------------------------------------------
int readDmmBinStats(uint32_t entryIdx,pmStatsRamDelayBinEntry_t *pmStatsRamDelayBinEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT0_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->latBkt0 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT1_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->latBkt1 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT2_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->latBkt2 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT3_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->latBkt3 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT0_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->jittBkt0 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT1_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->jittBkt1 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT2_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->jittBkt2 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT3_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamDelayBinEntry->jittBkt3 = data;

	//VRts_printf( "readDmmBinStats:Index = %d",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readDmmPmStatsRam(uint32_t entryIdx,pmStatsRamDmmEntry_t *pmStatsRamEntry);
// -----------------------------------------------------------------------------------------------------
int readDmmPmStatsRam(uint32_t entryIdx,pmStatsRamDmmEntry_t *pmStatsRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);
//	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SES_CNTR_ROW, PM_STATS_RAM_SEL, &data);
//	pmStatsRamEntry->SESCntr = data;

//	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ES_CNTR_ROW, PM_STATS_RAM_SEL, &data);
//	pmStatsRamEntry->ESCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enAlm = (data & PM_STATS_RAM_EN_ALM_MASK) ? 1 : 0;
	pmStatsRamEntry->rMepNum = (uint16_t)((data & PM_STATS_RAM_RMEP_NUM_MASK) >> PM_STATS_RAM_RMEP_NUM_OFFSET);
	pmStatsRamEntry->lMepNum = (uint16_t)((data & PM_STATS_RAM_LMEP_NUM_MASK) >> PM_STATS_RAM_LMEP_NUM_OFFSET);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_JITTER_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastJitter = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_DELAY_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->lastDelay = data & PM_STATS_RAM_LAST_DELAY_MASK;
	pmStatsRamEntry->firstRx = ((data & PM_STATS_RAM_FIRST_RX_MASK) >> PM_STATS_RAM_FIRST_RX_OFFSET) ;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_PKT_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDPktCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_LOW_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumLatLow = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_UPP_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumLatUpp = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_LOW_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumJittLow = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_UPP_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->sumJittUpp = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_THRES_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->enFD = (data & PM_STATS_RAM_EN_FD_MASK) ? 1 : 0;
	pmStatsRamEntry->fDThres = (data & PM_STATS_RAM_FD_THRES_MASK) >> PM_STATS_RAM_FD_THRES_OFFSET;
	pmStatsRamEntry->fD1SErrCntr = data & PM_STATS_RAM_FD_ERR_CNTR_MASK;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_ERR_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDErrCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_THRES_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDVThres = (data & PM_STATS_RAM_FDV_THRES_MASK) >> PM_STATS_RAM_FDV_THRES_OFFSET;
	pmStatsRamEntry->fDV1SErrCntr = data & PM_STATS_RAM_FDV_ERR_CNTR_MASK;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_ERR_CNTR_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->fDVErrCntr = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_LAT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->minLat = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_LAT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->maxLat = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_JITT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->minJitt = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_JITT_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->maxJitt = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT0_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt0 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT1_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt1 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT2_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt2 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT3_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->latBkt3 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT0_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt0 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT1_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt1 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT2_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt2 = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT3_ROW, PM_STATS_RAM_SEL, &data);
	pmStatsRamEntry->jittBkt3 = data;

	//VRts_printf( "readDmmPmStatsRam:Index = %d",entryIdx);
	return(NO_ERR);
}


int readDmmStatsLastValues(uint32_t entryIdx,uint32_t *lastJitter,uint32_t *lastDelay)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_JITTER_ROW, PM_STATS_RAM_SEL, &data);
	*lastJitter = data;

	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_DELAY_ROW, PM_STATS_RAM_SEL, &data);
	*lastDelay = data & PM_STATS_RAM_LAST_DELAY_MASK;

	//VRts_printf( "readDmmPmStatsRam:Index = %d",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeDmmPmStatsRam(uint32_t entryIdx,pmStatsRamEntry_t *pmStatsRamEntry);
// -----------------------------------------------------------------------------------------------------
int writeDmmPmStatsRam(uint32_t entryIdx,pmStatsRamDmmEntry_t *pmStatsRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_NUM_PM_SERVICES),ERR_INVALID_ADDRESS);
	// This is a readModify write so as to preserve the SW bits at [29:28]
	mrHalRamRead(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, &data);
	data &= ~(PM_STATS_RAM_EN_ALM_MASK | PM_STATS_RAM_RMEP_NUM_MASK | PM_STATS_RAM_LMEP_NUM_MASK);
	data |=  ((((uint32_t)pmStatsRamEntry->enAlm) << PM_STATS_RAM_EN_ALM_OFFSET) & PM_STATS_RAM_EN_ALM_MASK) |
			((((uint32_t)pmStatsRamEntry->rMepNum) << PM_STATS_RAM_RMEP_NUM_OFFSET) & PM_STATS_RAM_RMEP_NUM_MASK) |
			((((uint32_t)pmStatsRamEntry->lMepNum) << PM_STATS_RAM_LMEP_NUM_OFFSET) & PM_STATS_RAM_LMEP_NUM_MASK);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_ALM_MEP_NUMS_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->lastJitter;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_JITTER_ROW, PM_STATS_RAM_SEL, data);

	data = (((uint32_t) pmStatsRamEntry->firstRx) << PM_STATS_RAM_FIRST_RX_OFFSET) | pmStatsRamEntry->lastDelay;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAST_DELAY_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->fDPktCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_PKT_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumLatLow;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_LOW_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumLatUpp;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_LAT_UPP_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumJittLow;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_LOW_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->sumJittUpp;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_SUM_JITT_UPP_ROW, PM_STATS_RAM_SEL, data);

	data =  ((((uint32_t) pmStatsRamEntry->enFD) << PM_STATS_RAM_EN_FD_OFFSET) & PM_STATS_RAM_EN_FD_MASK) |
			((((uint32_t) pmStatsRamEntry->fDThres) << PM_STATS_RAM_FD_THRES_OFFSET) & PM_STATS_RAM_FD_THRES_MASK) |
			((uint32_t) pmStatsRamEntry->fD1SErrCntr & PM_STATS_RAM_FD_ERR_CNTR_MASK);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_THRES_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->fDErrCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FD_ERR_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = 	((((uint32_t) pmStatsRamEntry->fDVThres) << PM_STATS_RAM_FDV_THRES_OFFSET) & PM_STATS_RAM_FDV_THRES_MASK) |
			((uint32_t) pmStatsRamEntry->fDV1SErrCntr & PM_STATS_RAM_FDV_ERR_CNTR_MASK);
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_THRES_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->fDVErrCntr;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_FDV_ERR_CNTR_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->minLat;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_LAT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->maxLat;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_LAT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->minJitt;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MIN_JITT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->maxJitt;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_MAX_JITT_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt0;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT0_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt1;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT1_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt2;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT2_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->latBkt3;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_LAT_BKT3_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt0;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT0_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt1;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT1_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt2;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT2_ROW, PM_STATS_RAM_SEL, data);

	data = pmStatsRamEntry->jittBkt3;
	mrHalRamWrite(MR_BA_PM_STATS + (entryIdx * PM_STATS_ENTRY_SIZE) + PM_STATS_RAM_JITT_BKT3_ROW, PM_STATS_RAM_SEL, data);

	//VRts_printf( "writeDmmPmStatsRam:Index = %d",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readTxLBRam(uint8_t lbChnl,uint32_t *txPktCount);
// -----------------------------------------------------------------------------------------------------
int readTxLBRam(uint8_t lbChnl,uint32_t *txPktCount)
{

	EGL_ASSERT(lbChnl < (MAX_LB_CHANNELS),ERR_INVALID_ADDRESS);
	mrHalRamRead((lbChnl * TX_LB_STAT_ENTRY_SIZE) + 0, TX_LB_RAM_SEL, txPktCount);

	//VRts_printf( "readTxLBRam:LB Channel=%d txPktCount=%d",lbChnl,*txPktCount);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readLBRPerSecFiFo(uint8_t lbChnl,uint8_t fifoPosn,uint32_t* txCnt, uint32_t* rxCnt);
// -----------------------------------------------------------------------------------------------------
int readLBRPerSecFiFo(uint8_t lbChnl,uint8_t fifoPosn,uint32_t* txCnt, uint32_t* rxCnt)
{

	EGL_ASSERT(lbChnl < (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);
	mrHalRamRead(((lbChnl * LBR_ENTRY_SIZE) + MR_LB_1SEC_FIFO_OFFSET + (fifoPosn*2)), LBR_RAM_SEL, txCnt);
	mrHalRamRead(((lbChnl * LBR_ENTRY_SIZE) + MR_LB_1SEC_FIFO_OFFSET + (fifoPosn*2) + 1), LBR_RAM_SEL, rxCnt);
	return(NO_ERR);
}
// -----------------------------------------------------------------------------------------------------
// readLBRRam(uint32_t entryIdx,lbrRamEntry_t *lbrRamEntry);
// -----------------------------------------------------------------------------------------------------
int readLBRRam(uint32_t entryIdx,lbrRamEntry_t *lbrRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_LBR_LB_CFG_OFFSET + (entryIdx>>1), LBR_RAM_SEL, &data);
	if (entryIdx & 0x1)
		lbrRamEntry->multicast = (uint8_t) ((data & LBR_LMEP_NUM_RAM_ODD_MC_MASK) >> LBR_LMEP_NUM_RAM_ODD_MC_OFFSET);
	else
		lbrRamEntry->multicast = (uint8_t) ((data & LBR_LMEP_NUM_RAM_EVEN_MC_MASK) >> LBR_LMEP_NUM_RAM_EVEN_MC_OFFSET);

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 0, LBR_RAM_SEL, &data);
	lbrRamEntry->lastLat = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 1, LBR_RAM_SEL, &data);
	lbrRamEntry->lastJitt = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 2, LBR_RAM_SEL, &data);
	lbrRamEntry->expSN = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 3, LBR_RAM_SEL, &data);
	lbrRamEntry->numRxLbr = data;

	//mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 4, LBR_RAM_SEL, &data);
	//lbrRamEntry->txTSLow = data;

	//mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 5, LBR_RAM_SEL, &data);
	//lbrRamEntry->txTSUpp = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 6, LBR_RAM_SEL, &data);
	lbrRamEntry->minLat = data & 0x3FFFFFF;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 7, LBR_RAM_SEL, &data);
	lbrRamEntry->maxLat = data & 0x3FFFFFF;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 8, LBR_RAM_SEL, &data);
	lbrRamEntry->sumLatLow = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 9, LBR_RAM_SEL, &data);
	lbrRamEntry->sumLatUpp = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 10, LBR_RAM_SEL, &data);
	lbrRamEntry->minJitt = data & 0x3FFFFFF;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 11, LBR_RAM_SEL, &data);
	lbrRamEntry->maxJitt = data & 0x3FFFFFF;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 12, LBR_RAM_SEL, &data);
	lbrRamEntry->sumJitLow = data;

	mrHalRamRead((entryIdx * LBR_ENTRY_SIZE) + 13, LBR_RAM_SEL, &data);
	lbrRamEntry->sumJitUpp = data;

	//VRts_printf( "readLBRRam:Chnl = %d",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writeLBRRam(uint32_t entryIdx,lbrRamEntry_t *lbrRamEntry);
// -----------------------------------------------------------------------------------------------------
int writeLBRRam(uint32_t entryIdx,lbrRamEntry_t *lbrRamEntry)
{
	uint32_t	data;

	EGL_ASSERT(entryIdx <= (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);

	mrHalRamRead(MR_LBR_LB_CFG_OFFSET + (entryIdx>>1), LBR_RAM_SEL, &data);

	if (entryIdx & 0x1)
		data = (data & ~LBR_LMEP_NUM_RAM_ODD_MC_MASK) | (((uint32_t) lbrRamEntry->multicast)<<LBR_LMEP_NUM_RAM_ODD_MC_OFFSET);
	else
		data = (data & ~LBR_LMEP_NUM_RAM_EVEN_MC_MASK) | (((uint32_t) lbrRamEntry->multicast)<<LBR_LMEP_NUM_RAM_EVEN_MC_OFFSET);
	mrHalRamWrite(MR_LBR_LB_CFG_OFFSET + (entryIdx>>1), LBR_RAM_SEL, data);

	data = lbrRamEntry->lastLat;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 0, LBR_RAM_SEL, data);

	data = lbrRamEntry->lastJitt;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 1, LBR_RAM_SEL, data);

	data = lbrRamEntry->expSN;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 2, LBR_RAM_SEL, data);

	data = lbrRamEntry->numRxLbr;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 3, LBR_RAM_SEL, data);

	//data = lbrRamEntry->txTSLow;
	//mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 4, LBR_RAM_SEL, data);

	//data = lbrRamEntry->txTSUpp;
	//mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 5, LBR_RAM_SEL, data);

	data = lbrRamEntry->minLat;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 6, LBR_RAM_SEL, data);

	data = lbrRamEntry->maxLat;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 7, LBR_RAM_SEL, data);

	data = lbrRamEntry->sumLatLow;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 8, LBR_RAM_SEL, data);

	data = lbrRamEntry->sumLatUpp;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 9, LBR_RAM_SEL, data);

	data = lbrRamEntry->minJitt;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 10, LBR_RAM_SEL, data);

	data = lbrRamEntry->maxJitt;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 11, LBR_RAM_SEL, data);

	data = lbrRamEntry->sumJitLow;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 12, LBR_RAM_SEL, data);

	data = lbrRamEntry->sumJitUpp;
	mrHalRamWrite((entryIdx * LBR_ENTRY_SIZE) + 13, LBR_RAM_SEL, data);

	//VRts_printf( "writeLBRRam:Chnl = %d",entryIdx);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readLBRLMepNum( uint8_t lbChnl,uint16_t *lMepNum)
// -----------------------------------------------------------------------------------------------------
//
//
// =====================================================================================================
int readLBRLMepNum( uint8_t lbChnl,uint16_t *lMepNum, uint8_t *pcp)
{
	uint32_t	data;

	EGL_ASSERT(lbChnl < (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);
	mrHalRamRead(MR_LBR_LB_CFG_OFFSET + (lbChnl>>1), LBR_RAM_SEL, &data);

	if (lbChnl & 0x1)
	{
		*lMepNum = (uint16_t) ((data & LBR_LMEP_NUM_RAM_ODD_LMEP_NUM_MASK) >> LBR_LMEP_NUM_RAM_ODD_LMEP_NUM_OFFSET);
		//*mcBit = (uint8_t) ((data & LBR_LMEP_NUM_RAM_ODD_MC_MASK) >> LBR_LMEP_NUM_RAM_ODD_MC_OFFSET);
	}
	else
	{
		*lMepNum = (uint16_t) ((data & LBR_LMEP_NUM_RAM_EVEN_LMEP_NUM_MASK) >> LBR_LMEP_NUM_RAM_EVEN_LMEP_NUM_OFFSET);
		//*mcBit = (uint8_t) ((data & LBR_LMEP_NUM_RAM_EVEN_MC_MASK) >> LBR_LMEP_NUM_RAM_EVEN_MC_OFFSET);
	}

	// read the DE & prio from the LBM_PCP_REG_ADDR
	mrHalRegRead(LBM_PCP_REG_ADDR,&data);

	// Get the channels DE & prio bit
	// Note the PCP is expected to be encoded with DE at bit 0 and prio at bits 3:1
	// The PCP reg has DE at bit 3 and prio at bits 2:0!
	data = data >> (4*lbChnl);
	*pcp = (uint8_t)(((data & 0x7)<<1) | ((data & 0x8)>>3));

	//VRts_printf( "readLBRLMepNum:Chnl %d=> LMepNum=%d & pcp=%0x",lbChnl, *lMepNum,*pcp);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeLBRLMepNum(uint8_t lbChnl,uint16_t lMepNum)
// -----------------------------------------------------------------------------------------------------
//
//
// =====================================================================================================
int writeLBRLMepNum(uint8_t lbChnl,uint16_t lMepNum, uint8_t pcp)
{
	uint32_t	data;
	uint32_t	maskLMepNum;

	EGL_ASSERT(lbChnl < (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);
	// Write the DE bit to the LBM_PCP_REG_ADDR register...
	// Note the PCP is expected to be encoded with DE at bit 0 and prio at bits 3:1
	// The PCP reg has DE at bit 3 and prio at bits 2:0!
	mrHalRegRead(LBM_PCP_REG_ADDR,&data);
	data &= ~(0x0000000F<<(lbChnl*4));
	data |= ((uint32_t)(((pcp << 3)|(pcp >> 1)) & 0xF)) << (lbChnl*4) ;
	mrHalRegWrite(LBM_PCP_REG_ADDR,data);

	mrHalRamRead(MR_LBR_LB_CFG_OFFSET + (lbChnl>>1), LBR_RAM_SEL,&data);

	// Only the lMepNum and MC are saved
	// HW uses these values to process received LBR packets
	// ---------------------------------------------
	// | upper 16bits(lb=odd)| lower 16bits(lb=even)|
	// ---------------------------------------------
	// |mc1 x x x <lMepNum1> | mc0 x x x <lMepNum0> |
	// ---------------------------------------------
	// |mc3 x x x <lMepNum3> | mc2 x x x <lMepNum2> |
	// ---------------------------------------------
	// |mc5 x x x <lMepNum5> | mc4 x x x <lMepNum4> |
	// ---------------------------------------------
	// |mc7 x x x <lMepNum7> | mc6 x x x <lMepNum6> |
	// ---------------------------------------------
	maskLMepNum = (uint32_t) (lMepNum & 0xFFF); 		// ensure that the MSB of lMepNum is always 0. The MSB in the RAM is the Multi-cast bit
	if (lbChnl & 0x1)
	{
		// Preserve the MC bits for both channels and update the lMepNum for the selected channel
		data &= LBR_LMEP_NUM_RAM_EVEN_LMEP_NUM_MASK | LBR_LMEP_NUM_RAM_EVEN_MC_MASK | LBR_LMEP_NUM_RAM_ODD_MC_MASK;
		data |= (((maskLMepNum) << LBR_LMEP_NUM_RAM_ODD_LMEP_NUM_OFFSET) & LBR_LMEP_NUM_RAM_ODD_LMEP_NUM_MASK) ;
	}
	else
	{
		// Preserve the MC bits for both channels and update the lMepNum for the selected channel
		data &= LBR_LMEP_NUM_RAM_ODD_LMEP_NUM_MASK | LBR_LMEP_NUM_RAM_ODD_MC_MASK | LBR_LMEP_NUM_RAM_EVEN_MC_MASK;
		data |= (((maskLMepNum) << LBR_LMEP_NUM_RAM_EVEN_LMEP_NUM_OFFSET) & LBR_LMEP_NUM_RAM_EVEN_LMEP_NUM_MASK) ;
	}

	mrHalRamWrite(MR_LBR_LB_CFG_OFFSET + (lbChnl>>1), LBR_RAM_SEL,data);

	//VRts_printf( "writeLBRLMepNum:Chnl %d=> LMepNum=%d & pcp=%0x",lbChnl, lMepNum,pcp);
	return(NO_ERR);
}


// -----------------------------------------------------------------------------------------------------
// writeLBRSeqNum(uint8_t lbChnl,uint32_t seqNum)
// -----------------------------------------------------------------------------------------------------
//
//
// =====================================================================================================
int writeLBRSeqNum(uint8_t lbChnl,uint32_t seqNum)
{
	EGL_ASSERT(lbChnl < (MAX_LB_CHANNELS_FOR_Y1564),ERR_INVALID_ADDRESS);
	mrHalRamWrite((lbChnl * LBR_ENTRY_SIZE) + 2, LBR_RAM_SEL, seqNum);

	//VRts_printf( "writeLBRSeqNum:Chnl %d=> seqNum=%d",lbChnl,seqNum);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// readPmDtFiFo(uint32_t entryIdx,uint32_t *rowValue);
// -----------------------------------------------------------------------------------------------------
int readPmDtFiFo(uint32_t entryIdx,uint32_t *rowValue)
{

	EGL_ASSERT(entryIdx <= (MR_DETAILED_PM_FIFO_DEPTH),ERR_INVALID_ADDRESS);

	// Each entry is located at offset 63 from the start of each RMEP_DB entry
	mrHalRamRead(MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 63, EXT_SRAM_SEL, rowValue);

	//VRts_printf( "readPmDtFiFo:Index = %d=> Value=0x%0x",entryIdx,*rowValue);
	return(NO_ERR);
}

// -----------------------------------------------------------------------------------------------------
// writePmDtFiFo(uint32_t entryIdx,uint32_t rowValue);
// -----------------------------------------------------------------------------------------------------
int writePmDtFiFo(uint32_t entryIdx,uint32_t rowValue)
{
	EGL_ASSERT(entryIdx <= (MR_DETAILED_PM_FIFO_DEPTH),ERR_INVALID_ADDRESS);

	mrHalRamWrite(MR_BA_RMEP_DB + (entryIdx * DB_ENTRY_SIZE) + 63, EXT_SRAM_SEL, rowValue);

	//VRts_printf( "writePmDtFiFo:Index = %d=> Value=0x%0x",entryIdx,rowValue);
	return(NO_ERR);
}


void clearLBErrors(uint8_t lbChnl)
{
	uint32_t	data;

	mrHalRegRead(CLR_LBR_ERR_REG_ADDR,&data);
	data = (data & ~0xF) | ((((uint32_t) lbChnl) << 1) + 1);
	mrHalRegWrite(CLR_LBR_ERR_REG_ADDR,data);		// Write 1 to bit 0 to clear the chnl addressed in bits 1-3
	data = (data & ~0xF) | ((((uint32_t) lbChnl) << 1));
	mrHalRegWrite(CLR_LBR_ERR_REG_ADDR,data);		// Write 0 to bit 0

	//VRts_printf( "clearLBErrors:Chnl = %d",lbChnl);
}

/*
 *
 */
int readRawEvcTbl(uint32_t addr, uint32_t *rdPtr, iFace_t iFace)
{
	mrHalRamRead((addr) + (iFace == wanPort ? EVC_TBL_PORT_0_BA : EVC_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, rdPtr);
	return (NO_ERR);
}

/*
 *
 */
int writeRawEvcTbl(uint32_t addr, uint32_t wrData, iFace_t iFace)
{
	mrHalRamWrite((addr) + (iFace == wanPort ? EVC_TBL_PORT_0_BA : EVC_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, wrData);
	return (NO_ERR);
}

/*
 *
 */
int readEvcTbl(uint16_t evc, evcTblEntry_t *evcTblEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(evc < (MAX_NUM_EVCS),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((evc * EVC_TBL_ENTRY_SIZE) + (iFace == wanPort ? EVC_TBL_PORT_0_BA : EVC_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL,&data);
	evcTblEntry->txVid					= 		(uint16_t)		((data & EVC_TBL_TX_VID_MASK) >> EVC_TBL_TX_VID_OFFSET);
	evcTblEntry->pushTagType 			= 		(pushTag_t) 	((data & EVC_TBL_PUSH_TAG_TYPE_MASK) >> EVC_TBL_PUSH_TAG_TYPE_OFFSET);
	evcTblEntry->tagAction				= 		(tagAction_t)	((data & EVC_TBL_TAG_ACTION_MASK) >> EVC_TBL_TAG_ACTION_OFFSET);
	evcTblEntry->cosDscp				= 		(uint8_t) 		((data & EVC_TBL_COS_DSCP_MASK) >> EVC_TBL_COS_DSCP_OFFSET);
	evcTblEntry->usePcpEvcCol			= 		(uint8_t) 		((data & EVC_TBL_USE_PCP_EVC_COL_MASK) >> EVC_TBL_USE_PCP_EVC_COL_OFFSET);
	evcTblEntry->cosPreserve			= 		(uint8_t) 		((data & EVC_TBL_COS_PRESERVE_MASK) >> EVC_TBL_COS_PRESERVE_OFFSET);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: readVlanTbl - Reading EVC info from location %d, port %d:\n", evc, iFace);
#endif
	return(NO_ERR);
}


/*
 *
 */
int writeEvcTbl(uint16_t evc, evcTblEntry_t *evcTblEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(evc < (MAX_NUM_EVCS),ERR_INVALID_ADDRESS);

	// assemble the individual fields for the 1st Dword and write it

	data = (
	((((uint32_t) evcTblEntry->txVid)				<< EVC_TBL_TX_VID_OFFSET)  & EVC_TBL_TX_VID_MASK) |
	((((uint32_t) evcTblEntry->pushTagType) 		<< EVC_TBL_PUSH_TAG_TYPE_OFFSET) & EVC_TBL_PUSH_TAG_TYPE_MASK) |
	((((uint32_t) evcTblEntry->tagAction)			<< EVC_TBL_TAG_ACTION_OFFSET) & EVC_TBL_TAG_ACTION_MASK) |
	((((uint32_t) evcTblEntry->cosDscp)				<< EVC_TBL_COS_DSCP_OFFSET) & EVC_TBL_COS_DSCP_MASK) |
	((((uint32_t) evcTblEntry->usePcpEvcCol)		<< EVC_TBL_USE_PCP_EVC_COL_OFFSET) & EVC_TBL_USE_PCP_EVC_COL_MASK) |
	((((uint32_t) evcTblEntry->cosPreserve)			<< EVC_TBL_COS_PRESERVE_OFFSET) & EVC_TBL_COS_PRESERVE_MASK));


	mrHalRamWrite((evc * EVC_TBL_ENTRY_SIZE) + (iFace == wanPort ? EVC_TBL_PORT_0_BA : EVC_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeVlanTbl - Writing EVC info to location %d, port %d:\n", evc, iFace);
#endif
	return(NO_ERR);
}

/*
 *
 */
int readCfmTbl(uint16_t cfmNum, cfmTblEntry_t *cfmTblEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(cfmNum < (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	// Read back the first dword and extract the individual fields
	mrHalRamRead((cfmNum * CFM_TBL_ENTRY_SIZE) + (iFace == wanPort ? CFM_TBL_PORT_0_BA : CFM_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL,&data);
	cfmTblEntry->rxHighestMepLevel		= 		(mdLevel_t) 	((data & EVC_TBL_RX_HIGHEST_MEP_LVL_MASK) >> EVC_TBL_RX_HIGHEST_MEP_LVL_OFFSET);
	cfmTblEntry->rxHighestMepLevelVal	= 		(bool)			((data & EVC_TBL_RX_HIGHEST_MEP_LVL_VAL_MASK) >> EVC_TBL_RX_HIGHEST_MEP_LVL_VAL_OFFSET);
	cfmTblEntry->txHighestMepLevel		= 		(mdLevel_t) 	((data & EVC_TBL_TX_HIGHEST_MEP_LVL_MASK) >> EVC_TBL_TX_HIGHEST_MEP_LVL_OFFSET);
	cfmTblEntry->txHighestMepLevelVal	= 		(bool) 			((data & EVC_TBL_TX_HIGHEST_MEP_LVL_VAL_MASK) >> EVC_TBL_TX_HIGHEST_MEP_LVL_VAL_OFFSET);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: readCfmTbl - Reading CFM info from location %d, port %d:\n", cfmNum, iFace);
#endif
	return(NO_ERR);
}


/*
 *
 */
int writeCfmTbl(uint16_t cfmNum, cfmTblEntry_t *cfmTblEntry, iFace_t iFace)
{
	uint32_t	data;

	EGL_ASSERT(cfmNum < (MAX_NUM_MEPS),ERR_INVALID_ADDRESS);

	// assemble the individual fields for the 1st Dword and write it

	data = (
	((((uint32_t) cfmTblEntry->rxHighestMepLevel)	<< EVC_TBL_RX_HIGHEST_MEP_LVL_OFFSET) & EVC_TBL_RX_HIGHEST_MEP_LVL_MASK) |
	((((uint32_t) cfmTblEntry->rxHighestMepLevelVal)<< EVC_TBL_RX_HIGHEST_MEP_LVL_VAL_OFFSET) & EVC_TBL_RX_HIGHEST_MEP_LVL_VAL_MASK) |
	((((uint32_t) cfmTblEntry->txHighestMepLevel)	<< EVC_TBL_TX_HIGHEST_MEP_LVL_OFFSET) & EVC_TBL_TX_HIGHEST_MEP_LVL_MASK) |
	((((uint32_t) cfmTblEntry->txHighestMepLevelVal)<< EVC_TBL_TX_HIGHEST_MEP_LVL_VAL_OFFSET) & EVC_TBL_TX_HIGHEST_MEP_LVL_VAL_MASK));

	mrHalRamWrite((cfmNum * CFM_TBL_ENTRY_SIZE) + (iFace == wanPort ? CFM_TBL_PORT_0_BA : CFM_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, data);
#ifdef DEBUG_PRINT_L2
	ts_printf( "INFO: writeCfmTbl - Writing CFM info to location %d, port %d:\n", cfmNum, iFace);
#endif
	return(NO_ERR);
}


int writeRxPcpTbl(uint8_t row, iFace_t iFace,pcpEntry_t *pcpEntry)
{
	uint32_t	data;

	EGL_ASSERT(row < (COS_RX_PCP_TBL_SIZE * COS_RX_PCP_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	data = ((pcpEntry->priority << COS_TBL_PRIO_OFFSET) & COS_TBL_PRIO_MASK) |
			((pcpEntry->de << COS_TBL_DE_OFFSET) & COS_TBL_DE_MASK);
	mrHalRamWrite((row * COS_RX_PCP_TBL_ENTRY_SIZE) + (iFace == wanPort ? COS_RX_PCP_TBL_PORT_0_BA : COS_RX_PCP_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, data);

	//VRts_printf( "INFO: writeRxPcpTbl - Writing PCP info to location %d, port %d: prio=%d,DE=%d\n", row, iFace,pcpEntry->priority,pcpEntry->de);
	return(NO_ERR);
}

int readRxPcpTbl(uint8_t row, iFace_t iFace,pcpEntry_t *pcpEntry)
{
	uint32_t	data;

	EGL_ASSERT(row < (COS_RX_PCP_TBL_SIZE * COS_RX_PCP_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	mrHalRamRead((row * COS_RX_PCP_TBL_ENTRY_SIZE) + (iFace == wanPort ? COS_RX_PCP_TBL_PORT_0_BA : COS_RX_PCP_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, &data);
	pcpEntry->priority	= ((data & COS_TBL_PRIO_MASK) >> COS_TBL_PRIO_OFFSET);
	pcpEntry->de			= ((data & COS_TBL_DE_MASK) >> COS_TBL_DE_OFFSET) ;

	//VRts_printf( "INFO: readRxPcpTbl - Read PCP info from location %d, port %d: prio=%d,DE=%d\n", row, iFace,pcpEntry->priority,pcpEntry->de);
	return(NO_ERR);
}

int writeTxPcpTbl(uint8_t row, iFace_t iFace,prio_t pcp)
{
	uint32_t	data;

	EGL_ASSERT(row < (COS_TX_PCP_TBL_SIZE * COS_TX_PCP_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	data = (uint32_t)pcp;
	mrHalRamWrite((row * COS_TX_PCP_TBL_ENTRY_SIZE) + (iFace == wanPort ? COS_TX_PCP_TBL_PORT_0_BA : COS_TX_PCP_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, data);

	//VRts_printf( "INFO: writeRxPcpTbl - Writing PCP info to location %d, port %d: prio=%d\n", row, iFace,pcp);
	return(NO_ERR);
}

int readTxPcpTbl(uint8_t row, iFace_t iFace,prio_t *pcp)
{
	uint32_t	data;

	EGL_ASSERT(row < (COS_TX_PCP_TBL_SIZE * COS_TX_PCP_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	mrHalRamRead((row * COS_TX_PCP_TBL_ENTRY_SIZE) + (iFace == wanPort ? COS_TX_PCP_TBL_PORT_0_BA : COS_TX_PCP_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, &data);
	*pcp	= ((data & COS_TBL_PRIO_MASK) >> COS_TBL_PRIO_OFFSET);

	//VRts_printf( "INFO: readRxPcpTbl - Read PCP info from location %d, port %d: prio=%d\n", row, iFace,*pcp);
	return(NO_ERR);
}

int writeDscpTbl(uint8_t row, iFace_t iFace,pcpEntry_t *pcpEntry, uint8_t discard)
{
	uint32_t	data;

	EGL_ASSERT(row < (COS_DSCP_TBL_SIZE * COS_DSCP_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	data = ((((uint32_t)pcpEntry->priority) << COS_TBL_PRIO_OFFSET) & COS_TBL_PRIO_MASK) |
			((((uint32_t)pcpEntry->de) << COS_TBL_DE_OFFSET) & COS_TBL_DE_MASK) |
			((((uint32_t)discard) << DSCP_TBL_DISCARD_OFFSET) & DSCP_TBL_DISCARD_MASK);
	mrHalRamWrite((row * COS_DSCP_TBL_ENTRY_SIZE) + (iFace == wanPort ? COS_DSCP_TBL_PORT_0_BA : COS_DSCP_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, data);

	//VRts_printf( "INFO: writeRxPcpTbl - Writing PCP info to location %d, port %d: prio=%d,DE=%d\n", row, iFace,pcpEntry->priority,pcpEntry->de);
	return(NO_ERR);
}

int readDscpTbl(uint8_t row, iFace_t iFace,pcpEntry_t *pcpEntry, uint8_t *discard)
{
	uint32_t	data;

	EGL_ASSERT(row < (COS_DSCP_TBL_SIZE * COS_DSCP_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	mrHalRamRead((row * COS_DSCP_TBL_ENTRY_SIZE) + (iFace == wanPort ? COS_DSCP_TBL_PORT_0_BA : COS_DSCP_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, &data);
	pcpEntry->priority	= ((data & COS_TBL_PRIO_MASK) >> COS_TBL_PRIO_OFFSET);
	pcpEntry->de		= ((data & COS_TBL_DE_MASK) >> COS_TBL_DE_OFFSET);
	*discard			= ((data & DSCP_TBL_DISCARD_MASK) >> DSCP_TBL_DISCARD_OFFSET);
	//VRts_printf( "INFO: readRxPcpTbl - Read PCP info from location %d, port %d: prio=%d,DE=%d\n", row, iFace,pcpEntry->priority,pcpEntry->de);
	return(NO_ERR);
}

int writeFlowNumTbl(uint32_t row, iFace_t iFace, flowNumEntry_t *flowNumEntry)
{
	uint32_t	data;

	EGL_ASSERT(row < (FLOW_NUM_TBL_SIZE * FLOW_NUM_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	data = ((((uint32_t)flowNumEntry->pcpEvcCol) << FLOW_NUM_TBL_PCP_EVC_COL_OFFSET) & FLOW_NUM_TBL_PCP_EVC_COL_MASK) |
			((((uint32_t)flowNumEntry->mapPcpPrio) << FLOW_NUM_TBL_MAP_PCP_PRIO_OFFSET) & FLOW_NUM_TBL_MAP_PCP_PRIO_MASK) |
			((((uint32_t)flowNumEntry->pcpDiscard) << FLOW_NUM_TBL_PCP_DISCARD_OFFSET) & FLOW_NUM_TBL_PCP_DISCARD_MASK) |
			((((uint32_t)flowNumEntry->colFwd) << FLOW_NUM_TBL_COL_FWD_OFFSET) & FLOW_NUM_TBL_COL_FWD_MASK) |
			((((uint32_t)flowNumEntry->colAware) << FLOW_NUM_TBL_COL_AWARE_OFFSET) & FLOW_NUM_TBL_COL_AWARE_MASK) |
			((((uint32_t)flowNumEntry->flowNum) << FLOW_NUM_TBL_FLOW_NUM_OFFSET) & FLOW_NUM_TBL_FLOW_NUM_MASK) ;
	mrHalRamWrite((row * FLOW_NUM_TBL_ENTRY_SIZE) + (iFace == wanPort ? FLOW_NUM_TBL_PORT_0_BA : FLOW_NUM_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, data);

	//VRts_printf( "INFO: writeRxPcpTbl - Writing PCP info to location %d, port %d: flowNum=%d\n", row, iFace,flowNumEntry->flowNum);
	return(NO_ERR);
}

int readFlowNumTbl(uint32_t row, iFace_t iFace, flowNumEntry_t *flowNumEntry)
{
	uint32_t	data;

	EGL_ASSERT(row < (FLOW_NUM_TBL_SIZE * FLOW_NUM_TBL_ENTRY_SIZE),ERR_INVALID_ADDRESS);
	EGL_ASSERT((iFace == wanPort || iFace == lanPort),ERR_INVALID_ADDRESS);

	mrHalRamRead((row * FLOW_NUM_TBL_ENTRY_SIZE) + (iFace == wanPort ? FLOW_NUM_TBL_PORT_0_BA : FLOW_NUM_TBL_PORT_1_BA), VLAN_INFO_RAM_SEL, &data);
	flowNumEntry->pcpEvcCol		= (uint8_t)((data & FLOW_NUM_TBL_PCP_EVC_COL_MASK) >> FLOW_NUM_TBL_PCP_EVC_COL_OFFSET);
	flowNumEntry->mapPcpPrio		= (prio_t)((data & FLOW_NUM_TBL_MAP_PCP_PRIO_OFFSET) >> FLOW_NUM_TBL_MAP_PCP_PRIO_OFFSET);
	flowNumEntry->pcpDiscard	= (uint8_t)((data & FLOW_NUM_TBL_PCP_DISCARD_MASK) >> FLOW_NUM_TBL_PCP_DISCARD_OFFSET);
	flowNumEntry->colFwd		= (uint8_t)((data & FLOW_NUM_TBL_COL_FWD_MASK) >> FLOW_NUM_TBL_COL_FWD_OFFSET);
	flowNumEntry->colAware		= (uint8_t)((data & FLOW_NUM_TBL_COL_AWARE_MASK) >> FLOW_NUM_TBL_COL_AWARE_OFFSET);
	flowNumEntry->flowNum		= (uint16_t) ((data & FLOW_NUM_TBL_FLOW_NUM_MASK) >> FLOW_NUM_TBL_FLOW_NUM_OFFSET);

	//VRts_printf( "INFO: readFlowNumTbl - Read FlowNum info from location %d, port %d: flowNum=%d\n", row, iFace,flowNumEntry->flowNum);
	return(NO_ERR);
}

int writeFrameDelayBinThresh(uint8_t binNum, uint32_t threshold)
{
	// validate the binNum
	if (binNum == 0 || binNum > BINS_PER_FTD)
	{
		return(1);
	}
	mrHalRegWrite(LAT_BKT0_REG_ADDR + (binNum * 4),threshold);
	return(NO_ERR);
}

int writeFrameDelayVarBinThresh(uint8_t binNum, uint32_t threshold)
{
	// validate the binNum
	if (binNum == 0 || binNum > BINS_PER_FDV)
	{
		return(1);
	}
	mrHalRegWrite(JITT_BKT0_REG_ADDR + (binNum * 4),threshold);
	return(NO_ERR);
}

void setHwLMepEnableState(uint16_t rxLMepAddr, bool enable)
{
	uint32_t	data;

	if (enable)
	{
		mrHalRamRead(((rxLMepAddr * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, &data);
		data |= RX_LMEP_NUM_RAM_MEP_ENABLE_MASK;
		mrHalRamWrite(((rxLMepAddr * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, data);
	}
	else
	{
		mrHalRamRead(((rxLMepAddr * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, &data);
		data &= ~RX_LMEP_NUM_RAM_MEP_ENABLE_MASK;
		mrHalRamWrite(((rxLMepAddr * RX_LMEP_NUM_ENTRY_SIZE) + 1) + (RX_LMEP_NUM_TBL_PORT_0_BA), RX_LMEP_MAP_SEL, data);
	}
}

void setInvalidTlvFlag(rMepNum_t rMepNum)
{
	uint32_t	data;

	EGL_ASSERT(rMepNum <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead(rMepNum, RMEP_RAM_SEL, &data);
	data |= 0x20000000;
	mrHalRamWrite(rMepNum, RMEP_RAM_SEL, data);
}

void clrInvalidTlvFlag(rMepNum_t rMepNum)
{
	uint32_t	data;

	EGL_ASSERT(rMepNum <= (MAX_NUM_RMEPS),ERR_INVALID_ADDRESS);

	mrHalRamRead(rMepNum, RMEP_RAM_SEL, &data);
	if (data & 0x20000000)
	{
		mrHalRamWrite(rMepNum, RMEP_RAM_SEL, data & ~0x20000000);
	}
}
