/*******************************************************************************
 * (c) Copyright 2015 Microsemi Corporation.  All rights reserved.
 *
 *
 *
 * SVN $Revision: $
 * SVN $Date: $
 */
#include <api_oam_sdk/common/types/inc/linked_list.h>
#include <api_oam_sdk/metroam_hal/inc/mr_hal.h>
#include <api_oam_sdk/metroam_hal/inc/mr_hal.h>
#include <api_oam_sdk/service_bwp/src/svc_bwp_types.h>
#include <api_oam_sdk/service_evc/src/svc_evc_types.h>
#include <api_oam_sdk/service_interface/src/svc_iface_types.h>
#include <api_oam_sdk/service_l2cp/src/svc_l2cp_types.h>
#include <api_oam_sdk/system/inc/system.h>
#include <api_oam_sdk/table_access/inc/table_access.h>
#include "stdio.h"
#include "string.h"
#include "egl_types.h"
#include "egl_log.h"
#include "egl_assert.h"
#include "osal.h"

static iFaceEntry_t		iFaceArray[MAX_NUM_IFACES];
static uint16_t			log_handle					= 0;		// handle used to log messages for this module
static osMutex_t		iFaceListLock				= NULL;
static bool				iFaceInitialised			= false;

static uint16_t	g_mapList[MR_MAX_VLANS];		// Array for holding the list output from getListFromStringMap

#define LOCK_IFACE_LIST(timeout)	osRecursiveMutexTake(iFaceListLock,timeout)
#define UNLOCK_IFACE_LIST()			osRecursiveMutexGive(iFaceListLock)

/*
 * 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 setIFaceLogLevel(log_level_t logLevel)
{
	setModuleLogLevel(log_handle,logLevel);
}

/*
 * @brief	This sets the iFaceEntry values to their default
 *
 * In most cases this should only be done with iFaceLock enabled
 * to ensure thread safe operation
 */
static void setIFaceDefaults(iFaceEntry_t *iFaceEntry)
{
	memset(iFaceEntry,0,sizeof(iFaceEntry_t));
	iFaceEntry->cfg.svcIfaceType		= bUni2d1;
	iFaceEntry->cfg.frameFormat			= ff_noTag;
	iFaceEntry->eglCfg.admittance		= admitAll;
	iFaceEntry->eglCfg.useDEI			= true;
	strcpy(iFaceEntry->eglCfg.pcpEncoderMap,"0'2,1'2,2'2,3'2,4'2,5'2,6'2,7'2");
	strcpy(iFaceEntry->eglCfg.pcpDecoderMap,"0,2,4,6,8,10,12,14");
	strcpy(iFaceEntry->eglCfg.ingressDscpMap,"0:15,0:15,0:15,0:15");
}

/*
 * @brief Clears the IFACE list
 *
 * This should be called to initialise the IFACE list.
 * Any IFACEs on the list will be lost.
 */
static void clearIFaceList(void)
{
	uint16_t	k;

	// Initialise all entries in the IFACE store to defaults
	for (k = 0; k < MAX_NUM_IFACES; k++)
	{
		setIFaceDefaults(&iFaceArray[k]);
	}
	DO_LOG_DEBUG(log_handle,"Initialised the IFACE List");
}

static void initSvcUniTables(void)
{
	uint8_t		k;
	uint8_t		discard;
	pcpEntry_t	pcpEntry;

	for (k=0;k<8;k++)
	{
		pcpEntry.priority = k;
		pcpEntry.de = 0;

		// Populate the RxPCP on both ports with 1:1 mapping
		writeRxPcpTbl(k,wanPort,&pcpEntry);
		writeRxPcpTbl(k,lanPort,&pcpEntry);

		// Populate the TxPCP on both ports with 1:1 mapping
		writeTxPcpTbl(k*2,wanPort,k);
		writeTxPcpTbl(k*2,lanPort,k);
		writeTxPcpTbl(k*2 + 1,wanPort,k);
		writeTxPcpTbl(k*2 + 1,lanPort,k);
	}

	// Initialise the DSCP Decoder table: to "0:7,0:7,0:7,0:7,0:7,0:7,0:7,0:7"
	discard = 0;
	for (k=0;k<32;k++)
	{
		pcpEntry.priority = k % 8;
		pcpEntry.de = 0;
		writeDscpTbl(k*2,wanPort,&pcpEntry,discard);
		writeDscpTbl(k*2,lanPort,&pcpEntry,discard);
		pcpEntry.de = 1;
		writeDscpTbl(k*2 + 1,wanPort,&pcpEntry,discard);
		writeDscpTbl(k*2 + 1,lanPort,&pcpEntry,discard);
	}
}


