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

#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/metroam_hal/inc/mr_hal.h>
#include <api_oam_sdk/table_config/inc/table_config.h>

/*
 * @brief Change the active state of the tunnel mode on an interface
 */
void setTunnelModeActive(iFace_t iface, bool value)
{
	uint32_t	data;

	if (iface == wanPort)
	{
		mrHalRegRead(DEV_CFG_REG_ADDR,&data);
		if (value)
		{
			// Set the bit
			data |= DEV_CFG_REG_P0_TUNNEL_MASK;
		}
		else
		{
			// Clear the bit
			data &= ~DEV_CFG_REG_P0_TUNNEL_MASK;
		}
		mrHalRegWrite(DEV_CFG_REG_ADDR,data);
	}
}

/*
 * @brief Check if the tunnel mode is active on an interface
 */
bool isTunnelModeActive(iFace_t iface)
{
	uint32_t	data;

	if (iface == wanPort)
	{
		mrHalRegRead(DEV_CFG_REG_ADDR,&data);
		if (data & DEV_CFG_REG_P0_TUNNEL_MASK)
			return(true);
		else
			return(false);
	}
	else
	{
		return(false);
	}
}

/*
 * @brief Get the Vlan, prio and DE values for the tunnel tag on an interface
 */
void getTunnelVid(iFace_t iface, vidEntry_t *tunnelVid)
{
	uint32_t	data;

	if (iface == wanPort)
	{
		mrHalRegRead(CPU_MGNT_VLAN_CTRL_REG_ADDR,&data);
		data = (data & CPU_MGNT_VLAN_CTRL_TUNNEL_TAG_MASK) >> CPU_MGNT_VLAN_CTRL_TUNNEL_TAG_OFFSET;

		tunnelVid->vlan = (uint16_t) ((data & MR_TAG_VLAN_MASK) >> MR_TAG_VLAN_OFFSET);
		tunnelVid->de 	= 0;		// tunnel tags always have DE = 0
		tunnelVid->prio = (uint8_t) ((data & 0x7000) >> (MR_TAG_PRIO_OFFSET-1));			// This is unconventional - but matches HW use.
	}
	else
	{
		tunnelVid->de = false;
		tunnelVid->prio = 0;
		tunnelVid->vlan = 0;
	}

}



/*
 * @brief Get the Vlan, prio and DE values for the tunnel tag on an interface
 */
void setTunnelVid(iFace_t iface, vidEntry_t tunnelVid)
{
	uint32_t	data;
	uint32_t	vid;

	if (iface == wanPort)
	{
		vid = ((((uint32_t) tunnelVid.prio) << (MR_TAG_PRIO_OFFSET-1)) &  0x7000) |			// This is unconventional - but matches HW use.
			//((((uint32_t) tunnelVid.de) << MR_TAG_DE_OFFSET) & MR_TAG_DE_MASK) |  		// de is always set to 0 by HW
			((((uint32_t) tunnelVid.vlan) << MR_TAG_VLAN_OFFSET) & MR_TAG_VLAN_MASK);
		vid = (vid << CPU_MGNT_VLAN_CTRL_TUNNEL_TAG_OFFSET);

		mrHalRegRead(CPU_MGNT_VLAN_CTRL_REG_ADDR,&data);
		data = (data & ~CPU_MGNT_VLAN_CTRL_TUNNEL_TAG_MASK) | vid;
		mrHalRegWrite(CPU_MGNT_VLAN_CTRL_REG_ADDR,data);
	}
}


/*
 * @brief Returns the Ethertype value for the tunnel tag on an interface
 */
uint16_t getTunnelTagId(iFace_t iface)
{
	if (iface == wanPort)
	{
		return(getSTagId());
	}
	return (0);
}

/*
 * @brief Set the Ethertype value for the tunnel tag on an interface
 */
void setTunnelTagId(iFace_t iface, uint16_t tagId)
{

}