/*
 * @brief	Called at device startup to initialise IFACE module
 *
 * Safe to call repeatedly.
 */
void iFaceInit(void)
{
	log_init();	// Initialises the logging system if it's not already initialised

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

	// Create a mutex to protect the IFACE list if we don't already have one
	if (iFaceListLock == NULL)
	{
		iFaceListLock = osRecursiveMutexCreate();
		ASSERT_NOT_NULL(iFaceListLock);
	}

	// If not already initialised clear the IFACE list for first use.
	if (!iFaceInitialised)
	{
		// Set the default logging level to NOTICE
		setModuleLogLevel(log_handle, eLOG_LEVEL_NOTICE);

		DO_LOG_DEBUG(log_handle,"Preparing the IFACE List for first use");
		LOCK_IFACE_LIST(0);
		clearIFaceList();
		UNLOCK_IFACE_LIST();

		// Make sure the HW is also set to the default values
		initSvcUniTables();

		iFaceInitialised = true;
	}

	// Initialise all the dependent modules
	uniInit();
	l2cpInit();
	bwpInit();
	evcInit();

}


/*
 * @brief Test if the supplied IFACE Index is valid
 */
bool isIFaceValid(iFace_t iFace)
{
	if ((iFace != wanPort) && (iFace != lanPort))
	{
		DO_LOG_DEBUG(log_handle,"The IFACE Index (%d) was invalid",iFace);
		return (false);
	}
	return(true);
}

/*
 * @brief Read the service IFACE configuration.
 */
int svcIfaceRead(iFace_t iFace, svcIfaceCfg_t *svcIFaceCfg, svcIfaceEglCfg_t *svcIfaceEglCfg, svcIfaceStatus_t *svcIfaceStatus)
{

	LOCK_IFACE_LIST(0);
	// Test is the iFace known and get it's associated iFace
	if (!isIFaceValid(iFace))
	{
		UNLOCK_IFACE_LIST();
		DO_LOG_INFO(log_handle,"Operation rejected due to invalid or nonexistent IFACE index (%lu)",iFace);
		return (1);
	}

	if (svcIFaceCfg != NULL)
	{
		memcpy(svcIFaceCfg, &iFaceArray[iFace].cfg, sizeof(svcIfaceCfg_t));
	}

	if (svcIfaceEglCfg != NULL)
	{
		memcpy(svcIfaceEglCfg, &iFaceArray[iFace].eglCfg, sizeof(svcIfaceEglCfg_t));
	}

	if (svcIfaceStatus != NULL)
	{
		svcIfaceStatus->maxEndPointPerVc = 1;
		svcIfaceStatus->maxVc = MAX_NUM_EVCS;
		svcIfaceStatus->type = bUni1d1 + bUni1d2 + bUni2d1  + bEnni; // We don't support bUni2d2
	}

	UNLOCK_IFACE_LIST();
	DO_LOG_DEBUG(log_handle,"Read info for IFACE (%lu)",iFace);
	return (2); // Operation accepted
}

/**
 * @brief	Write a new value to the selected service IFACE parameter.
 */
int svcIfaceWrite(iFace_t iFace, svcIfaceWrParam_t wrParam, void *paramValue)
{
	uint32_t	data;
	int16_t		k;
	uint16_t	listLen;
	pcpEntry_t	pcpEntry;

	LOCK_IFACE_LIST(0);
	// Test is the iFace known and get it's associated iFace
	if (!isIFaceValid(iFace))
	{
		UNLOCK_IFACE_LIST();
		DO_LOG_INFO(log_handle,"Operation rejected due to invalid or nonexistent IFACE index (%lu)",iFace);
		return (1);
	}

	if (paramValue == NULL)
	{
		UNLOCK_IFACE_LIST();
		DO_LOG_INFO(log_handle,"Operation rejected due to NULL value");
		return (3);
	}

	switch(wrParam)
	{
		case ifaceParam_svcIfaceType:
		{
			svcIfaceType_t	*svcIfaceTypePtr = (svcIfaceType_t*)paramValue;

			//check the value is one of the types supported
			switch(*svcIfaceTypePtr)
			{
				case bUni1d1:
				case bUni1d2:
				case bUni2d1:
				//case bUni2d2:		// Not supported
				case bEnni:
				//case bEnniVuni:	// Not supported
					break;
				default:
				{
					UNLOCK_IFACE_LIST();
					DO_LOG_INFO(log_handle,"Operation rejected due to invalid Iface Type %d",*svcIfaceTypePtr);
					return (3);
				}
			}

//			if (iFaceArray[iFace].cfg.svcIfaceType != *svcIfaceTypePtr)
//			{
				// Write the new value into the IFACE
				iFaceArray[iFace].cfg.svcIfaceType = *svcIfaceTypePtr;
				DO_LOG_NOTICE(log_handle,"On Interface with index %d the Interface Type value was changed to %d",iFace,*svcIfaceTypePtr);

				//TODO: add code to carry out action of changing Interface type on this interface
//			}
			break;
		}
		case ifaceParam_frameFormat:
		{
			frameFormat_t	*frameFormatPtr = (frameFormat_t*)paramValue;

			//check is the new value valid
			if ((*frameFormatPtr < ff_noTag) || (*frameFormatPtr > ff_stagCtag))
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid Frame Format %d",*frameFormatPtr);
				return (3);
			}

//			if (iFaceArray[iFace].cfg.frameFormat != *frameFormatPtr)
//			{
				// Write the new value into the IFACE
				iFaceArray[iFace].cfg.frameFormat = *frameFormatPtr;
				DO_LOG_NOTICE(log_handle,"On interface with index %lu the frame format was changed to %s",iFace,frameFormatToStr[*frameFormatPtr]);

				mrHalRegRead(DEV_CFG_REG_ADDR,&data);
				if (iFace == wanPort)
				{
					data &= ~DEV_CFG_REG_P0_TAG_TYPE_MASK; // clear the current TAG type
					data |= ((((uint32_t) iFaceArray[iFace].cfg.frameFormat - 1) << DEV_CFG_REG_P0_TAG_TYPE_OFFSET) & DEV_CFG_REG_P0_TAG_TYPE_MASK);
				}
				else
				{
					data &= ~DEV_CFG_REG_P1_TAG_TYPE_MASK; // clear the current TAG type
					data |= ((((uint32_t) iFaceArray[iFace].cfg.frameFormat - 1) << DEV_CFG_REG_P1_TAG_TYPE_OFFSET) & DEV_CFG_REG_P1_TAG_TYPE_MASK);
				}
				mrHalRegWrite(DEV_CFG_REG_ADDR,data);
//			}
			break;
		}
		case ifaceParam_ingressBwpGrpIndex:
		{
			bwpGrpIndex_t	*ingressBwpGrpIndexPtr = (bwpGrpIndex_t*)paramValue;

			//check is the index valid, 0 is an expected value meaning NO BWP Group index.
			if (*ingressBwpGrpIndexPtr != 0)
			{
				if (!svcBwpGrpIsBwpGrpIndexValid(*ingressBwpGrpIndexPtr))
				{
					UNLOCK_IFACE_LIST();
					DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown BWP group index %ul",*ingressBwpGrpIndexPtr);
					return (3);
				}
			}

//			if (iFaceArray[iFace].cfg.ingressBwpGrpIndex != *ingressBwpGrpIndexPtr)
//			{

#if NOT_SUPPORTED_ON_THIS_VERSION
				//TODO: add code to carry out action of changing BWP on this interface
				if (svcBwpGrpAddToEvc(PORT_ASSIGNED_EVC, iFace, *ingressBwpGrpIndexPtr) == 0)
				{

				}
#else
				// Only allow this value to be set to 0
				if (*ingressBwpGrpIndexPtr != 0)
				{
					UNLOCK_IFACE_LIST();
					DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown BWP group index %ul",*ingressBwpGrpIndexPtr);
					return (3);
				}
#endif
				// Write the new value into the IFACE
				iFaceArray[iFace].cfg.ingressBwpGrpIndex = *ingressBwpGrpIndexPtr;
				DO_LOG_NOTICE(log_handle,"On interface with index %lu the BWP group index was changed to %d",iFace,*ingressBwpGrpIndexPtr);
//			}
			break;
		}

		case ifaceParam_l2cpGrpIndex:
		{
			l2cpGrpIndex_t	*l2cpGrpIndexPtr = (l2cpGrpIndex_t*)paramValue;

			//check is the index valid, 0 is an expected value meaning NO L2CP Group index.
			if (*l2cpGrpIndexPtr != 0)
			{
				if (!svcL2cpGrpIsL2cpGrpIndexValid(*l2cpGrpIndexPtr))
				{
					UNLOCK_IFACE_LIST();
					DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown L2CP group index %ul",*l2cpGrpIndexPtr);
					return (3);
				}
			}

//			if (iFaceArray[iFace].cfg.l2cpGrpIndex != *l2cpGrpIndexPtr)
//			{
				// Write the new value into the IFACE
				iFaceArray[iFace].cfg.l2cpGrpIndex = *l2cpGrpIndexPtr;
				DO_LOG_NOTICE(log_handle,"On interface with index %lu the L2CP group index was changed to %d",iFace,*l2cpGrpIndexPtr);

				// Update the hardware with the new L2CP group settings
				addL2CPGroupToInterface(iFace,*l2cpGrpIndexPtr);
//			}
			break;
		}

		case ifaceParam_pcpEncoderMap:			// used at the TX port
		{
			char	*pcpEncoderMapPtr = (char*)paramValue;
#if 0
			if (strcmp(iFaceArray[iFace].eglCfg.pcpEncoderMap,pcpEncoderMapPtr) == 0)
			{
				// Strings are the same, i.e. no change!
				break;
			}
#endif
			// Typical values:
			// "0'2,1'2,2'2,3'2,4'2,5'2,6'2,7'2" => "0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7" => '8P0D'
			// "0,0,1,1,2,2,3,3,5,4,5,4,6,6,7,7" => '7P1D'
			if (!getListFromStringMap(pcpEncoderMapPtr,g_mapList,0,7,&listLen))
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown pcpEncoderMap value %s",pcpEncoderMapPtr);
				return (3);
			}

			// We need to ensure we get a list of 16 or we have an incomplete mapping
			if (listLen != 16)
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid number of value in pcpEncoderMap '%s' expected 16, got %d",pcpEncoderMapPtr,listLen);
				return (3);
			}

			for (k = 0; k < listLen; k++)
			{
				writeTxPcpTbl(k,iFace,(prio_t)g_mapList[k]);
			}
			strcpy(iFaceArray[iFace].eglCfg.pcpEncoderMap,pcpEncoderMapPtr);

			DO_LOG_NOTICE(log_handle,"On interface with index %d the pcpEncoderMap was changed to %s",iFace,pcpEncoderMapPtr);
			break;
		}
		case ifaceParam_pcpDecoderMap:		// used at the RX port
		{
			char	*pcpDecoderMapPtr = (char*)paramValue;

#if 0
			if (strcmp(iFaceArray[iFace].eglCfg.pcpDecoderMap,pcpDecoderMapPtr) == 0)
			{
				// Strings are the same, i.e. no change!
				break;
			}
#endif
			// Typical values:
			// "0,2,4,6,8,10,12,14" => '8P0D'
			// "0,2,4,6,9,8,12,14"  => '7P1D'
			if (!getListFromStringMap(pcpDecoderMapPtr,g_mapList,0,15,&listLen))
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown pcpDecoderMap value %s",pcpDecoderMapPtr);
				return (3);
			}

			// We need to ensure we get a list of 8 or we have an incomplete mapping
			if (listLen != 8)
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid number of value in pcpDecoderMap '%s' expected 8, got %d",pcpDecoderMapPtr,listLen);
				return (3);
			}

			for (k = 0; k < listLen; k++)
			{
				pcpEntry.de			= (bool)((g_mapList[k] & COS_TBL_DE_MASK) >> COS_TBL_DE_OFFSET) ;
				pcpEntry.priority	= (prio_t)((g_mapList[k] & COS_TBL_PRIO_MASK) >> COS_TBL_PRIO_OFFSET);
				writeRxPcpTbl(k,iFace,&pcpEntry);
			}
			strcpy(iFaceArray[iFace].eglCfg.pcpDecoderMap,pcpDecoderMapPtr);
			DO_LOG_NOTICE(log_handle,"On interface with index %d the pcpDecoderMap was changed to %s",iFace,pcpDecoderMapPtr);
			break;
		}
		case ifaceParam_ingressDscpMap:
		{
			char	*ingressDscpMapPtr = (char*)paramValue;
#if 0
			if (strcmp(iFaceArray[iFace].eglCfg.ingressDscpMap,ingressDscpMapPtr) == 0)
			{
				// Strings are the same, i.e. no change!
				break;
			}
#endif
			// Typical values:
			// "0'8,2'8,3'8,6'8,8'8,10'8,12'8,14'8" => "0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3....8"
			if (!getListFromStringMap(ingressDscpMapPtr,g_mapList,0,15,&listLen))
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown ingressDscpMap value %s",ingressDscpMapPtr);
				return (3);
			}

			// We need to ensure we get a list of 8 or we have an incomplete mapping
			if (listLen != 64)
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid number of value in ingressDscpMap '%s' expected 8, got %d",ingressDscpMapPtr,listLen);
				return (3);
			}

			for (k = 0; k < listLen; k++)
			{
				if (g_mapList[k] == 0xFFFF)
				{
					pcpEntry.de			= 0 ;
					pcpEntry.priority	= 0;
					writeDscpTbl(k,iFace,&pcpEntry,1);
				}
				else
				{
					pcpEntry.de			= (bool)((g_mapList[k] & COS_TBL_DE_MASK) >> COS_TBL_DE_OFFSET) ;
					pcpEntry.priority	= (prio_t)((g_mapList[k] & COS_TBL_PRIO_MASK) >> COS_TBL_PRIO_OFFSET);
					writeDscpTbl(k,iFace,&pcpEntry,0);
				}
			}
			strcpy(iFaceArray[iFace].eglCfg.ingressDscpMap,ingressDscpMapPtr);
			DO_LOG_NOTICE(log_handle,"On interface with index %d the ingressDscpMap was changed to %s",iFace,ingressDscpMapPtr);
			break;
		}
		case ifaceParam_vLanFilterList:
		{
			char		*vLanFilterListPtr = (char*)paramValue;
#if 0
			if (strcmp(iFaceArray[iFace].eglCfg.vLanFilterList,vLanFilterListPtr) == 0)
			{
				// Strings are the same, i.e. no change!
				break;
			}
#endif
			if (!getListFromStringMap(vLanFilterListPtr,g_mapList,0,4095,&listLen))
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown vlanFilterList value %s",vLanFilterListPtr);
				return (3);
			}

			// To ensure we only filter vlans in the filter list we must check the
			// current setting for all Vlans on the interface and update as necessary..
			restoreInterfaceFilteredVlans(iFace, g_mapList, listLen);

			strcpy(iFaceArray[iFace].eglCfg.vLanFilterList,vLanFilterListPtr);
			DO_LOG_NOTICE(log_handle,"On interface with index %d the vlanFilterList was changed to %s",iFace,vLanFilterListPtr);
			break;
		}
		case ifaceParam_admittance:
		{
			admittance_t		*admittancePtr = (admittance_t*)paramValue;

#if 0
			if (iFaceArray[iFace].eglCfg.admittance == *admittancePtr)
			{
				// Values are the same, no change!
				break;
			}
#endif
			if (*admittancePtr > admitVlanOnly)
			{
				UNLOCK_IFACE_LIST();
				DO_LOG_INFO(log_handle,"Operation rejected due to invalid or unknown admittance value %d",*admittancePtr);
				return (3);
			}

			mrHalRegRead(DEV_CFG_REG_ADDR,&data);
			if (iFace == wanPort)
			{
				data &= ~DEV_CFG_REG_P0_ADMIT_RULE_MASK;
				data |= (((uint32_t)*admittancePtr) << DEV_CFG_REG_P0_ADMIT_RULE_OFFSET) & DEV_CFG_REG_P0_ADMIT_RULE_MASK;
			}
			else
			{
				data &= ~DEV_CFG_REG_P1_ADMIT_RULE_MASK;
				data |= (((uint32_t)*admittancePtr) << DEV_CFG_REG_P1_ADMIT_RULE_OFFSET) & DEV_CFG_REG_P1_ADMIT_RULE_MASK;
			}
			mrHalRegWrite(DEV_CFG_REG_ADDR,data);
			iFaceArray[iFace].eglCfg.admittance = *admittancePtr;
			DO_LOG_NOTICE(log_handle,"On interface with index %d the admittance value was changed to %s",iFace,admittanceToStr[*admittancePtr]);
			break;
		}
		case ifaceParam_useDEI:
		{
			bool		*useDeiPtr = (bool*)paramValue;

#if 0
			if (iFaceArray[iFace].eglCfg.useDEI == *useDeiPtr)
			{
				// Values are the same, no change!
				break;
			}
#endif
			mrHalRegRead(DEV_CFG_REG_ADDR,&data);
			if (iFace == wanPort)
			{
				data &= ~DEV_CFG_REG_P0_USE_DEI_MASK;
				data |= (((uint32_t)*useDeiPtr) << DEV_CFG_REG_P0_USE_DEI_OFFSET) & DEV_CFG_REG_P0_USE_DEI_MASK;
			}
			else
			{
				data &= ~DEV_CFG_REG_P1_USE_DEI_MASK;
				data |= (((uint32_t)*useDeiPtr) << DEV_CFG_REG_P1_USE_DEI_OFFSET) & DEV_CFG_REG_P1_USE_DEI_MASK;
			}
			mrHalRegWrite(DEV_CFG_REG_ADDR,data);
			iFaceArray[iFace].eglCfg.useDEI = *useDeiPtr;
			DO_LOG_NOTICE(log_handle,"On interface with index %d the useDEI value was changed to %s",iFace,*useDeiPtr ? "True" : "False");
			break;
		}
		case ifaceParam_colorAware:
		{
			bool	*colorAwarePtr = (bool*)paramValue;

			mrHalRegRead(DEV_CFG_REG_ADDR,&data);
			if (iFace == wanPort)
			{
				data &= ~DEV_CFG_REG_P0_COLOR_AWARE_MASK;
				data |= (((uint32_t)*colorAwarePtr) << DEV_CFG_REG_P0_COLOR_AWARE_OFFSET) & DEV_CFG_REG_P0_COLOR_AWARE_MASK;
			}
			else
			{
				data &= ~DEV_CFG_REG_P1_COLOR_AWARE_MASK;
				data |= (((uint32_t)*colorAwarePtr) << DEV_CFG_REG_P1_COLOR_AWARE_OFFSET) & DEV_CFG_REG_P1_COLOR_AWARE_MASK;
			}
			mrHalRegWrite(DEV_CFG_REG_ADDR,data);
			iFaceArray[iFace].eglCfg.colorAware = *colorAwarePtr;
			DO_LOG_NOTICE(log_handle,"On interface with index %d the colorAware was changed to %s",iFace,*colorAwarePtr?"True" : "False");
			break;
		}
		case ifaceParam_colorForward:
		{
			bool	*colorForwardPtr = (bool*)paramValue;

			mrHalRegRead(DEV_CFG_REG_ADDR,&data);
			if (iFace == wanPort)
			{
				data &= ~DEV_CFG_REG_P0_COLOR_FWD_MASK;
				data |= (((uint32_t)*colorForwardPtr) << DEV_CFG_REG_P0_COLOR_FWD_OFFSET) & DEV_CFG_REG_P0_COLOR_FWD_MASK;
			}
			else
			{
				data &= ~DEV_CFG_REG_P1_COLOR_FWD_MASK;
				data |= (((uint32_t)*colorForwardPtr) << DEV_CFG_REG_P1_COLOR_FWD_OFFSET) & DEV_CFG_REG_P1_COLOR_FWD_MASK;
			}
			mrHalRegWrite(DEV_CFG_REG_ADDR,data);
			iFaceArray[iFace].eglCfg.colorForward = *colorForwardPtr;
			DO_LOG_NOTICE(log_handle,"On interface with index %d the colorForward was changed to %s",iFace,*colorForwardPtr?"True" : "False");
			break;
		}
		default:
		{
			UNLOCK_IFACE_LIST();
			DO_LOG_INFO(log_handle,"Operation rejected due to the selected managed object being Read-Only");
			return (2);
			break;
		}
	}
	UNLOCK_IFACE_LIST();
	return (4); // Operation accepted

}

frameFormat_t getPortFrameFormat(iFace_t iFace)
{
	return (iFaceArray[iFace].cfg.frameFormat); // Operation accepted
}
