zte's code,first commit

Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/Kconfig b/ap/os/linux/linux-3.4.x/drivers/net/gmac/Kconfig
new file mode 100644
index 0000000..b5118c1
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/Kconfig
@@ -0,0 +1,30 @@
+#
+# gmac driver configuration
+#
+
+# menuconfig NET_ZX29_GMAC
+#	bool  "ZTE 7520V2 NET GMAC"
+#	default Y
+#	depends on NET
+#	---help---
+#	  This section contains gmac config 
+
+# if NET_ZX29_GMAC
+
+config NET_ZX29_GMAC
+	bool "ZTE 7520V2 NET GMAC"
+	default y
+	
+config NET_ZX29_GMAC_PHY
+      bool "ZTE 7520V2 NET GMAC PHY"
+	  depends on NET_ZX29_GMAC
+      default y
+
+ 
+config NET_ZX29_GMAC_SWITCH
+      bool "ZTE 7520V2 NET GMAC SWITCH"
+	  depends on NET_ZX29_GMAC
+      default y
+
+
+# endif # NET_ZX29_GMAC
\ No newline at end of file
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/Makefile b/ap/os/linux/linux-3.4.x/drivers/net/gmac/Makefile
new file mode 100644
index 0000000..45c71f2
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/Makefile
@@ -0,0 +1,22 @@
+#
+# Makefile for the Linux Ethernet gmac driver.
+#
+
+#obj-$(CONFIG_NET_ZX29_GMAC)					+= zx_gmac.o
+
+#obj-$(CONFIG_NET_ZX29_GMAC_PHY) 			+= phy/
+
+obj-$(CONFIG_NET_ZX29_GMAC)  			+= gmac.o
+
+
+ifeq ($(CONFIG_NET_ZX29_GMAC_PHY),y)
+gmac-y +=  zx_gmac.o \
+						phy/zx_gmac_phy.o 
+endif
+
+ifeq ($(CONFIG_NET_ZX29_GMAC_SWITCH),y)					 
+gmac-y +=  zx_gmac.o \
+						switch/rtk_api.o \
+						switch/rtl8306e_asicdrv.o \
+						switch/zx_gmac_switch.o 
+endif
\ No newline at end of file
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/phy/Makefile b/ap/os/linux/linux-3.4.x/drivers/net/gmac/phy/Makefile
new file mode 100644
index 0000000..cef4e1f
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/phy/Makefile
@@ -0,0 +1,4 @@
+# Makefile for linux/drivers/net/gmac_device_phy
+#
+
+#obj-$(CONFIG_NET_ZX29_GMAC_PHY) += zx_gmac_phy.o
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/phy/zx_gmac_phy.c b/ap/os/linux/linux-3.4.x/drivers/net/gmac/phy/zx_gmac_phy.c
new file mode 100644
index 0000000..1d30656
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/phy/zx_gmac_phy.c
@@ -0,0 +1,1199 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2011, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾ 

+*

+* ÎļþÃû³Æ:	zx_gmac.c

+* Îļþ±êʶ:

+* ÄÚÈÝÕªÒª: sanchips Serial GMAC Çý¶¯ 

+* ÆäËü˵Ã÷:	±¾ÏµÍ³ËùÓÐÍâÉèʹÓù̶¨Ó³É䣬´Ó×ÊÔ´ÖлñÈ¡µÄµØÖ·¾ùΪÐéÄâµØÖ·£¬¹ÊÎÞÐëioremap

+*			Èç¹ûϵͳÖÐʹÓö¯Ì¬Ó³É䣬ÇëÐÞ¸Äprobeº¯ÊýÒÔÐÞ¶©µØÖ·Ó³Éä 

+* µ±Ç°°æ±¾:	1.1

+* ×÷¡¡¡¡Õß:	¹ùÒýÐã 

+* Íê³ÉÈÕÆÚ: 2011-8-1

+*

+* Ð޸ļǼ1

+* ÐÞ¸ÄÈÕÆÚ:

+* °æ±¾¡¡ºÅ:

+* Ð޸ġ¡ÈË:

+* ÐÞ¸ÄÄÚÈÝ:

+*

+*******************************************************************************/

+

+#include "../zx_gmac.h"

+#include <linux/wakelock.h>

+#include <linux/delay.h>

+

+/*-----------------------------------------------------------------------------------

+* ºêÒåÒå

+------------------------------------------------------------------------------*/

+#define  GMAC_NO_INT

+#define CONFIG_PHY_TIMER_SET

+#define   GMAC_PHY_PLUG_NAME          "eth_state"

+#define PHY_RTL8201					0x00008200

+#define PHY_8E1119R					0x01410E80

+#define PHY_KSZ8051					0x00221550

+#define PHY_KSZ8081                 0x00221560

+#define PHY_IP101A                  0x02430C50

+#define PHY_IP101G                  0x02430c54

+

+

+/*phy reg */

+

+/* PHY page mode control Register. */

+#define MII_PAGECTRL             		20

+

+

+

+/* WOL+ control Register, page4 register16. */

+#define WOL_CTRL             		16

+#define WOL_CTRL_EN             		0x8000

+#define WOL_CTRL_MASTER             	0x4000

+#define WOL_CTRL_INTR_ACT_HIGH          0x2000

+#define WOL_CTRL_INTR_12_RSVD           0x1000//reserved

+#define WOL_CTRL_SENSE_MAGIC_PKT        0x800

+#define WOL_CTRL_SENSE_ANY_PKT          0x400

+#define WOL_CTRL_SENSE_DUT              0x200

+#define WOL_CTRL_DNSPD_EN               0x100

+#define WOL_CTRL_TIMER_SEL              0xC0

+#define WOL_CTRL_TIMER_30S              0x00<<6

+#define WOL_CTRL_TIMER_3M               0x01<<6

+#define WOL_CTRL_TIMER_10M              0x11<<6

+#define WOL_CTRL_MANUAL_SET             0x20

+

+

+/* WOL+ status Register, page17 register17. */

+#define WOL_SR             		17

+#define WOL_SR_INTR_DIS             	0x8000

+

+

+/*  Interrupt status Register, page16 register17. */

+#define INT_SR             		        17

+#define INT_SR_INTR_PIN_USED            0x8000

+#define INT_SR_ALL_MASK                 0x800

+#define INT_SR_SPEED_MASK               0x400

+#define INT_SR_DUPLEX_MASK              0x200

+#define INT_SR_LINK_MASK                0x100

+#define INT_SR_INT_STATUS               0x8

+#define INT_SR_SPEED_INT                0x4

+#define INT_SR_DUPLEX_INT               0x2

+#define INT_SR_LINK_INT                 0x1

+

+

+/*  Interrupt status Register, page16 register29. */

+#define IO_SPEC_CR             		        29

+#define IO_SPEC_CR_SEL_INTR32               0x4

+

+/****************************************************************************

+* 	                               Global Variables

+****************************************************************************/

+unsigned                  phy_id_globle;

+int page_select = 0;

+static E_LINK_STATE phy_port_state=0;

+int int_count = 0;

+struct kset *kset_gmac;

+struct kobject *gmackobj = NULL;

+struct kobject *phykobj = NULL;

+static unsigned int phy_plug = 0;

+static unsigned int phy_init_state = 0;

+static unsigned int phy_init_flag = 1;

+static unsigned long phy_init_time_start = 0;

+static unsigned long phy_init_time_now = 0;

+static char  phy_init_invalid[]="invalid";

+static char  phy_on[]="phy_on";

+static char  phy_off[]="phy_off";

+static char  invalid[]="invalid";

+struct wake_lock wlock_PHY;

+struct wake_lock wlock_PHY_first;

+struct wake_lock phy_negotiation_lock;

+struct timer_list		phy_timer;	

+typedef enum{

+     GMAC_PHY_PLUGIN = 0,

+     GMAC_PHY_PLUGOUT,

+     GMAC_SWITCH_NUM,

+}phy_notify_event;

+

+#ifdef GMAC_NO_INT

+struct semaphore gmac_plug_thread_sema;

+struct net_device *g_gmac_phy_dev   = NULL;

+static unsigned int g_mac_phy_state = 0;

+#endif

+

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪµ÷ÓõÄÍⲿº¯Êý½Ó¿Ú

+* 

+* 

+------------------------------------------------------------------------------*/

+extern struct net_device* 	gmac_net_dev;

+extern int gmac_mii_read(struct net_device *dev, int phy, int reg);

+extern void gmac_mii_write(struct net_device *dev, int phy, int reg, int val);

+extern void gmac_set_speed_duplex(struct net_device * dev,E_SPEED speed,E_DUPLEX duplex);

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪÄÚ²¿º¯Êý˵Ã÷

+* 

+* 

+------------------------------------------------------------------------------*/

+static irqreturn_t zx_phy_int_threadhandler(int irq, void *dev_id);

+static irqreturn_t zx_phy_int(int irq, void *dev_id);

+static void zx_phy_timer(unsigned long data);

+static void kobj_gmac_release(struct kobject *kobject);

+static void kobj_gmac_del(struct kobject *kobject);

+E_LINK_STATE gmac_phy_link_status(struct net_device *dev);

+#ifdef GMAC_NO_INT

+//void zx_gmac_plug_thread(unsigned long dev_id);

+void zx_gmac_plug_thread_ms(unsigned long dev_id);

+#endif

+

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪ´úÂëÕýÎÄÇø

+* 

+* 

+------------------------------------------------------------------------------*/

+// É趨µ±Ç°µÄģʽ¡¢Ë«¹¤

+static int phy_set_speed_duplex(struct net_device *dev, E_SPEED speed, E_DUPLEX duplex)

+{

+    unsigned			val;

+    struct zx_net_dev* 	prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    int					phy 	= prv->phy;

+    volatile unsigned 	*gmac 	= (unsigned*)dev->base_addr;

+    //×¢Ò⣺Ŀǰδ¿¼ÂÇǧÕ×Çé¿ö

+    if((eSPEED_END <= speed) || (eDUPLEX_END <= duplex))

+    {

+        return -1;

+    }

+    spin_lock_irq(&prv->phy_lock);

+    switch(prv->phy_id)

+    {

+        case PHY_IP101G:

+        {

+            if(eSET_AUTO_NEGO == prv->set_duplex_mode)

+            {

+                val = gmac_mii_read(dev, phy, MII_ADVERTISE);

+                val &= ~(ADVERTISE_10HALF|ADVERTISE_10FULL|ADVERTISE_100HALF|ADVERTISE_100FULL);//0x1E1;clear speed and duplex setting

+                gmac_mii_write(dev, phy, MII_ADVERTISE, val);

+                

+                val	= gmac_mii_read(dev, phy, MII_BMCR);

+                val &= ~(BMCR_ANENABLE|BMCR_ANRESTART);//0x1200;

+                gmac_mii_write(dev, phy, MII_BMCR, val);				// ¹Ø±Õ×ÔЭÉÌ

+            }

+            

+            val	= gmac_mii_read(dev, phy, MII_BMCR);				//¶ÁÈ¡µ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+            val &= ~(BMCR_SPEED100|BMCR_FULLDPLX);//0x2100;		//Çå¿Õµ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+

+            if(eSPEED_100M == speed)

+            {

+                val |= BMCR_SPEED100;		//°´Óû§ÐèÇóÅäÖÃËÙ¶È

+            }

+            if(eDUPLEX_FULL == duplex)

+            {

+                val |= BMCR_FULLDPLX;		//°´Óû§ÐèÇóÅäÖÃË«¹¤

+            }

+            gmac_mii_write(dev, phy, MII_BMCR, val);

+            

+            prv->speed	= speed;

+            prv->duplex	= duplex;

+            

+            gmac_set_speed_duplex(dev,speed,duplex);

+            break;

+        }

+        case PHY_8E1119R:

+        {

+        //Ñ¡ÔñµÚ0Ò³¼Ä´æÆ÷

+        gmac_mii_write(dev,phy, 22, 0);

+        if(eSET_AUTO_NEGO == prv->set_duplex_mode)

+        {

+            val	= gmac_mii_read(dev, phy, 0);

+            val &= ~0x1200;

+            gmac_mii_write(dev, phy, 0, val);				// ¹Ø±Õ×ÔЭÉÌ

+        }

+        //Ñ¡ÔñµÚ2Ò³¼Ä´æÆ÷

+        gmac_mii_write(dev, phy, 22, 0x2);

+        //×¢Ò⣺Ŀǰ²»Ö§³Ö1000M£¬¹Êµ±Ç°(eSPEED_1000M == speed)µÄÇé¿ö²»´æÔÚ£¬ÇÒ䶨Òå

+        if		(eSPEED_10M == speed) gmac_mii_write(dev, phy, 21, 0x4);	//Ñ¡Ôñ¹Ü½ÅĬÈÏʱÖÓΪ10M

+        else if	(eSPEED_100M == speed) gmac_mii_write(dev, phy, 21, 0x5);	//Ñ¡Ôñ¹Ü½ÅĬÈÏʱÖÓΪ100M

+        //Ñ¡ÔñµÚ0Ò³¼Ä´æÆ÷

+        gmac_mii_write(dev,phy, 22, 0);

+        val	= gmac_mii_read(dev, phy, 0);				//¶ÁÈ¡µ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+        val &= ~0x2140;								//Çå¿Õµ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+        val |= (speed << 13) | (duplex << 8);		//°´Óû§ÐèÇóÅäÖÃËٶȺÍË«¹¤×´Ì¬

+        gmac_mii_write(dev, phy, 0, val);

+        prv->speed	= speed;

+        prv->duplex	= duplex;

+        val	= MAC(0x0000) | 1<<11 | 1<<14;	// ĬÈÏΪ100Mȫ˫¹¤

+        if(eSPEED_10M == prv->speed)

+        {

+            val &= ~(1 << 14);					// 10M

+        }

+        if(eDUPLEX_HALF == prv->duplex)

+        {

+            val &= (~(1 << 11));					// °ëË«¹¤

+            val |= (1 << 16);

+        }

+        MAC(0x0000) = val;

+        break;

+        }

+        case PHY_KSZ8051:

+        {

+        if(eSET_AUTO_NEGO == prv->set_duplex_mode)

+        {

+            val	= gmac_mii_read(dev, phy, 0);

+            val &= ~0x1200;

+            gmac_mii_write(dev, phy, 0, val);				// ¹Ø±Õ×ÔЭÉÌ

+        }

+        val	= gmac_mii_read(dev, phy, 0);				//¶ÁÈ¡µ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+        val &= ~0x2100;								//Çå¿Õµ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+        val |= (speed << 13) | (duplex << 8);		//°´Óû§ÐèÇóÅäÖÃËٶȺÍË«¹¤×´Ì¬

+        gmac_mii_write(dev, phy, 0, val);

+        prv->speed	= speed;

+        prv->duplex	= duplex;

+        val	= MAC(0x0000) | 1<<11 | 1<<14;	// ĬÈÏΪ100Mȫ˫¹¤

+        if(eSPEED_10M == prv->speed)

+        {

+            val &= ~(1 << 14);					// 10M

+        }

+

+        if(eDUPLEX_HALF == prv->duplex)

+        {

+            val &= (~(1 << 11));					// °ëË«¹¤

+            val |= (1 << 16);

+        }

+        MAC(0x0000) = val;

+

+        break;

+        }

+        case PHY_KSZ8081:

+        {

+            if(eSET_AUTO_NEGO == prv->set_duplex_mode)

+            {

+                val	= gmac_mii_read(dev, phy, 0);

+                val &= ~0x1200;

+                gmac_mii_write(dev, phy, 0, val);				// ¹Ø±Õ×ÔЭÉÌ

+            }

+            val	= gmac_mii_read(dev, phy, 0);				//¶ÁÈ¡µ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+            val &= ~0x2100;								//Çå¿Õµ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+            val |= (speed << 13) | (duplex << 8);		//°´Óû§ÐèÇóÅäÖÃËٶȺÍË«¹¤×´Ì¬

+            gmac_mii_write(dev, phy, 0, val);

+            prv->speed	= speed;

+            prv->duplex	= duplex;

+            val	= MAC(0x0000) | 1<<11 | 1<<14;	// ĬÈÏΪ100Mȫ˫¹¤

+            if(eSPEED_10M == prv->speed)

+            {

+                val &= ~(1 << 14);					// 10M

+            }

+            if(eDUPLEX_HALF == prv->duplex)

+            {

+                val &= (~(1 << 11));					// °ëË«¹¤

+                val |= (1 << 16);

+            }

+            MAC(0x0000) = val;

+            break;

+        }

+        case PHY_RTL8201:

+        default:

+        {

+            if(eSET_AUTO_NEGO == prv->set_duplex_mode)

+            {

+                val	= gmac_mii_read(dev, phy, 0);

+                val &= ~0x1200;

+                gmac_mii_write(dev, phy, 0, val);				// ¹Ø±Õ×ÔЭÉÌ

+            }

+            val	= gmac_mii_read(dev, phy, 0);				//¶ÁÈ¡µ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+            val &= ~0x2100;								//Çå¿Õµ±Ç°µÄËٶȺÍË«¹¤×´Ì¬

+            val |= (speed << 13) | (duplex << 8);		//°´Óû§ÐèÇóÅäÖÃËٶȺÍË«¹¤×´Ì¬

+            gmac_mii_write(dev, phy, 0, val);

+            prv->speed	= speed;

+            prv->duplex	= duplex;

+            val	= MAC(0x0000) | 1<<11 | 1<<14;	// ĬÈÏΪ100Mȫ˫¹¤

+            if(eSPEED_10M == prv->speed)

+            {

+              val &= ~(1 << 14);					// 10M

+            }

+            if(eDUPLEX_HALF == prv->duplex)

+            {

+                val &= (~(1 << 11));					// °ëË«¹¤

+                val |= (1 << 16);

+            }

+            MAC(0x0000) = val;

+            break;

+        }

+    }

+    //¼ì²âÁ¬½Ó״̬£¬´ËʱÓÉÓÚ¸ÕÅäÖÃËÙÂÊ¡¢Ë«¹¤Ä£Ê½£¬¿Ï¶¨Ó¦¸ÃÊÇδÁ¬½Ó״̬¡£

+    if(netif_carrier_ok(dev))	netif_carrier_off(dev);

+    prv->link	= eLINK_OFF;

+    //É趨µ±Ç°µÄÊÖ¶¯×´Ì¬

+    if		       ((eSPEED_10M  == prv->speed) && (eDUPLEX_FULL == prv->duplex)) prv->set_duplex_mode = eSET_10M_FULL_DUPLEX;

+    else if	((eSPEED_100M == prv->speed) && (eDUPLEX_HALF == prv->duplex)) prv->set_duplex_mode = eSET_100M_HALF_DUPLEX;

+    else if	((eSPEED_100M == prv->speed) && (eDUPLEX_FULL == prv->duplex)) prv->set_duplex_mode = eSET_100M_FULL_DUPLEX;

+    else if	((eSPEED_10M  == prv->speed) && (eDUPLEX_HALF == prv->duplex)) prv->set_duplex_mode = eSET_10M_HALF_DUPLEX;

+    spin_unlock_irq(&prv->phy_lock);

+    return 0;

+}

+

+// PHYµÄ×Ô¶¯Ð­ÉÌ

+static int phy_negotiation(struct net_device *dev)

+{

+    unsigned			val;

+    struct zx_net_dev* 	prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    int phy 	= prv->phy;

+    int autotimeout = 30000;

+    switch(prv->phy_id)

+    {

+             case PHY_IP101G:

+        {

+            //set auto-neg advertisement capabilities to 10/100 half/full

+            val = ADVERTISE_100FULL|ADVERTISE_100HALF|ADVERTISE_10FULL|ADVERTISE_10HALF|ADVERTISE_CSMA;

+            gmac_mii_write(dev, phy, MII_ADVERTISE, val);

+            

+            val	= gmac_mii_read(dev, phy, MII_BMCR);

+            val |= BMCR_ANENABLE | BMCR_ANRESTART;

+            gmac_mii_write(dev, phy, MII_BMCR, val);

+            

+            while(autotimeout)

+	    {

+	        val = gmac_mii_read(dev,phy, MII_BMSR);

+	        if(val&BMSR_ANEGCOMPLETE)

+	        {

+	  	    break;

+	        }

+	        autotimeout--;

+	    };

+           if(autotimeout == 0)

+    	    {

+    		printk("phy IP101G auto negotiation failed\n");   //add log

+    		return -1;

+    	    }           

+            break;            

+        }

+        case PHY_IP101A:

+        {

+            //set auto-neg advertisement capabilities to 10/100 half/full

+            val = ADVERTISE_100FULL|ADVERTISE_100HALF|ADVERTISE_10FULL|ADVERTISE_10HALF|ADVERTISE_CSMA;

+            gmac_mii_write(dev, phy, MII_ADVERTISE, val);

+            

+            val	= gmac_mii_read(dev, phy, MII_BMCR);

+            val |= BMCR_ANENABLE | BMCR_ANRESTART;

+            gmac_mii_write(dev, phy, MII_BMCR, val);

+            

+            while(autotimeout)

+	    {

+	        val = gmac_mii_read(dev,phy, MII_BMSR);

+	        if(val&BMSR_ANEGCOMPLETE)

+	        {

+	  	    break;

+	        }

+	        autotimeout--;

+	    };

+           if(autotimeout == 0)

+    	    {

+    		return -1;

+    	    }           

+            break;           

+        }

+        case PHY_8E1119R:

+        {

+            //Ñ¡ÔñµÚ2Ò³¼Ä´æÆ÷

+            gmac_mii_write(dev, phy, 22, 0x2);

+            //Ñ¡Ôñ¹Ü½ÅĬÈÏʱÖÓΪ100M

+            gmac_mii_write(dev, phy, 21, 0x5);

+            //Ñ¡ÔñµÚ0Ò³¼Ä´æÆ÷

+            gmac_mii_write(dev,phy, 22, 0);

+            //¹Ø±Õ1000M×ÔЭÉ̹¦ÄÜ£¬ÒòΪĿǰGMACÄ£¿é²»Ö§³Ö1000M¹¦ÄÜ

+            val = gmac_mii_read(dev,phy,9);

+            val &= ~0x0300;

+            gmac_mii_write(dev,phy, 9, val);

+            val	= gmac_mii_read(dev, phy, 0);

+            val |= 0x1200;

+            gmac_mii_write(dev, phy, 0, val);             // Æô¶¯×ÔЭÉÌ

+            break;

+        }

+        case PHY_KSZ8051:

+        {

+            val	= gmac_mii_read(dev, phy, 0);

+            val |= 0x1200;

+            gmac_mii_write(dev, phy, 0, val);				// Æô¶¯×ÔЭÉÌ

+            break;

+            }

+            case PHY_KSZ8081:

+            {

+            val	= gmac_mii_read(dev, phy, 0);

+            val |= 0x1200;

+            gmac_mii_write(dev, phy, 0, val);				// Æô¶¯×ÔЭÉÌ

+            break;

+        }

+        case PHY_RTL8201:

+        default:

+        {

+            val	= gmac_mii_read(dev, phy, 0);

+            val |= 0x1200;

+            gmac_mii_write(dev, phy, 0, val);				// Æô¶¯×ÔЭÉÌ

+            break;

+        }

+    }

+    spin_lock_irq(&prv->phy_lock);

+    //¼ì²âÁ¬½Ó״̬£¬´ËʱÓÉÓÚ¸ÕÅäÖÃ×ÔЭÉÌ£¬¿Ï¶¨Ó¦¸ÃÊÇδÁ¬½Ó״̬¡£

+    if(netif_carrier_ok(dev))	netif_carrier_off(dev);

+    prv->link					= eLINK_OFF;

+    prv->set_duplex_mode		= eSET_AUTO_NEGO;

+    prv->autoneg                =AUTONEG_ENABLE;

+    spin_unlock_irq(&prv->phy_lock);

+    return 0;

+}

+

+// PHY³õʼ»¯

+static int gmac_phy_init(struct net_device *dev)

+{

+    int				i;

+    int 				phy;

+    short unsigned		val = 0;

+    short unsigned  val_wol_enable = 0;

+    unsigned int          	tval = 0;

+    unsigned                  plug_flag =0;

+	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;

+    int ret;

+    int hh;

+    int vv;

+    int ext_int6_no;

+    int autotimeout = 500;

+    struct zx_net_dev* 	prv	= (struct zx_net_dev*)netdev_priv(dev);

+    int value = 0;

+

+    

+    // »ñÈ¡µÚÒ»¸öPHYµÄÐòºÅ¼°ID

+    for(phy = 0; phy <= 31; phy++)

+    {

+        val				= gmac_mii_read(dev, phy, MII_BMSR);

+		printk("gmac_phy_init_mii_read, val:0x%x\n",val);

+

+        if((0 != val) && (0xFFFF != val))

+        {

+            prv->phy 	= phy;

+            prv->phy_id	= (gmac_mii_read(dev, phy, MII_PHYSID1) << 16) | gmac_mii_read(dev, phy, MII_PHYSID2);

+	  		phy_id_globle   =  prv->phy_id;

+            //prv->phy_id &= ~0xf;//Ë︣ɽÌí¼Ó£¬ÒòΪһ°ãÀ´½²£¬PHY ID2µÄ×îºó4BIT¶¼ÊÇÓ²¼þ°æ±¾ºÅ£¬»áËæ×ų§¼ÒÓ²¼þÉý¼¶¶ø¸Ä±ä

+            break;

+        }

+    }

+

+    if(phy > 31)

+    {

+        return -1;

+    }

+    else{

+        printk(KERN_INFO "TSP zx29 gmac  find phy,phy_id_globle:0x%d\n",phy_id_globle);

+    }

+

+    val = gmac_mii_read(dev, phy, MII_BMCR) | BMCR_RESET;

+    gmac_mii_write(dev, phy, MII_BMCR, val);

+

+

+        for(i = 100000;  i > 0; i--)				// Åж¨PHYÊÇ·ñ¸´Î»³É¹¦

+        {

+            if((gmac_mii_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)	

+            {

+                break;

+            }

+            udelay(10);

+        }

+        switch(prv->phy_id)

+        {

+            case PHY_IP101A:

+            {

+                //150331 temp 802.3.az¹Ø±Õ

+                gmac_mii_write(dev, phy, 0xd, 0x0007); 

+                gmac_mii_write(dev, phy, 0xe, 0x003c);

+                gmac_mii_write(dev, phy, 0xd, 0x4007);

+                gmac_mii_write(dev, phy, 0xe, 0x0000);  

+                break;

+            }

+            case PHY_KSZ8081:

+            {

+                gmac_mii_write(dev, phy, 13, 0x001c);

+                gmac_mii_write(dev, phy, 14, 0x0008);

+                gmac_mii_write(dev, phy, 13, 0x401c);

+                gmac_mii_write(dev, phy, 14, 0x0067);

+                gmac_mii_write(dev, phy, 13, 0x001c);

+                gmac_mii_write(dev, phy, 14, 0x0009);

+                gmac_mii_write(dev, phy, 13, 0x401c);

+                gmac_mii_write(dev, phy, 14, 0xffff);

+                gmac_mii_write(dev, phy, 13, 0x001c);

+                gmac_mii_write(dev, phy, 14, 0x000a);

+                gmac_mii_write(dev, phy, 13, 0x401c);

+                gmac_mii_write(dev, phy, 14, 0xffff);

+                break;

+            }

+            default:

+            {

+                break;

+            }

+        }

+#ifndef GMAC_NO_INT

+    //timer

+    init_timer(&phy_timer);

+    phy_timer.expires 		= jiffies + 3*HZ;

+    phy_timer.data 		= (unsigned long)dev;

+    phy_timer.function 	= &zx_phy_timer;

+    add_timer(&phy_timer);

+#endif	

+     //register int

+    //enable interrupt

+    hh   = gmac_mii_read(dev, prv->phy, INT_SR);

+    hh |= INT_SR_INTR_PIN_USED;

+    hh &= ~(INT_SR_ALL_MASK|INT_SR_LINK_MASK);

+    gmac_mii_write(dev, prv->phy, INT_SR, hh);		

+

+    hh   = gmac_mii_read(dev, prv->phy, IO_SPEC_CR);

+    hh |= IO_SPEC_CR_SEL_INTR32;

+    gmac_mii_write(dev, prv->phy, IO_SPEC_CR, hh);	

+

+    //set auto-neg advertisement capabilities to 10/100 half/full

+    value = ADVERTISE_100FULL|ADVERTISE_100HALF|ADVERTISE_10FULL|ADVERTISE_10HALF|ADVERTISE_CSMA;

+    gmac_mii_write(dev, phy, MII_ADVERTISE, value);//0x1E1

+

+    val	= gmac_mii_read(dev, phy, MII_BMCR);

+    val |= BMCR_ANENABLE | BMCR_ANRESTART;

+    gmac_mii_write(dev, phy, MII_BMCR, val);

+

+

+#if 0//lvwenhua for wol+

+    if(prv->phy_id == PHY_IP101G)

+    {

+        #if 1//lvwenhua for test

+        {

+           gmac_mii_write(dev,prv->phy, 20, 16);

+           value = gmac_mii_read(dev,prv->phy, 17);

+           printk("lvwenhua gmac phy init p16r17=0x%x \n", value);

+           

+           gmac_mii_write(dev,prv->phy, 20, 16);

+           value = gmac_mii_read(dev,prv->phy, 29);

+           printk("lvwenhua gmac phy init p16r29=0x%x \n", value);

+           

+           gmac_mii_write(dev,prv->phy, 20, 4);

+           value = gmac_mii_read(dev,prv->phy, 16);

+           printk("lvwenhua gmac phy init p4r16=0x%x \n", value);

+           

+           gmac_mii_write(dev,prv->phy, 20, 17);

+           value = gmac_mii_read(dev,prv->phy, 17);

+           printk("lvwenhua gmac phy init p17r17=0x%x \n", value);

+        }

+        #endif

+

+//        value = WOL_CTRL_EN|WOL_CTRL_INTR_12_RSVD|WOL_CTRL_SENSE_ANY_PKT|WOL_CTRL_SENSE_DUT|WOL_CTRL_DNSPD_EN|WOL_CTRL_TIMER_30S;

+        value = WOL_CTRL_EN|WOL_CTRL_MASTER|WOL_CTRL_INTR_12_RSVD|WOL_CTRL_SENSE_ANY_PKT|WOL_CTRL_SENSE_DUT|WOL_CTRL_DNSPD_EN|WOL_CTRL_TIMER_30S;

+        gmac_mii_write(dev,prv->phy, MII_PAGECTRL, 4);

+        gmac_mii_write(dev,prv->phy, WOL_CTRL,value);//set wol+ 0x9740:enable,master,any packets,3minutes time out

+        

+        gmac_mii_write(dev,prv->phy, MII_PAGECTRL, 17);

+        gmac_mii_write(dev,prv->phy, WOL_SR,WOL_SR_INTR_DIS);//set wol+ interrupt disable

+        

+        gmac_mii_write(dev,prv->phy, MII_PAGECTRL, 16);

+        printk("gmac phy init: set wol+ p4r16=0x%x \n", value);

+

+        #if 1//lvwenhua for test

+        {

+           gmac_mii_write(dev,prv->phy, 20, 16);

+           value = gmac_mii_read(dev,prv->phy, 17);

+           printk("lvwenhua gmac phy after init p16r17=0x%x \n", value);

+           

+           gmac_mii_write(dev,prv->phy, 20, 16);

+           value = gmac_mii_read(dev,prv->phy, 29);

+           printk("lvwenhua gmac phy after init p16r29=0x%x \n", value);

+           

+           gmac_mii_write(dev,prv->phy, 20, 4);

+           value = gmac_mii_read(dev,prv->phy, 16);

+           printk("lvwenhua gmac phy after init p4r16=0x%x \n", value);

+           

+           gmac_mii_write(dev,prv->phy, 20, 17);

+           value = gmac_mii_read(dev,prv->phy, 17);

+           printk("lvwenhua gmac phy after init p17r17=0x%x \n", value);

+

+

+            gmac_mii_write(dev,prv->phy, 20, 16);

+        }

+        #endif

+    }

+#endif

+

+

+

+#ifdef CONFIG_ARCH_ZX297520V2

+			ret = gpio_request(ZX29_GPIO_56, "ext_int6");

+      if (ret) 

+      {

+	    	printk(KERN_INFO " gpio56  request error.\n");

+	    	return ret;

+      }

+      zx29_gpio_pd_pu_set(ZX29_GPIO_56,IO_CFG_PULL_DISABLE);

+

+	/* config as ext_int*/

+      ret = zx29_gpio_config(ZX29_GPIO_56, GPIO56_EXT_INT6); 

+      if (ret) 

+      return ret;

+      /* get int no */

+      ext_int6_no = prv->ext_irq;

+      printk(KERN_INFO "TSP zx29 gmac phy ext_int6_no irq = %d  !!!!!\n",ext_int6_no);

+      zx29_gpio_set_inttype(ZX29_GPIO_56, IRQ_TYPE_LEVEL_HIGH);

+

+      pcu_int_clear(PCU_EX6_INT);   

+

+	  wake_lock_init(&wlock_PHY, WAKE_LOCK_SUSPEND, "gmacPhy");

+      ret = request_threaded_irq(ext_int6_no, zx_phy_int, zx_phy_int_threadhandler,flags, dev->name, dev);

+

+	  if(ret)

+		return ret;	

+      irq_set_irq_wake(ext_int6_no, 1);

+#elif  CONFIG_ARCH_ZX297520V3

+#ifdef GMAC_NO_INT

+     g_gmac_phy_dev = dev;

+     wake_lock_init(&wlock_PHY, WAKE_LOCK_SUSPEND, "gmacPhy");

+	 sema_init(&gmac_plug_thread_sema, 0);

+     kthread_run(zx_gmac_plug_thread_ms, (unsigned long)dev, "gmac_proc/%s", "plug");

+#else

+   /*ÍⲿÖжϲ»È·¶¨*/

+       ret = gpio_request(ZX29_GPIO_64, "phy_int");

+       if (ret) 

+      {

+    	printk(KERN_INFO "reset phy_int  request error.\n");

+    	return ret;

+      }

+	/* config as ext_int*/

+      ret = zx29_gpio_config(ZX29_GPIO_64, GPIO64_PHY_INT); 

+      if (ret) 

+      return ret;

+      /* get int no */

+      ext_int6_no = prv->ext_irq;

+      printk(KERN_INFO "TSP zx29 gmac phy ext_int6_no irq = %d  !!!!!\n",ext_int6_no);

+

+      pcu_int_clear(PCU_GMACPHY_INT);   

+

+	  wake_lock_init(&wlock_PHY, WAKE_LOCK_SUSPEND, "gmacPhy");

+      ret = request_threaded_irq(ext_int6_no, zx_phy_int, zx_phy_int_threadhandler,flags, dev->name, dev);

+      if(ret)

+		return ret;	

+   	irq_set_irq_wake(ext_int6_no, 1);

+#endif

+#endif

+

+   return 0;

+}

+

+// ÅжÏPHYÊÇ·ñÁ¬½ÓÉÏ

+E_LINK_STATE gmac_phy_link_status(struct net_device *dev)

+{

+    unsigned			val = 0;

+    struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+    

+    if(PHY_8E1119R == prv->phy_id)// ±³¿¿±³

+    {

+        val	= gmac_mii_read(dev, prv->phy, MII_BMSR);

+        val	= gmac_mii_read(dev, prv->phy, MII_BMSR);

+    }

+    else

+    {

+        val = gmac_mii_read(dev, prv->phy, MII_BMSR);

+    }

+    

+    return (val & BMSR_LSTATUS)? eLINK_ON:eLINK_OFF;

+}

+

+static void zx_phy_timer(unsigned long data)

+{

+	struct net_device* 	dev		= (struct net_device*)data;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+	//unsigned	 		val		= gmac_phy_linked(dev);

+	phy_plug		= gmac_phy_link_status(dev);

+	phy_timer.expires 			= jiffies + 3*HZ;				// Ï´ζ¨Ê±Æ÷£º3sºó¿ªÊ¼

+	add_timer(&phy_timer);

+

+#if 0//lvwenhua for test

+int value = 0;

+

+    gmac_mii_write(dev,prv->phy, 20, 16);

+    value = gmac_mii_read(dev,prv->phy, 17);

+    printk("lvwenhua gmac phy timer p16r17=0x%x \n", value);

+    

+    gmac_mii_write(dev,prv->phy, 20, 16);

+    value = gmac_mii_read(dev,prv->phy, 29);

+    printk("lvwenhua gmac phy timer p16r29=0x%x \n", value);

+    

+    gmac_mii_write(dev,prv->phy, 20, 4);

+    value = gmac_mii_read(dev,prv->phy, 16);

+    printk("lvwenhua gmac phy timer p4r16=0x%x \n", value);

+    

+    gmac_mii_write(dev,prv->phy, 20, 17);

+    value = gmac_mii_read(dev,prv->phy, 17);

+    printk("lvwenhua gmac phy timer p17r17=0x%x \n", value);

+    

+    gmac_mii_write(dev,prv->phy, 20, 16);

+    value = gmac_mii_read(dev,prv->phy, MII_BMSR);

+    printk("lvwenhua gmac phy timer MII_BMSR r1=0x%x \n", value);

+    

+#endif

+}

+#ifdef CONFIG_PHY_TIMER_SET

+// Íø¿Ú¶¨Ê±Æ÷

+static void zx_net_phy_timer(unsigned long data)

+{

+	struct net_device* 	dev		= (struct net_device*)data;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+	unsigned	 		val		= gmac_phy_link_status(dev);

+	volatile unsigned 	*gmac 	= (unsigned*)dev->base_addr;

+	int					phy 	= prv->phy;

+	unsigned 			temp_val;

+    

+	spin_lock_irq(&prv->phy_lock);

+	if(eLINK_ON == val)													// PHY ÒÑÁ¬½ÓÉÏ

+	{

+		if((eLINK_OFF == prv->link) && (eSET_AUTO_NEGO == prv->set_duplex_mode))		// Á¬½Ó״̬ÓëÉϴβ»Í¬£¬ÇÒΪ×ÔЭÉÌģʽ

+		{

+			switch(prv->phy_id)

+			{

+    			case PHY_IP101G:

+                {

+                    prv->speed	= (gmac_mii_read(dev,phy, MII_BMCR) & BMCR_SPEED100)?eSPEED_100M:eSPEED_10M;

+                    prv->duplex	= (gmac_mii_read(dev,phy, MII_BMCR) & BMCR_FULLDPLX)?eDUPLEX_FULL:eDUPLEX_HALF;

+                    break;

+                }

+                case PHY_IP101A:

+                {

+                    prv->speed	= (gmac_mii_read(dev,phy, MII_BMCR) & BMCR_SPEED100)?eSPEED_100M:eSPEED_10M;

+                    prv->duplex	= (gmac_mii_read(dev,phy, MII_BMCR) & BMCR_FULLDPLX)?eDUPLEX_FULL:eDUPLEX_HALF;

+                    break;

+                }

+				case PHY_8E1119R:

+				{

+					//Ñ¡ÔñµÚ0Ò³¼Ä´æÆ÷

+					gmac_mii_write(dev, phy, 22, 0x0);

+

+					temp_val     = gmac_mii_read(dev,phy, 17);

+					prv->speed  = (temp_val & 0xC000) >> 14;

+					prv->duplex = (temp_val & 0x2000) >> 13;

+

+					break;

+				}

+				case PHY_KSZ8051:

+				{

+					temp_val	= gmac_mii_read(dev,phy, 0x1e);

+					temp_val	&= 0x7;//¶ÁÈ¡0x1e¼Ä´æÆ÷µÄ2:0 BIT£¬ÅжÏ×ÔЭÉ̽á¹û

+					if(1 == temp_val)//10M,°ëË«¹¤

+					{

+						prv->speed	= eSPEED_10M;

+						prv->duplex	= eDUPLEX_HALF;

+					}else if(2 == temp_val)//100M,°ëË«¹¤

+					{

+						prv->speed	= eSPEED_100M;

+						prv->duplex	= eDUPLEX_HALF;

+					}

+					else if(5 == temp_val)//10M,ȫ˫¹¤

+					{

+						prv->speed	= eSPEED_10M;

+						prv->duplex	= eDUPLEX_FULL;

+					}else if(6 == temp_val)//100M,ȫ˫¹¤

+					{

+						prv->speed	= eSPEED_100M;

+						prv->duplex	= eDUPLEX_FULL;

+					}else//Èç¹û×ÔЭÉÌδÍê³É£¬Ôò½øÐÐERR´òÓ¡£¬²¢ÇÒ°´100M,ȫ˫¹¤É趨

+					{

+						prv->speed	= eSPEED_100M;

+						prv->duplex	= eDUPLEX_FULL;

+					}

+					break;

+				}

+				case PHY_KSZ8081:

+				{

+					temp_val	= gmac_mii_read(dev,phy, 0x1e);

+					temp_val	&= 0x7;//¶ÁÈ¡0x1e¼Ä´æÆ÷µÄ2:0 BIT£¬ÅжÏ×ÔЭÉ̽á¹û

+					if(1 == temp_val)//10M,°ëË«¹¤

+					{

+						prv->speed	= eSPEED_10M;

+						prv->duplex	= eDUPLEX_HALF;

+					}else if(2 == temp_val)//100M,°ëË«¹¤

+					{

+						prv->speed	= eSPEED_100M;

+						prv->duplex	= eDUPLEX_HALF;

+					}

+					else if(5 == temp_val)//10M,ȫ˫¹¤

+					{

+						prv->speed	= eSPEED_10M;

+						prv->duplex	= eDUPLEX_FULL;

+					}else if(6 == temp_val)//100M,ȫ˫¹¤

+					{

+						prv->speed	= eSPEED_100M;

+						prv->duplex	= eDUPLEX_FULL;

+					}else//Èç¹û×ÔЭÉÌδÍê³É£¬Ôò½øÐÐERR´òÓ¡£¬²¢ÇÒ°´100M,ȫ˫¹¤É趨

+					{

+						prv->speed	= eSPEED_100M;

+						prv->duplex	= eDUPLEX_FULL;

+					}

+					break;

+				}

+				case PHY_RTL8201:

+				default:

+				{

+					temp_val	    = gmac_mii_read(dev,phy, 0);

+					prv->speed	= (temp_val & 0x2000) >> 13;

+					prv->duplex	= (temp_val & 0x0100) >> 8;

+					break;

+				}

+			}

+            

+            gmac_set_speed_duplex(dev,prv->speed,prv->duplex);

+		}	

+

+		if(!netif_carrier_ok(dev))	

+			netif_carrier_on(dev);

+	}

+	else													// PHY δÄÜÁ¬½Ó

+	{

+		if(netif_carrier_ok(dev))	netif_carrier_off(dev);

+	}

+	prv->link 					= val;

+	prv->timer.expires 			= jiffies + HZ;				// Ï´ζ¨Ê±Æ÷£º1sºó¿ªÊ¼

+	spin_unlock_irq(&prv->phy_lock);

+	add_timer(&prv->timer);

+}

+#endif

+void phy_notify_up(gmac_notify_event notify_type, void* puf)

+{

+	int rtv = -1;

+	enum kobject_action action = KOBJ_MAX;

+	char*envp_ext[] = {"GMACEVENT=gmac_eth0",NULL}; 

+    

+	switch(notify_type){

+		case GMAC_PHY_PLUGIN:

+			printk("gmac phy plugin \n");

+			action = KOBJ_ADD;

+			break;

+		case GMAC_PHY_PLUGOUT:

+			printk("gmac phy plugout \n");

+			action = KOBJ_REMOVE;

+			break;

+		default:

+			printk(KERN_WARNING "UNKWON GMAC EVENT \n");

+			break;

+	}

+    

+	if(phykobj){

+		rtv = kobject_uevent_env(phykobj, action,envp_ext);

+	}

+	printk(KERN_WARNING "rtv:%d \n",rtv);

+}

+

+#ifndef GMAC_NO_INT

+static irqreturn_t zx_phy_int_threadhandler(int irq, void *dev_id) 

+{

+	struct net_device* dev 		= (struct net_device*)dev_id;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+	int					phy 	= prv->phy;

+	volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+	unsigned int	 		val , nphy, i;

+	unsigned int	 link_in_count = 0;

+	unsigned int	 link_out_count  = 0;

+	unsigned  plug_flag;

+

+	if(phy_port_state == eLINK_ON)

+	{

+		wake_lock(&wlock_PHY);

+		phy_notify_up(GMAC_PHY_PLUGIN, NULL);

+		phy_plug = 1;

+	}

+	else 

+	{

+		wake_unlock(&wlock_PHY);

+		phy_notify_up(GMAC_PHY_PLUGOUT, NULL); 

+		phy_plug = 0;

+	} 

+	

+   return IRQ_HANDLED;

+}

+static irqreturn_t zx_phy_int(int irq, void *dev_id)

+{

+       int_count++;

+	struct net_device* dev 		= (struct net_device*)dev_id;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+       unsigned int rdata;

+       unsigned int phynum = 0;  

+#ifdef CONFIG_ARCH_ZX297520V2

+       pcu_int_clear(PCU_EX6_INT);

+#elif CONFIG_ARCH_ZX297520V3

+       pcu_int_clear(PCU_GMACPHY_INT);

+#endif

+       prv->ext_int_event   = gmac_mii_read(dev, prv->phy, INT_SR)&INT_SR_LINK_INT; 

+       phy_port_state   = gmac_phy_link_status(dev);

+	return   IRQ_WAKE_THREAD;

+}

+#endif

+// ´ò¿ªÍøÂçÉ豸

+int zx_gmac_phy_open(struct net_device *dev)

+{

+    struct zx_net_dev* prv	= (struct zx_net_dev*)netdev_priv(dev);

+#ifdef CONFIG_PHY_TIMER_SET

+    init_timer(&prv->timer);

+    prv->timer.expires 		= jiffies + HZ;

+    prv->timer.data 		= (unsigned long)dev;

+    prv->timer.function 	= &zx_net_phy_timer;

+    add_timer(&prv->timer);

+#endif

+    return 0;

+}

+

+// ¹Ø±ÕÍøÂçÉ豸

+int zx_gmac_phy_stop(struct net_device *dev)

+{

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+#ifdef CONFIG_PHY_TIMER_SET

+    del_timer_sync(&prv->timer);

+#endif 

+	wake_unlock(&wlock_PHY);

+

+    return 0;

+}

+

+int zx_gmac_phy_release(struct net_device *dev)

+{

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+	printk("[gmac phy: release!]\n");

+#ifndef GMAC_NO_INT

+	del_timer_sync(&phy_timer);	

+#endif

+#ifdef CONFIG_ARCH_ZX297520V2

+	gpio_free(ZX29_GPIO_56);

+#elif CONFIG_ARCH_ZX297520V3

+	gpio_free(ZX29_GPIO_64);

+#endif

+	free_irq(prv->ext_irq,dev); 

+	wake_unlock(&wlock_PHY);

+	wake_lock_destroy(&wlock_PHY);

+	kobj_gmac_del(NULL);

+

+    return 0;

+}

+

+

+//KOBJ ADD BY LYL

+static struct attribute gmac_plug_attr =

+{

+        .name = "eth_state",

+        .mode = S_IRWXUGO,

+};

+

+static struct attribute *gmac_status_attrs[] =

+{

+       &gmac_plug_attr,

+       NULL,

+};

+ssize_t kobj_gmac_show(struct kobject *kobject,struct attribute *attr,char *buf)

+{

+    unsigned  link =0;

+#if 1

+sprintf(buf, "%s","0");//phy_off);

+

+#else

+	link	= gmac_phy_link_status(gmac_net_dev);

+	printk("attrname: %s.\n",attr->name);

+	if(!strcmp(attr->name, GMAC_PHY_PLUG_NAME)){

+		if(link){

+		    sprintf(buf, "%s","1");//phy_on);

+		}else {

+		    sprintf(buf, "%s","0");//phy_off);

+		}                 		

+	}

+#endif

+	return strlen(buf);

+}

+ssize_t kobj_gmac_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)

+{

+	unsigned int value = 0;

+	value = simple_strtoul(buf, NULL, 4);

+	printk("attrname: %s.\n",attr->name);

+	if(!strcmp(attr->name,GMAC_PHY_PLUG_NAME)){

+		phy_plug = value;

+	}

+	return size;

+}

+static struct sysfs_ops obj_gmac_sysops =

+{

+        .show = kobj_gmac_show,

+        .store = kobj_gmac_store,        

+};

+

+static void kobj_gmac_release(struct kobject *kobject)

+{

+	printk("[gmac kobj_test: release!]\n");

+}

+

+static void kobj_gmac_del(struct kobject *kobject)

+{

+#if 1

+	kset_unregister(kset_gmac);

+

+	kobject_uevent(gmackobj, KOBJ_REMOVE);

+	kobject_del(gmackobj);

+	kobject_put(gmackobj);

+

+	kobject_uevent(phykobj, KOBJ_REMOVE);

+	kobject_del(phykobj);

+	kobject_put(phykobj);

+

+	kfree(phykobj);

+	kfree(gmackobj);

+#endif

+	printk("[gmac kobj_test: delete!]\n");

+}

+

+

+static struct kobj_type gmacktype =

+{       .release = kobj_gmac_release,

+        .sysfs_ops = &obj_gmac_sysops,

+        .default_attrs = gmac_status_attrs,

+};

+static int kset_filter(struct kset *kset,struct kobject *kobj)

+{

+        printk("kset Filter: kobj %s.\n",kobj->name);

+        return 1;

+}

+static const char *kset_name(struct kset *kset,struct kobject *kobj)

+{    

+        static char buf[20];

+        printk("Name:  kobj %s.\n",kobj->name);

+        sprintf(buf,"%s","gmac");

+        return buf;

+}

+static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)

+{

+        int i = 0;

+        printk("uevent: kobj %s.\n",kobj->name);

+        while(i < env->envp_idx)

+        {

+        printk("%s.\n",env->envp[i]);

+         i ++;

+         }

+         return 0;

+}

+static struct kset_uevent_ops gmac_uevent_ops =

+{

+        .filter = kset_filter,

+        .name = kset_name,

+        .uevent = kset_uevent,

+};

+static int  kset_gmac_init(void)

+{

+         int ret = 0;

+         /* ´´½¨²¢×¢²á kset_p */   

+         gmackobj = kzalloc(sizeof(*gmackobj),GFP_KERNEL);

+         if(!gmackobj){

+            printk(KERN_WARNING "mallock gmackobj failed \n");

+            return 0;

+         }

+         kobject_init(gmackobj, &gmacktype);

+         kobject_add(gmackobj,kernel_kobj,"%s","eth_debug");  

+         kset_gmac = kset_create_and_add("gmac", &gmac_uevent_ops, NULL); 

+         

+         phykobj = kzalloc(sizeof(*phykobj),GFP_KERNEL);

+         if(!phykobj){

+       	printk(KERN_WARNING "mallock phykobj failed \n");

+    	  return 0;

+         }

+         kobject_init(phykobj, &gmacktype);

+         kobject_add(phykobj,&kset_gmac->kobj,"%s","gmacconfig");

+         phykobj->kset = kset_gmac;

+         return ret;

+}

+#if 0

+void gmac_kick_plug_thread(void)

+{

+    int int_event = 0;

+    struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(g_gmac_phy_dev);

+  //  if (phy_init_state = 1)

+  //  {

+        int_event        = gmac_mii_read(g_gmac_phy_dev, prv->phy, INT_SR)&INT_SR_LINK_INT; 

+        phy_port_state   = gmac_phy_link_status(g_gmac_phy_dev);

+      // if(!test_and_set_bit(1, &gmac_plug_sema_up_flag))

+  //  printk("gaohf:kick_plug ,phy_plug=%d,phy_port_state=%d\n",phy_plug,phy_port_state);

+        if (g_mac_phy_state != phy_port_state )

+        {

+            g_mac_phy_state = phy_port_state;

+            up(&gmac_plug_thread_sema);

+        }

+  //  }

+}

+

+void zx_gmac_plug_thread(unsigned long dev_id)

+{

+	struct net_device* dev 		= (struct net_device*)dev_id;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+	int					phy 	= prv->phy;

+	volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+	unsigned int	 		val , nphy, i;

+	unsigned int	 link_in_count = 0;

+	unsigned int	 link_out_count  = 0;

+	unsigned  plug_flag;

+

+	while (!kthread_should_stop()){

+		down(&gmac_plug_thread_sema);

+    	if(phy_port_state == eLINK_ON)

+    	{

+    		wake_lock(&wlock_PHY);

+    		phy_notify_up(GMAC_PHY_PLUGIN, NULL);

+    		phy_plug = eLINK_ON;

+            printk("gaohf GMAC PHY_PLUGIN \n");

+    	}

+    	else 

+    	{

+    		wake_unlock(&wlock_PHY);

+    		phy_notify_up(GMAC_PHY_PLUGOUT, NULL); 

+    		phy_plug = eLINK_OFF;

+            printk("gaohf GMAC PHY_PLUGOUT \n");

+    	} 

+	}

+}

+#endif

+

+#ifdef GMAC_NO_INT

+void zx_gmac_plug_thread_ms(unsigned long dev_id)

+{

+	struct net_device *dev = (struct net_device*)dev_id;

+	struct zx_net_dev *prv = (struct zx_net_dev*)netdev_priv(dev);

+    int          int_event = 0;

+    

+	while (!kthread_should_stop()){

+        int_event        = gmac_mii_read(g_gmac_phy_dev, prv->phy, INT_SR)&INT_SR_LINK_INT; 

+        phy_port_state   = gmac_phy_link_status(g_gmac_phy_dev);

+        if (g_mac_phy_state != phy_port_state )

+        {

+            g_mac_phy_state = phy_port_state;

+        	if(phy_port_state == eLINK_ON)

+        	{

+        		wake_lock(&wlock_PHY);

+        		phy_notify_up(GMAC_PHY_PLUGIN, NULL);

+        		phy_plug = eLINK_ON;

+				prv->link = eLINK_ON;

+                printk("gaohf GMAC PHY_PLUGIN \n");

+        	}

+        	else 

+        	{

+        		wake_unlock(&wlock_PHY);

+        		phy_notify_up(GMAC_PHY_PLUGOUT, NULL); 

+        		phy_plug = eLINK_OFF;

+				prv->link =  eLINK_OFF;

+                printk("gaohf GMAC PHY_PLUGOUT \n");

+        	} 

+        }

+        msleep(1000);

+	}

+}

+#endif

+

+int  zx_gmac_phy_init(struct net_device *dev)

+{  

+         int	ret = 0;

+         struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+

+         kset_gmac_init();	  

+         ret = gmac_phy_init(dev);

+         if( ret <0 )   

+         {

+              printk(KERN_INFO "TSP zx29 gmac can not find phy\n");

+              return 1  ;

+         }

+         phy_init_state = 1;

+         return 0;

+}

+

diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/Makefile b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/Makefile
new file mode 100644
index 0000000..4a921cc
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/Makefile
@@ -0,0 +1,10 @@
+# Makefile for linux/drivers/net/rtl8306e
+#
+
+//obj-y += mdcmdio.o
+//obj-$(CONFIG_NET_ZX29_GMAC_SWITCH) += rtk_api.o
+//obj-y += rtl_igmp_glue.o
+//obj-y += rtl_igmp_snooping.o
+//obj-$(CONFIG_NET_ZX29_GMAC_SWITCH) += rtl8306e_asicdrv.o
+
+//obj-$(CONFIG_NET_ZX29_GMAC_SWITCH)	+= zx_gmac_switch.o
\ No newline at end of file
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api.c b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api.c
new file mode 100644
index 0000000..ae2c5ac
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api.c
@@ -0,0 +1,5344 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 26889 $ 
+* $Date: 2012-02-28 21:08:47 +0800 (星期二, 2012-02-28) $
+*
+* Purpose : realtek common API
+*
+* Feature :  This file consists of following modules:
+*                
+*
+*/
+
+#include "rtl8306e_types.h"
+#include "rtl8306e_asicdrv.h"
+#include "rtk_api.h"
+#include "rtk_api_ext.h"
+
+
+/* Function Name:
+ *      rtk_switch_init
+ * Description:
+ *      Set chip to default configuration enviroment
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED               -  Failure
+ * Note:
+ *     The API can set chip registers to default configuration for
+ *     different release chip model.
+ */
+rtk_api_ret_t rtk_switch_init(void)
+{
+    rtl8306e_asic_init();
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_switch_maxPktLen_set
+ * Description:
+ *      Set the max packet length of the specific unit
+ * Input:
+ *      len       -       max packet length
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                    -  Success
+ *      RT_ERR_FAILED               -  Failure
+ *      RT_ERR_INPUT                -  Invalid input parameter
+ * Note:
+ *      The API can set max packet length of the specific unit to
+ *          - MAXPKTLEN_1522B,
+ *          - MAXPKTLEN_1536B,
+ *          - MAXPKTLEN_1552B,
+ *          - MAXPKTLEN_2000B, 
+ */
+rtk_api_ret_t rtk_switch_maxPktLen_set(rtk_switch_maxPktLen_t len)
+{
+    rtk_api_ret_t retVal;
+    uint32          maxlen;
+
+    if (len > MAXPKTLEN_2000B)
+        return RT_ERR_INPUT;
+
+    switch(len)
+    {
+        case MAXPKTLEN_1522B:
+            maxlen = RTL8306_MAX_PKT_LEN_1518;
+            break;            
+        case MAXPKTLEN_1536B:
+            maxlen = RTL8306_MAX_PKT_LEN_1536;
+            break;
+        case MAXPKTLEN_1552B:
+            maxlen = RTL8306_MAX_PKT_LEN_1552;
+            break;
+        case MAXPKTLEN_2000B:
+            maxlen = RTL8306_MAX_PKT_LEN_2000;
+            break;
+        default:
+            return FAILED;
+    }
+
+    if((retVal = rtl8306e_switch_maxPktLen_set(maxlen)) != RT_ERR_OK)
+        return retVal;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_switch_maxPktLen_get
+ * Description:
+ *      Get the max packet length of the specific unit
+ * Input:
+ *      none
+ * Output:
+ *      pLen                             -    the pointer of max packet length
+ * Return: 
+ *      RT_ERR_OK                    -  Success
+ *      RT_ERR_FAILED               -  Failure
+ *      RT_ERR_NULL_POINTER     -  Input parameter is null pointer 
+ * Note:
+ *      The API can set max packet length of the specific unit to
+ *          - MAXPKTLEN_1522B,
+ *          - MAXPKTLEN_1536B,
+ *          - MAXPKTLEN_1552B,
+ *          - MAXPKTLEN_2000B, 
+ */
+rtk_api_ret_t rtk_switch_maxPktLen_get(rtk_switch_maxPktLen_t *pLen)
+{
+    rtk_api_ret_t retVal;
+    uint32          maxlen;
+
+    if (NULL == pLen)
+        return RT_ERR_NULL_POINTER;
+    
+    if((retVal = rtl8306e_switch_maxPktLen_get(&maxlen)) != RT_ERR_OK)
+        return retVal;
+
+    switch(maxlen)
+    {
+        case RTL8306_MAX_PKT_LEN_1518:
+            *pLen = MAXPKTLEN_1522B;
+            break;
+
+        case RTL8306_MAX_PKT_LEN_1536:
+            *pLen = MAXPKTLEN_1536B;
+            break;
+            
+        case RTL8306_MAX_PKT_LEN_1552:
+            *pLen = MAXPKTLEN_1552B;
+            break;
+            
+        case RTL8306_MAX_PKT_LEN_2000:
+            *pLen = MAXPKTLEN_2000B;
+            break;
+
+        default:
+            return FAILED;
+    }
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_phyReg_set
+ * Description:
+ *      Set PHY register data of the specific port
+ * Input:
+ *      phy                - phy number, 0 ~ 6 
+ *      reg                 - Register id
+ *      regData           - Register data
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK         -  Success
+ *      RT_ERR_FAILED   -   Failure
+ * Note:
+ *      This API can set PHY register data of the specific port.
+ *      RTL8306E switch has 5 FE port, and port 4 could be set as
+ *      phy mode or mac mode, port 5 is mac mode which connect
+ *      with mii interface. so parameter phy 0 ~4 means port 0 ~4
+ *      phy register, 5 means port 4 mac mode, 6 means port 5.
+ *      
+ */
+ 
+rtk_api_ret_t rtk_port_phyReg_set(rtk_port_t phy, rtk_port_phy_reg_t reg, rtk_port_phy_data_t regData)
+{
+    rtk_api_ret_t retVal;
+    
+    if(phy > (RTL8306_PHY_NUMBER - 1))
+        return RT_ERR_PORT_ID;
+
+    retVal = rtl8306e_reg_set(phy, reg, 0, regData);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_port_phyReg_get
+ * Description:
+ *      Get PHY register data of the specific port
+ * Input:
+ *      phy                  - phy number, 0 ~ 6
+ *      reg                   - Register id
+ * Output:
+ *      pData               - the pointer of Register data
+ * Return:
+ *      RT_ERR_OK        -  Success
+ *      RT_ERR_FAILED   -  Failure
+ * Note:
+ *      This API can set PHY register data of the specific port.
+ *      RTL8306E switch has 5 FE port, and port 4 could be set as
+ *      phy mode or mac mode, port 5 is mac mode which connect
+ *      with mii interface. so parameter phy 0 ~4 means port 0 ~4
+ *      phy register, 5 means port 4 mac mode, 6 means port 5.
+ *      
+ */
+ 
+rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t phy, rtk_port_phy_reg_t reg, rtk_port_phy_data_t *pData) 
+{
+    rtk_api_ret_t retVal;
+
+    if(phy > (RTL8306_PHY_NUMBER - 1))
+        return RT_ERR_PORT_ID;
+
+    retVal = rtl8306e_reg_get(phy, reg, 0, pData);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_phyAutoNegoAbility_set
+ * Description:
+ *      Set ethernet PHY auto-negotiation desired ability
+ * Input:
+ *      port       -  Port id
+ *      pAbility   -  Ability structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In auto-negotiation mode, phy autoNegotiation ability must be enabled
+ */ 
+rtk_api_ret_t rtk_port_phyAutoNegoAbility_set(rtk_port_t port, rtk_port_phy_ability_t *pAbility)
+{
+    rtk_api_ret_t retVal;     
+    uint32 phyData;    
+    uint32 phyEnMsk0;
+    uint32 phyEnMsk4;
+
+    if(port > 4)
+        return RT_ERR_PORT_ID;         
+
+    if(NULL == pAbility)
+        return RT_ERR_NULL_POINTER;
+
+    if(pAbility->Half_10 >= RTK_ENABLE_END  || pAbility->Full_10 >= RTK_ENABLE_END ||
+       pAbility->Half_100 >= RTK_ENABLE_END || pAbility->Full_100 >= RTK_ENABLE_END ||
+       pAbility->AutoNegotiation >= RTK_ENABLE_END ||pAbility->AsyFC >= RTK_ENABLE_END ||
+       pAbility->FC >= RTK_ENABLE_END)
+        return RT_ERR_INPUT; 
+
+    /*for PHY auto mode setup*/
+    pAbility->AutoNegotiation = 1; 
+
+    phyEnMsk0 = 0;
+    phyEnMsk4 = 0;
+    
+    if(1 == pAbility->Half_10)
+    {
+        /*10BASE-TX half duplex capable in reg 4.5*/
+        phyEnMsk4 = phyEnMsk4 | (1<<5);
+    }
+
+    if(1 == pAbility->Full_10)
+    {
+        /*10BASE-TX full duplex capable in reg 4.6*/
+        phyEnMsk4 = phyEnMsk4 | (1<<6);        
+    }
+
+    if(1 == pAbility->Half_100)
+    {
+        /*100BASE-TX half duplex capable in reg 4.7*/
+        phyEnMsk4 = phyEnMsk4 | (1<<7);
+    }
+
+    if(1 == pAbility->Full_100)
+    {
+        /*100BASE-TX full duplex capable in reg 4.8*/
+        phyEnMsk4 = phyEnMsk4 | (1<<8);
+    }
+    
+    if(1 == pAbility->AutoNegotiation)
+    {
+        /*Auto-Negotiation setting in reg 0.12*/
+        phyEnMsk0 = phyEnMsk0 | (1<<12);
+    }
+
+    if(1 == pAbility->AsyFC)
+    {
+        /*Asymetric flow control in reg 4.11*/
+        phyEnMsk4 = phyEnMsk4 | (1<<11);
+    }
+    
+    if(1 == pAbility->FC)
+    {
+        /*Flow control in reg 4.10*/
+        phyEnMsk4 = phyEnMsk4 | (1<<10);
+    }
+
+    /*Auto-Negotiation control register setting*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_AN_ADVERTISEMENT_REG, &phyData)) != RT_ERR_OK)
+        return retVal;
+
+    phyData = (phyData & (~0x0DE0)) | phyEnMsk4;
+    if((retVal = rtk_port_phyReg_set(port, (rtk_port_phy_reg_t)PHY_AN_ADVERTISEMENT_REG, phyData)) != RT_ERR_OK)
+        return retVal;
+
+    /*Control register setting and restart auto*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, &phyData)) != RT_ERR_OK)
+        return retVal;
+    phyData = (phyData & (~0x3100)) | phyEnMsk0;
+    
+    /*If have auto-negotiation capable, then restart auto negotiation*/
+    if(1 == pAbility->AutoNegotiation)
+    {
+        phyData = phyData | (1 << 9);
+    }
+
+    if((retVal = rtk_port_phyReg_set(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, phyData)) != RT_ERR_OK)
+        return retVal;    
+
+    return RT_ERR_OK;
+    
+}
+
+/* Function Name:
+ *      rtk_port_phyAutoNegoAbility_get
+ * Description:
+ *      Get ethernet PHY auto-negotiation desired ability
+ * Input:
+ *      port       -  Port id
+ * Output:
+ *      pAbility   -  Ability structure
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_PHY_AUTO_NEGO_MODE
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In auto-negotiation mode, phy autoNegotiation ability must be enabled
+ */   
+rtk_api_ret_t rtk_port_phyAutoNegoAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility)
+{
+    uint32 phyData0;
+    uint32 phyData4;
+    rtk_api_ret_t retVal;  
+    
+    if(port > 4)
+        return RT_ERR_PORT_ID; 
+
+    if(NULL == pAbility)
+        return RT_ERR_NULL_POINTER;
+
+    /*Control register setting and restart auto*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, &phyData0)) != RT_ERR_OK)
+        return retVal;
+
+    /*Auto-Negotiation control register setting*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_AN_ADVERTISEMENT_REG, &phyData4)) != RT_ERR_OK)
+        return retVal;
+
+    if(!(phyData0 & (1<<12)))
+        return RT_ERR_PHY_AUTO_NEGO_MODE;
+
+    if(phyData4 & (1<<11))
+        pAbility->AsyFC = 1;
+    else
+        pAbility->AsyFC = 0;
+
+    if(phyData4 & (1<<10))
+        pAbility->FC = 1;
+    else
+        pAbility->FC = 0;
+    
+    
+    if(phyData4 & (1<<8))
+        pAbility->Full_100= 1;
+    else
+        pAbility->Full_100= 0;
+    
+    if(phyData4 & (1<<7))
+        pAbility->Half_100= 1;
+    else
+        pAbility->Half_100= 0;
+
+    if(phyData4 & (1<<6))
+        pAbility->Full_10= 1;
+    else
+        pAbility->Full_10= 0;
+    
+    if(phyData4 & (1<<5))
+        pAbility->Half_10= 1;
+    else
+        pAbility->Half_10= 0;
+
+
+    if(phyData0 & (1<<12))
+        pAbility->AutoNegotiation= 1;
+    else
+        pAbility->AutoNegotiation= 0;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *     rtk_port_phyForceModeAbility_set
+ * Description:
+ *      Set the port PHY force mode, config its speed/duplex mode/pause/asy_pause 
+ * Input:
+ *      port       -  Port id
+ *      pAbility   -  Ability structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_PHY_FORCE_1000
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In force mode, phy autoNegotiation ability must be disabled.
+ */
+rtk_api_ret_t rtk_port_phyForceModeAbility_set(rtk_port_t port, rtk_port_phy_ability_t *pAbility)
+{
+    rtk_api_ret_t retVal;           
+    uint32 phyData;
+    uint32 phyEnMsk0;
+    uint32 phyEnMsk4;
+    
+    if(port > 4)
+        return RT_ERR_PORT_ID;  
+    
+    if(NULL == pAbility)
+        return RT_ERR_NULL_POINTER;
+
+    if(pAbility->Half_10 >= RTK_ENABLE_END || pAbility->Full_10 >= RTK_ENABLE_END ||
+       pAbility->Half_100 >= RTK_ENABLE_END || pAbility->Full_100 >= RTK_ENABLE_END ||
+       pAbility->AutoNegotiation >= RTK_ENABLE_END ||pAbility->AsyFC >= RTK_ENABLE_END ||
+       pAbility->FC >= RTK_ENABLE_END)
+        return RT_ERR_INPUT; 
+
+    /*for PHY force mode setup*/
+    pAbility->AutoNegotiation = 0;
+    
+    phyEnMsk0 = 0;
+    phyEnMsk4 = 0;
+    
+    if(1 == pAbility->Half_10)
+    {
+        /*Speed selection in reg 0.13 */
+        /* 1= 100Mpbs*/
+        /* 0= 10Mpbs*/        
+        phyEnMsk0 = phyEnMsk0 & (~(1<<13));
+
+        /*Half duplex mode in reg 0.8*/
+        phyEnMsk0 = phyEnMsk0 & (~(1<<8));
+    }
+
+    if(1 == pAbility->Full_10)
+    {
+        /*Speed selection in reg 0.13 */
+        /* 1= 100Mpbs*/
+        /* 0= 10Mpbs*/        
+        phyEnMsk0 = phyEnMsk0 & (~(1<<13));
+
+        /*Full duplex mode in reg 0.8*/
+        phyEnMsk0 = phyEnMsk0 | (1<<8);
+        
+    }
+
+    if(1 == pAbility->Half_100)
+    {
+        /*Speed selection in reg 0.13 */
+        /* 1= 100Mpbs*/
+        /* 0= 10Mpbs*/       
+        phyEnMsk0 = phyEnMsk0 | (1<<13);
+        
+        /*Half duplex mode in reg 0.8*/
+        phyEnMsk0 = phyEnMsk0 & (~(1<<8));
+    }
+
+
+    if(1 == pAbility->Full_100)
+    {
+        /*Speed selection in reg 0.13 */
+        /* 1= 100Mpbs*/
+        /* 0= 10Mpbs*/       
+        phyEnMsk0 = phyEnMsk0 | (1<<13);
+        
+        /*Full duplex mode in reg 0.8*/
+        phyEnMsk0 = phyEnMsk0 | (1<<8);
+    }
+        
+    if(1 == pAbility->AsyFC)
+    {
+        /*Asymetric flow control in reg 4.11*/
+        phyEnMsk4 = phyEnMsk4 | (1<<11);
+    }
+    if(1 == pAbility->FC)
+    {
+        /*Flow control in reg 4.10*/
+        phyEnMsk4 = phyEnMsk4 | (1<<10);
+    }
+    
+    /*Auto-Negotiation control register setting*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_AN_ADVERTISEMENT_REG, &phyData))!= RT_ERR_OK)
+        return retVal;
+
+    phyData = (phyData & (~0x0DE0)) | phyEnMsk4;
+    if((retVal = rtk_port_phyReg_set(port, (rtk_port_phy_reg_t)PHY_AN_ADVERTISEMENT_REG, phyData)) != RT_ERR_OK)
+        return retVal;
+
+    /*Control register setting and restart auto*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, &phyData)) != RT_ERR_OK)
+        return retVal;
+    phyData = (phyData & (~0x3100)) | phyEnMsk0;
+    if((retVal = rtk_port_phyReg_set(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, phyData)) != RT_ERR_OK)
+        return retVal;
+    
+       
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_port_phyForceModeAbility_get
+ * Description:
+ *      Get the port PHY speed/duplex mode/pause/asy_pause in force mode
+ * Input:
+ *      port       -  Port id
+ * Output:
+ *      pAbility   -  Ability structure
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In force mode, phy autoNegotiation ability must be disabled.
+ */
+rtk_api_ret_t rtk_port_phyForceModeAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility)
+{
+    uint32 phyData0;
+    uint32 phyData4;
+    rtk_api_ret_t retVal;    
+    
+    if(port > 4)
+        return RT_ERR_PORT_ID; 
+    
+    if(NULL == pAbility)
+        return RT_ERR_NULL_POINTER;
+                 
+
+    /*Control register setting and restart auto*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, &phyData0)) != RT_ERR_OK)
+        return retVal;
+
+    /*Auto-Negotiation control register setting*/
+    if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_AN_ADVERTISEMENT_REG, &phyData4)) != RT_ERR_OK)
+        return retVal;
+
+    if(phyData0 & (1<<12))
+        return RT_ERR_PHY_FORCE_ABILITY;
+
+    if(phyData4 & (1<<11))
+        pAbility->AsyFC = 1;
+    else
+        pAbility->AsyFC = 0;
+
+    if(phyData4 & (1<<10))
+        pAbility->FC = 1;
+    else
+        pAbility->FC = 0;
+    
+
+    pAbility->Full_100 = 0;
+    pAbility->Half_100 = 0;
+    pAbility->Full_10 = 0;    
+    pAbility->Half_10 = 0;
+    pAbility->Full_1000 = 0;
+
+    if(phyData0 & (1<<8) && phyData0 & (1<<13))
+        pAbility->Full_100= 1;
+    
+    if(!(phyData0 & (1<<8)) && phyData0 & (1<<13))
+        pAbility->Half_100= 1;
+
+    if(phyData0 & (1<<8) && !(phyData0 & (1<<13)))
+        pAbility->Full_10= 1;
+    
+    if(!(phyData0 & (1<<8)) && !(phyData0 & (1<<13)))
+        pAbility->Half_10= 1;
+
+    if(phyData0 & (1<<12))
+        pAbility->AutoNegotiation= 1;
+    else
+        pAbility->AutoNegotiation= 0;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_phyStatus_get
+ * Description:
+ *      Get ethernet PHY linking status
+ * Input:
+ *      port             -  Port id
+ * Output:
+ *      pLinkStatus   -  the pointer of PHY link status 
+ *      pSpeed         -  the pointer of PHY link speed
+ *      pDuplex        -  the pointer of PHY duplex 
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_NULL_POINTER
+ *     
+ * Note:
+ *      RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ */
+rtk_api_ret_t rtk_port_phyStatus_get(rtk_port_t port, rtk_port_linkStatus_t *pLinkStatus, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex)
+{
+    rtk_api_ret_t retVal;
+    uint32 phyData0;
+    uint32  linkUp;
+    
+    if(port > 4)
+        return RT_ERR_PORT_ID; 
+    
+    if((NULL == pLinkStatus) || (NULL == pSpeed) || (NULL == pDuplex))
+        return RT_ERR_NULL_POINTER;
+
+    rtl8306e_port_phyLinkStatus_get(port, &linkUp);
+    if (TRUE == linkUp)
+    {
+        *pLinkStatus = PORT_LINKUP;
+        /*Control register setting and restart auto*/
+        if((retVal = rtk_port_phyReg_get(port, (rtk_port_phy_reg_t)PHY_CONTROL_REG, &phyData0)) != RT_ERR_OK)
+            return retVal;
+        *pSpeed = ((phyData0 & (0x1 << 13)) >> 13) ? PORT_SPEED_100M : PORT_SPEED_10M; 
+        *pDuplex = ((phyData0 & (0x1 << 8)) >> 8) ? PORT_FULL_DUPLEX : PORT_HALF_DUPLEX;
+    }
+    else
+    {
+        *pLinkStatus = PORT_LINKDOWN;
+        *pSpeed = PORT_SPEED_10M;
+        *pDuplex = PORT_HALF_DUPLEX; 
+    }
+  
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt0_set
+ * Description:
+ *      Set external interface 1(MAC 5) force linking configuration.
+ * Input:
+ *      mode - external interface mode
+ *      pPortability - port ability configuration
+ * Output:
+ *      None 
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure
+ *      RT_ERR_INPUT       - Invalid input parameters.
+ * Note:
+ *      (1) This API can set external interface 1(MAC 5) force mode properties,
+ *      including link status,speed,duplex,and tx pause and tx pause ability.
+ *      In force mode, autoNegotiation ability must be disabled.
+ *      (2) For 8306E, the external interface 1(MAC 5) operating mode can be
+ *      MAC Mode (T)MII, PHY Mode (T)MII and RMII. The operating mode is 
+ *      determined by strapping pin upon reset, and can not be configured 
+ *      by software, except the selection of MII or TMII. 
+ *      (3)The input parament mode here is only used to select MII or TMII.
+ *      When operating mode is configured as MAC Mode (T)MII or PHY Mode (T)MII
+ *      via strapping pin, then the selection of MII or TMII can be done via software.
+ *      For example, set mode MODE_EXT_TMII_MAC to select TMII, and set mode
+ *      MODE_EXT_MII_MAC to select MII.
+ */
+rtk_api_ret_t rtk_port_macForceLinkExt0_set(rtk_mode_ext_t mode, rtk_port_mac_ability_t *pPortability)
+{
+    rtk_api_ret_t retVal;
+    uint32 regVal;
+
+    if (pPortability->speed > 1 || pPortability->duplex > 1 || pPortability->txpause > 1 ||
+        pPortability->rxpause > 1 || pPortability->link > 1)
+        return RT_ERR_INPUT;
+
+    if (MODE_EXT_TMII_MAC == mode || MODE_EXT_TMII_PHY == mode)
+    {
+        rtl8306e_regbit_set (0, 16, 14, 0, 1);
+        rtl8306e_regbit_set (4, 27, 12, 0, 1);    
+    }
+    else if (MODE_EXT_MII_MAC == mode || MODE_EXT_MII_PHY == mode)
+    {
+        rtl8306e_regbit_set (0, 16, 14, 0, 0);
+        rtl8306e_regbit_set (4, 27, 12, 0, 0); 
+    }
+
+    /*must be in forcemode*/
+    pPortability->forcemode = 1;
+
+    /*Nway ability must be disabled*/
+    pPortability->nway = 0;
+    if ((retVal = rtl8306e_regbit_set (6, 22, 6, 0, 0)) != RT_ERR_OK)
+        return retVal;
+    
+    if ((retVal = rtl8306e_regbit_set (6, 22, 15, 0, pPortability->link ? 1 : 0)) != RT_ERR_OK)
+        return retVal;
+    
+    rtl8306e_reg_get(6, 22, 0, &regVal);
+    regVal &= (~0x30);
+    if ((pPortability->speed == PORT_SPEED_100M) && (pPortability->duplex == PORT_FULL_DUPLEX))
+        regVal |= 0x30; 
+    else if ((pPortability->speed == PORT_SPEED_10M) && (pPortability->duplex == PORT_FULL_DUPLEX))
+        regVal |= 0x10;
+    else if ((pPortability->speed == PORT_SPEED_100M) && (pPortability->duplex == PORT_HALF_DUPLEX ))
+        regVal |= 0x20;
+    else
+        regVal |= 0x0;
+    if ((retVal = rtl8306e_reg_set (6, 22, 0, regVal)) != RT_ERR_OK)
+        return retVal;
+
+    /*Enable symmetric flow control of MAC 5*/
+    if (pPortability->symflc)
+    {
+       rtl8306e_regbit_set (6, 24, 12, 0, 0);
+       rtl8306e_regbit_set (6, 4, 10, 0, 1);
+    }
+    /*Enable asymmetric flow control of MAC 5*/
+    else
+    {
+        rtl8306e_regbit_set (6, 4, 10, 0, 0);
+        if ((retVal = rtl8306e_regbit_set (6, 24, 12, 0, 1)) != RT_ERR_OK)
+            return retVal;
+        if ((retVal = rtl8306e_regbit_set (6, 24, 14, 0, pPortability->txpause ? 0 : 1)) != RT_ERR_OK)
+            return retVal;
+        if ((retVal = rtl8306e_regbit_set (6, 24, 13, 0, pPortability->rxpause ? 0 : 1)) != RT_ERR_OK)
+            return retVal;
+    }
+
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt0_get
+ * Description:
+ *      Get external interface 1(MAC 5) force linking configuration.
+ * Input:
+ *      None
+ * Output:
+ *      pMode - external interface mode
+ *      pPortability - port ability configuration
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_INPUT - Invalid input parameters.
+ * Note:
+ *      This API can get external interface 1 (MAC 5) force mode properties.
+ *      The external interface 1 operating mode can be:
+ *      - MODE_EXT_MII_MAC,
+ *      - MODE_EXT_MII_PHY, 
+ *      - MODE_EXT_TMII_MAC,
+ *      - MODE_EXT_TMII_PHY, 
+ *      - MODE_EXT_RMII, 
+ */
+rtk_api_ret_t rtk_port_macForceLinkExt0_get(rtk_mode_ext_t *pMode, rtk_port_mac_ability_t *pPortability)
+{
+    uint32 regVal;
+    uint32 modesel;
+
+    rtl8306e_regbit_set(0, 16, 11, 0, 1);
+    rtl8306e_reg_get(6, 26, 3, &regVal);
+    modesel = regVal & 0x1F;
+    if (0x1 == modesel || 0x2 == modesel || 0x9 == modesel || 0x12 == modesel || 0x10 == modesel)
+        *pMode = MODE_EXT_MII_PHY;
+    else if (0xA == modesel || 0xB == modesel)
+        *pMode = MODE_EXT_MII_MAC;
+    else if (0x0 == modesel || 0x8 == modesel || 0x11 == modesel)
+        *pMode = MODE_EXT_RMII;
+    else
+        *pMode = MODE_EXT_END;
+    
+    rtl8306e_regbit_get (0, 16, 14, 0, &regVal);
+    if (regVal && (MODE_EXT_MII_PHY == *pMode))
+        *pMode = MODE_EXT_TMII_PHY;
+    
+    if (regVal && (MODE_EXT_MII_MAC == *pMode))
+        *pMode = MODE_EXT_TMII_MAC;
+
+    rtl8306e_regbit_get (6, 22, 6, 0, &regVal);
+    pPortability->nway = regVal ? 1 : 0;
+    pPortability->forcemode = ~(pPortability->nway);
+
+    rtl8306e_regbit_get (6, 24, 12, 0, &regVal);
+    pPortability->symflc = regVal ? 0 : 1;
+    
+    rtl8306e_regbit_get (6, 24, 13, 0, &regVal);
+    pPortability->rxpause = regVal ? 0 : 1;
+
+    rtl8306e_regbit_get (6, 24, 14, 0, &regVal);
+    pPortability->txpause = regVal ? 0 : 1;
+
+    rtl8306e_regbit_get (6, 22, 15, 0, &regVal);
+    pPortability->link= regVal ? 1 : 0;
+
+    rtl8306e_reg_get (6, 22, 0, &regVal);
+    if ((regVal & (0x3 << 4)) >> 4 == 0x3)
+    {
+        pPortability->speed =1;
+        pPortability->duplex =1;
+    }
+    else if ((regVal & (0x3 << 4)) >> 4 == 0x2)
+    {
+        pPortability->speed = 1;
+        pPortability->duplex =0;
+    }
+    else if ((regVal & (0x3 << 4)) >> 4 == 0x1)
+    {
+        pPortability->speed = 0;
+        pPortability->duplex =1;
+    }
+    else if ((regVal & (0x3 << 4)) >> 4 == 0x0)
+    {
+        pPortability->speed = 0;
+        pPortability->duplex =0;
+    }
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt_set
+ * Description:
+ *      Set external interface force linking configuration.
+ * Input:
+ *      port    -   port number
+ *      mode - external interface mode
+ *      pPortability - port ability configuration
+ * Output:
+ *      None 
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure
+ *      RT_ERR_INPUT       - Invalid input parameters.
+ * Note:
+ *      (1) This API can set external interface 0 and 1(MAC4 and MAC 5)force mode properties,
+ *      including link status,speed,duplex,and tx pause and tx pause ability.
+ *      In force mode, autoNegotiation ability must be disabled.
+ *      (2) For 8306E, the external interface 0(MAC 4) operating mode can be
+ *      MAC Mode MII, PHY Mode MII and RMII. The operating mode is 
+ *      determined by strapping pin upon reset, and can not be configured 
+ *      by software.  
+ *      (3) For 8306E, the external interface 1(MAC 5) operating mode can be
+ *      MAC Mode (T)MII, PHY Mode (T)MII and RMII. The operating mode is 
+ *      determined by strapping pin upon reset, and can not be configured 
+ *      by software, except the selection of MII or TMII. 
+ *      (4)The input parament mode here is only used to select MII or TMII. And it only takes effect
+ *      for external interface 1, neither for external interface 0.
+ *      When operating mode is configured as MAC Mode (T)MII or PHY Mode (T)MII
+ *      via strapping pin, then the selection of MII or TMII can be done via software.
+ *      For example, set mode MODE_EXT_TMII_MAC to select TMII, and set mode
+ *      MODE_EXT_MII_MAC to select MII.
+ */
+rtk_api_ret_t rtk_port_macForceLinkExt_set(rtk_port_t port, rtk_mode_ext_t mode, rtk_port_mac_ability_t *pPortability)
+{
+    rtk_api_ret_t retVal;
+    uint32 regVal;
+
+    if (port > RTL8306_PORT5)
+        return RT_ERR_INPUT; 
+    if (pPortability->speed > 1 || pPortability->duplex > 1 || pPortability->txpause > 1 ||
+        pPortability->rxpause > 1 || pPortability->link > 1)
+        return RT_ERR_INPUT; 
+
+    if (RTL8306_PORT4 == port)
+    {
+        /*must be in forcemode*/
+        pPortability->forcemode = 1;
+
+        /*Nway ability must be disabled*/
+        pPortability->nway = 0;
+
+        if ((retVal = rtl8306e_regbit_set (5, 0, 12, 0, 0)) != RT_ERR_OK)
+            return retVal;
+        rtl8306e_regbit_get (5, 0, 12, 0, &regVal);
+        
+        /*speed and duplex*/
+        rtl8306e_reg_get(5, 0, 0, &regVal);
+        regVal &= ~((0x1<<13) | (0x1<<8));
+        if (pPortability->speed == PORT_SPEED_100M) 
+            regVal |= (0x1 << 13);
+        else
+            regVal |= 0;
+        if (pPortability->duplex == PORT_FULL_DUPLEX)
+            regVal |= (0x1 << 8);
+        else
+            regVal |= 0;    
+        if ((retVal = rtl8306e_reg_set (5, 0, 0, regVal)) != RT_ERR_OK)
+            return retVal;
+        /*Enable advertising symmetric flow control ability of MAC 4*/
+        if (pPortability->symflc)
+            rtl8306e_regbit_set (5, 4, 10, 0, 1);
+        else 
+            rtl8306e_regbit_set (5, 4, 10, 0, 0);
+    }
+    else if (RTL8306_PORT5 == port)
+    {
+        if (MODE_EXT_TMII_MAC == mode || MODE_EXT_TMII_PHY == mode)
+        {
+            rtl8306e_regbit_set (0, 16, 14, 0, 1);
+            rtl8306e_regbit_set (4, 27, 12, 0, 1);    
+        }
+        else if (MODE_EXT_MII_MAC == mode || MODE_EXT_MII_PHY == mode)
+        {
+            rtl8306e_regbit_set (0, 16, 14, 0, 0);
+            rtl8306e_regbit_set (4, 27, 12, 0, 0); 
+        }
+
+        /*must be in forcemode*/
+        pPortability->forcemode = 1;
+
+        /*Nway ability must be disabled*/
+        pPortability->nway = 0;
+        if ((retVal = rtl8306e_regbit_set (6, 22, 6, 0, 0)) != RT_ERR_OK)
+            return retVal;
+        
+        if ((retVal = rtl8306e_regbit_set (6, 22, 15, 0, pPortability->link ? 1 : 0)) != RT_ERR_OK)
+            return retVal;
+        
+        rtl8306e_reg_get(6, 22, 0, &regVal);
+        regVal &= (~0x30);
+        if ((pPortability->speed == PORT_SPEED_100M) && (pPortability->duplex == PORT_FULL_DUPLEX))
+            regVal |= 0x30; 
+        else if ((pPortability->speed == PORT_SPEED_10M) && (pPortability->duplex == PORT_FULL_DUPLEX))
+            regVal |= 0x10;
+        else if ((pPortability->speed == PORT_SPEED_100M) && (pPortability->duplex == PORT_HALF_DUPLEX ))
+            regVal |= 0x20;
+        else
+            regVal |= 0x0;
+        if ((retVal = rtl8306e_reg_set (6, 22, 0, regVal)) != RT_ERR_OK)
+            return retVal;
+
+        /*Enable symmetric flow control of MAC 5*/
+        if (pPortability->symflc)
+        {
+           rtl8306e_regbit_set (6, 24, 12, 0, 0);
+           rtl8306e_regbit_set (6, 4, 10, 0, 1);
+        }
+        /*Enable asymmetric flow control of MAC 5*/
+        else
+        {
+            rtl8306e_regbit_set (6, 4, 10, 0, 0);
+            if ((retVal = rtl8306e_regbit_set (6, 24, 12, 0, 1)) != RT_ERR_OK)
+                return retVal;
+            if ((retVal = rtl8306e_regbit_set (6, 24, 14, 0, pPortability->txpause ? 0 : 1)) != RT_ERR_OK)
+                return retVal;
+            if ((retVal = rtl8306e_regbit_set (6, 24, 13, 0, pPortability->rxpause ? 0 : 1)) != RT_ERR_OK)
+                return retVal;
+        }        
+    }
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt_get
+ * Description:
+ *      Get external interface force linking configuration.
+ * Input:
+ *      port    -   port number
+ * Output:
+ *      pMode - external interface mode
+ *      pPortability - port ability configuration
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_INPUT - Invalid input parameters.
+ *      RT_ERR_NULL_POINTER - Null pointer
+ * Note:
+ *      This API can get external interface 0 (MAC 4) and 1 (MAC 5) force mode properties.
+ *      The external interface 0 operating mode can be:
+ *      - MODE_EXT_MII_MAC,
+ *      - MODE_EXT_MII_PHY, 
+ *      - MODE_EXT_RMII,     
+ *      The external interface 1 operating mode can be:
+ *      - MODE_EXT_MII_MAC,
+ *      - MODE_EXT_MII_PHY, 
+ *      - MODE_EXT_TMII_MAC,
+ *      - MODE_EXT_TMII_PHY, 
+ *      - MODE_EXT_RMII, 
+ */
+rtk_api_ret_t rtk_port_macForceLinkExt_get(rtk_port_t port, rtk_mode_ext_t *pMode, rtk_port_mac_ability_t *pPortability)
+{
+    uint32 regVal;
+    uint32 modesel;
+
+    if (port > RTL8306_PORT5)
+        return RT_ERR_INPUT; 
+    if((NULL == pMode) || (NULL == pPortability))
+        return RT_ERR_NULL_POINTER;
+
+    if (RTL8306_PORT4 == port)
+    {
+        rtl8306e_regbit_set(0, 16, 11, 0, 1);
+        rtl8306e_reg_get(6, 26, 3, &regVal);
+        modesel = regVal & 0x1F;
+        if (0x2 == modesel || 0x4 == modesel || 0x5 == modesel || 0x6 == modesel || 0x7 == modesel || \
+            0x14  == modesel || 0x15 == modesel || 0x16 == modesel || 0x17 == modesel)
+            *pMode = MODE_EXT_MII_PHY;
+        else if (0x8 == modesel || 0x9 == modesel || 0xA == modesel || 0xB == modesel || 0xC == modesel || 0xD == modesel || \
+            0xE == modesel || 0xF == modesel || 0x1C == modesel || 0x1D == modesel || 0x1E == modesel || 0X1F == modesel)
+            *pMode = MODE_EXT_MII_MAC;
+        else if (0x0 == modesel || 0x1 == modesel || 0x3 == modesel || 0x11 == modesel || 0x13 == modesel)
+            *pMode = MODE_EXT_RMII;
+        else
+            *pMode = MODE_EXT_END;
+
+        /*get nway bility*/
+        rtl8306e_regbit_get (5, 0, 12, 0, &regVal);
+        pPortability->nway = regVal ? 1 : 0;
+        pPortability->forcemode = regVal ? 0: 1;
+        
+        /*get speed and duplex ability*/
+        rtl8306e_regbit_get (5, 0, 13, 0, &regVal);
+        if(regVal)
+            pPortability->speed =PORT_SPEED_100M;
+        else 
+            pPortability->speed = PORT_SPEED_10M;
+        
+        rtl8306e_regbit_get (5, 0, 8, 0, &regVal);
+        if(regVal)
+            pPortability->duplex = PORT_FULL_DUPLEX;
+        else
+            pPortability->duplex = PORT_HALF_DUPLEX;
+        
+        /*get asymmetric flow control aibility*/
+        rtl8306e_regbit_get (5, 4, 10, 0, &regVal);
+        pPortability->symflc = regVal ? 1 : 0;
+        pPortability->rxpause = regVal ? 1 : 0;
+        pPortability->txpause = regVal ? 1 : 0;
+
+        /*get link status*/
+        rtl8306e_regbit_get (5, 1, 2, 0, &regVal);
+        pPortability->link= regVal ? 1 : 0;        
+    }
+    else if (RTL8306_PORT5 == port)
+    {
+        rtl8306e_regbit_set(0, 16, 11, 0, 1);
+        rtl8306e_reg_get(6, 26, 3, &regVal);
+        modesel = regVal & 0x1F;
+        if (0x1 == modesel || 0x2 == modesel || 0x9 == modesel || 0x12 == modesel || 0x10 == modesel)
+            *pMode = MODE_EXT_MII_PHY;
+        else if (0xA == modesel || 0xB == modesel)
+            *pMode = MODE_EXT_MII_MAC;
+        else if (0x0 == modesel || 0x8 == modesel || 0x11 == modesel)
+            *pMode = MODE_EXT_RMII;
+        else
+            *pMode = MODE_EXT_END;
+        
+        rtl8306e_regbit_get (0, 16, 14, 0, &regVal);
+        if (regVal && (MODE_EXT_MII_PHY == *pMode))
+            *pMode = MODE_EXT_TMII_PHY;
+        
+        if (regVal && (MODE_EXT_MII_MAC == *pMode))
+            *pMode = MODE_EXT_TMII_MAC;
+
+
+        rtl8306e_regbit_get (6, 22, 6, 0, &regVal);
+        pPortability->nway = regVal ? 1 : 0;
+        pPortability->forcemode = regVal ? 0: 1;
+
+        rtl8306e_regbit_get (6, 24, 12, 0, &regVal);
+        pPortability->symflc = regVal ? 0 : 1;
+        
+        rtl8306e_regbit_get (6, 24, 13, 0, &regVal);
+        pPortability->rxpause = regVal ? 0 : 1;
+
+        rtl8306e_regbit_get (6, 24, 14, 0, &regVal);
+        pPortability->txpause = regVal ? 0 : 1;
+
+        rtl8306e_regbit_get (6, 22, 15, 0, &regVal);
+        pPortability->link= regVal ? 1 : 0;
+
+        rtl8306e_reg_get (6, 22, 0, &regVal);
+        if ((regVal & (0x3 << 4)) >> 4 == 0x3)
+        {
+            pPortability->speed =PORT_SPEED_100M;
+            pPortability->duplex =PORT_FULL_DUPLEX;
+        }
+        else if ((regVal & (0x3 << 4)) >> 4 == 0x2)
+        {
+            pPortability->speed = PORT_SPEED_100M;
+            pPortability->duplex = PORT_HALF_DUPLEX;
+        }
+        else if ((regVal & (0x3 << 4)) >> 4 == 0x1)
+        {
+            pPortability->speed = PORT_SPEED_10M;
+            pPortability->duplex =PORT_FULL_DUPLEX;
+        }
+        else if ((regVal & (0x3 << 4)) >> 4 == 0x0)
+        {
+            pPortability->speed = PORT_SPEED_10M;
+            pPortability->duplex =PORT_HALF_DUPLEX;
+        }    
+    }
+
+    return RT_ERR_OK;
+}
+
+#ifdef CHIP_RTL8304E
+/* Function Name:
+ *      rtk_port_mii1Disable_set
+ * Description:
+ *      Disable MII1 for RTL8304E by trunk
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ * Note:
+ *      Strapping pin 49 can be used to force MII1 link down for RTL8306E.
+ *      But there are no strapping pins or registers for RTL8304E to do so.
+ *      To disable MII1 for RTL8304E, trunk can be used. First enable trunk function,
+ *      Then trunk rtl8306e's port3 and port4 to be a trunk port. After this port2(MII1) is 
+ *      forced to be linking down for RTL8304E.    
+*/
+rtk_api_ret_t rtk_port_mii1Disable_set(void)
+{
+    rtl8306e_regbit_set(0,19,11,0,0);
+    rtl8306e_regbit_set(0,16,6,0,0);
+
+    return RT_ERR_OK;
+}
+#endif
+
+/* Function Name:
+ *      rtk_port_isolation_set
+ * Description:
+ *      Set permitted port isolation portmask
+ * Input:
+ *      port                - port id, 0 ~ 5 
+ *      portmask         - Permit port mask
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK             -   Success
+ *      RT_ERR_PORT_ID     -   Invalid port number
+ *      RT_ERR_PORT_MASK -   Invalid portmask
+ *      RT_ERR_FAILED        -   Failure
+ * Note:
+ *      This API set the port mask that a port can trasmit packet to of each port.
+ *      A port can only transmit packet to ports included in permitted portmask  
+ */
+rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t portmask)
+{
+    rtk_api_ret_t retVal;
+    uint32 isomask;
+    uint32 regval;
+
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+
+    if( portmask.bits[0] > RTK_MAX_PORT_MASK)
+        return RT_ERR_PORT_MASK;
+    
+    isomask = (~ (portmask.bits[0])) & 0x3F;
+    rtl8306e_reg_get(0, 29, 3, &regval);
+    switch (port)
+    {
+        case 0:
+            regval &= ~0x1F;
+            if (isomask & 0x2)
+                regval |=  (1 << 0); 
+            if (isomask & 0x4)
+                regval |=  (1 << 1); 
+            if (isomask & 0x8)
+                regval |=  (1 << 2); 
+            if (isomask & 0x10)
+                regval |=  (1 << 3); 
+            if (isomask & 0x20)
+                regval |=  (1 << 4); 
+            break;
+        case 1:
+            regval &= ~0x1E1;
+            if (isomask & 0x1)
+                regval |=  (1 << 0); 
+            if (isomask & 0x4)
+                regval |=  (1 << 5); 
+            if (isomask & 0x8)
+                regval |=  (1 << 6); 
+            if (isomask & 0x10)
+                regval |=  (1 << 7); 
+            if (isomask & 0x20)
+                regval |=  (1 << 8); 
+            break;
+        case 2:
+            regval &= ~0xE42;
+            if (isomask & 0x1)
+                regval |=  (1 << 1); 
+            if (isomask & 0x2)
+                regval |=  (1 << 5); 
+            if (isomask & 0x8)
+                regval |=  (1 << 9); 
+            if (isomask & 0x10)
+                regval |=  (1 << 10); 
+            if (isomask & 0x20)
+                regval |=  (1 << 11); 
+            break;
+        case 3:
+            regval &= ~0x3244;
+            if (isomask & 0x1)
+                regval |=  (1 << 2); 
+            if (isomask & 0x2)
+                regval |=  (1 << 6); 
+            if (isomask & 0x4)
+                regval |=  (1 << 9);
+            if (isomask & 0x10)
+                regval |=  (1 << 12); 
+            if (isomask & 0x20)
+                regval |=  (1 << 13); 
+            break;
+        case 4:
+            regval &= ~0x5488;
+            if (isomask & 0x1)
+                regval |=  (1 << 3); 
+            if (isomask & 0x2)
+                regval |=  (1 << 7); 
+            if (isomask & 0x4)
+                regval |=  (1 << 10);
+            if (isomask & 0x8)
+                regval |=  (1 << 12); 
+            if (isomask & 0x20)
+                regval |=  (1 << 14); 
+            break;
+        case 5:
+            regval &= ~0x6910;
+            if (isomask & 0x1)
+                regval |=  (1 << 4); 
+            if (isomask & 0x2)
+                regval |=  (1 << 8); 
+            if (isomask & 0x4)
+                regval |=  (1 << 11);
+            if (isomask & 0x8)
+                regval |=  (1 << 13); 
+            if (isomask & 0x10)
+                regval |=  (1 << 14); 
+            break;
+        default:
+            return RT_ERR_PORT_ID;
+    }
+    if((retVal= rtl8306e_reg_set(0, 29, 3, regval)) != RT_ERR_OK)
+        return retVal;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_port_isolation_get
+ * Description:
+ *      Get permitted port isolation portmask
+ * Input:
+ *      port                - port id, 0 ~ 5 
+ * Output:
+ *      pPortmask       - the pointer of permit port mask
+ * Return:
+ *      RT_ERR_OK                  -   Success
+ *      RT_ERR_PORT_ID          -   Invalid port number
+ *      RT_ERR_NULL_POINTER  -   Input parameter is null pointer
+ *      RT_ERR_FAILED             -   Failure
+ * Note:
+ *      This API get the port mask that a port can transmit packet to of each port.
+ *      A port can only transmit packet to ports included in permitted portmask  
+ */
+rtk_api_ret_t rtk_port_isolation_get(rtk_port_t port, rtk_portmask_t *pPortmask)
+{
+    uint32 isomask;
+    uint32 regval;
+    
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+    if (NULL == pPortmask)
+        return RT_ERR_NULL_POINTER;
+    
+    isomask = 0;
+    rtl8306e_reg_get(0, 29, 3, &regval);
+    switch (port)
+    {
+        case 0:
+            isomask |= 0x1;
+            if(regval & (1 << 0))
+                isomask |= 0x2;
+            if(regval & (1 << 1))
+                isomask |= 0x4;
+            if(regval & (1 << 2))
+                isomask |= 0x8;
+            if(regval & (1 << 3))
+                isomask |= 0x10;
+            if(regval & (1 << 4))
+                isomask |= 0x20;
+            break;
+        case 1:
+            isomask |= 0x2;
+            if(regval & (1 << 0))
+                isomask |= 0x1;
+            if(regval & (1 << 5))
+                isomask |= 0x4;
+            if(regval & (1 << 6))
+                isomask |= 0x8;
+            if(regval & (1 << 7))
+                isomask |= 0x10;
+            if(regval & (1 << 8))
+                isomask |= 0x20;
+            break;
+        case 2:
+            isomask |= 0x4;
+            if(regval & (1 << 1))
+                isomask |= 0x1;
+            if(regval & (1 << 5))
+                isomask |= 0x2;
+            if(regval & (1 << 9))
+                isomask |= 0x8;
+            if(regval & (1 << 10))
+                isomask |= 0x10;
+            if(regval & (1 << 11))
+                isomask |= 0x20;
+            break;
+        case 3:
+            isomask |= 0x8;
+            if(regval & (1 << 2))
+                isomask |= 0x1;
+            if(regval & (1 << 6))
+                isomask |= 0x2;
+            if(regval & (1 << 9))
+                isomask |= 0x4;
+            if(regval & (1 << 12))
+                isomask |= 0x10;
+            if(regval & (1 << 13))
+                isomask |= 0x20;
+            break;
+        case 4:
+            isomask |= 0x10;
+            if(regval & (1 << 3))
+                isomask |= 0x1;
+            if(regval & (1 << 7))
+                isomask |= 0x2;
+            if(regval & (1 << 10))
+                isomask |= 0x4;
+            if(regval & (1 << 12))
+                isomask |= 0x8;
+            if(regval & (1 << 14))
+                isomask |= 0x20;
+            break;
+        case 5:
+            isomask |= 0x20;
+            if(regval & (1 << 4))
+                isomask |= 0x1;
+            if(regval & (1 << 8))
+                isomask |= 0x2;
+            if(regval & (1 << 11))
+                isomask |= 0x4;
+            if(regval & (1 << 13))
+                isomask |= 0x8;
+            if(regval & (1 << 14))
+                isomask |= 0x10;
+            break;
+        default:
+            return RT_ERR_PORT_ID;
+    }
+    pPortmask->bits[0] = (~isomask) & 0x3F;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_stat_port_reset
+ * Description:
+ *      Reset per port MIB counter by port.
+ * Input:
+ *      port - port id.
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - set shared meter successfully
+ *      RT_ERR_FAILED          - FAILED to iset shared meter
+ * Note:
+ */
+rtk_api_ret_t rtk_stat_port_reset(rtk_port_t port)
+{
+    rtk_api_ret_t retVal;
+
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID; 
+    
+    if ((retVal = rtl8306e_mib_reset(port) ) != RT_ERR_OK)
+        return retVal; 
+        
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_rate_igrBandwidthCtrlRate_set
+ * Description:
+ *      Set port ingress bandwidth control
+ * Input:
+ *      port            -  Port id
+ *      rate            -  Rate of share meter
+ *      ifg_include   -  Rate's calculation including IFG, ENABLED:include DISABLED:exclude
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK              -  Success
+ *      RT_ERR_PORT_ID      -  Invalid port number
+ *      RT_ERR_FAILED        -  Failure
+ *      RT_ERR_ENABLE       -  Invalid IFG parameter
+ *      RT_ERR_INBW_RATE -  Invalid ingress rate parameter
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+
+rtk_api_ret_t rtk_rate_igrBandwidthCtrlRate_set( rtk_port_t port, rtk_rate_t rate,  rtk_enable_t ifg_include)
+{
+    rtk_api_ret_t retVal;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    
+    if (rate > RTL8306_QOS_RATE_INPUT_MAX) 
+        return RT_ERR_INBW_RATE;
+
+    if(ifg_include >= RTK_ENABLE_END)
+        return RT_ERR_ENABLE;
+
+    if((retVal = rtl8306e_qos_portRate_set(port, rate, RTL8306_PORT_RX , TRUE)) != RT_ERR_OK)
+        return retVal;
+
+    rtl8306e_regbit_set(0, 21, 14, 3, ifg_include ? 1:0);
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_rate_igrBandwidthCtrlRate_get
+ * Description:
+ *      Get port ingress bandwidth control
+ * Input:
+ *      port             -  Port id
+ * Output:
+ *      pRate           -  the pointer of rate of share meter
+ *      pIfg_include   -  Rate's calculation including IFG, ENABLED:include DISABLED:exclude
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_PORT_ID              -  Invalid port number
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_ENABLE               -  Invalid IFG parameter
+ *      RT_ERR_NULL_POINTER      -  null pointer
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+ 
+rtk_api_ret_t rtk_rate_igrBandwidthCtrlRate_get(rtk_port_t port, rtk_rate_t *pRate, rtk_enable_t *pIfg_include)
+{
+    rtk_api_ret_t retVal;
+    uint32 enabled;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if((NULL == pRate) || (NULL == pIfg_include))
+        return RT_ERR_NULL_POINTER;
+    
+    if((retVal = rtl8306e_qos_portRate_get(port, pRate, RTL8306_PORT_RX, &enabled)) != SUCCESS)
+        return retVal;
+
+    if(!enabled)
+        *pRate = RTL8306_QOS_RATE_INPUT_MAX;
+
+    rtl8306e_regbit_get(0, 21, 14, 3, &enabled);
+    *pIfg_include = enabled ? ENABLED : DISABLED;
+        
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_rate_egrBandwidthCtrlRate_set
+ * Description:
+ *      Set port egress bandwidth control
+ * Input:
+ *      port            -  Port id
+ *      rate            -  Rate of bandwidth control
+ *      ifg_include   -  Rate's calculation including IFG, ENABLED:include DISABLED:exclude
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                   -  Success
+ *      RT_ERR_PORT_ID           -  Invalid port number
+ *      RT_ERR_FAILED             -  Failure
+ *      RT_ERR_ENABLE             -  Invalid IFG parameter
+ *      RT_ERR_QOS_EBW_RATE -  Invalid egress rate parameter
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+
+rtk_api_ret_t rtk_rate_egrBandwidthCtrlRate_set(rtk_port_t port, rtk_rate_t rate,  rtk_enable_t ifg_include)
+{
+    rtk_api_ret_t retVal;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    
+    if (rate > RTL8306_QOS_RATE_INPUT_MAX) 
+        return RT_ERR_QOS_EBW_RATE;
+
+    if(ifg_include >= RTK_ENABLE_END)
+        return RT_ERR_ENABLE;
+
+    if((retVal = rtl8306e_qos_portRate_set(port, rate, RTL8306_PORT_TX , TRUE)) != RT_ERR_OK)
+        return retVal;
+
+    rtl8306e_regbit_set(port, 17, 15, 2, ifg_include ? 0 :1);
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_rate_igrBandwidthCtrlRate_get
+ * Description:
+ *      Get port ingress bandwidth control
+ * Input:
+ *      port             -  Port id
+ * Output:
+ *      pRate           -  the pointer of rate of bandwidth control
+ *      pIfg_include   -  Rate's calculation including IFG, ENABLED:include DISABLED:exclude
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_PORT_ID             -  Invalid port number
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_NULL_POINTER      -  null pointer
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+
+rtk_api_ret_t rtk_rate_egrBandwidthCtrlRate_get(rtk_port_t port, rtk_rate_t *pRate, rtk_enable_t *pIfg_include)
+{
+    rtk_api_ret_t retVal;
+    uint32 enabled;
+    uint32 disabled;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if((NULL == pRate) || (NULL == pIfg_include))
+        return RT_ERR_NULL_POINTER;
+    
+    if((retVal = rtl8306e_qos_portRate_get(port, pRate, RTL8306_PORT_TX, &enabled)) != SUCCESS)
+        return retVal;
+
+    if(!enabled)
+        *pRate = RTL8306_QOS_RATE_INPUT_MAX;
+
+    rtl8306e_regbit_get(port, 17, 15, 2, &disabled);
+    *pIfg_include = disabled ? DISABLED : ENABLED;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_init
+ * Description:
+ *      Configure Qos default settings with queue number assigment to each port
+ * Input:
+ *      queueNum     -  Queue number of each port
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_QUEUE_NUM         -  Error queue number
+ * Note:
+ *    This API will initialize related Qos setting with queue number assigment.
+ *    The queue number is from 1 to 4.
+ */
+
+rtk_api_ret_t rtk_qos_init(rtk_queue_num_t queueNum)
+{
+    uint32 queue, port;
+    
+    if (rtl8306e_qos_queueNum_set(queueNum) == FAILED)
+        return FAILED;
+    
+    switch(queueNum)
+    {
+        case 1:
+            /*priority to qid mapping*/
+            rtl8306e_qos_priToQueMap_set(0, 0);
+            rtl8306e_qos_priToQueMap_set(1, 0);       
+            rtl8306e_qos_priToQueMap_set(2, 0);                   
+            rtl8306e_qos_priToQueMap_set(3, 0);                               
+            break;
+            
+        case 2:
+            /*priority to qid mapping*/
+            rtl8306e_qos_priToQueMap_set(0, 0);
+            rtl8306e_qos_priToQueMap_set(1, 0);       
+            rtl8306e_qos_priToQueMap_set(2, 1);                   
+            rtl8306e_qos_priToQueMap_set(3, 1);                                           
+            break;
+            
+        case 3:
+            /*priority to qid mapping*/
+            rtl8306e_qos_priToQueMap_set(0, 0);
+            rtl8306e_qos_priToQueMap_set(1, 1);       
+            rtl8306e_qos_priToQueMap_set(2, 1);                   
+            rtl8306e_qos_priToQueMap_set(3, 2);                                                       
+            break;            
+            
+        case 4:
+            /*priority to qid mapping*/
+            rtl8306e_qos_priToQueMap_set(0, 0);
+            rtl8306e_qos_priToQueMap_set(1, 1);       
+            rtl8306e_qos_priToQueMap_set(2, 2);                   
+            rtl8306e_qos_priToQueMap_set(3, 3);
+
+            for(queue = 0; queue < 4; queue++)
+            {
+                /*queue threshold*/
+                rtl8306e_qos_queFlcThr_set(queue, RTL8306_FCO_QLEN, RTL8306_FCON, RTL8306_FCO_SET0, 9);
+                rtl8306e_qos_queFlcThr_set(queue, RTL8306_FCO_QLEN, RTL8306_FCOFF, RTL8306_FCO_SET0, 5);        
+                rtl8306e_qos_queFlcThr_set(queue, RTL8306_FCO_DSC, RTL8306_FCON, RTL8306_FCO_SET0, 40);
+                rtl8306e_qos_queFlcThr_set(queue, RTL8306_FCO_DSC, RTL8306_FCOFF, RTL8306_FCO_SET0, 28);                                     
+
+            }
+            for (port = 0; port < 6; port ++)
+            {
+                rtl8306e_qos_portFlcThr_set(port, 130, 100,  RTL8306_PORT_TX); 
+                for(queue = 0; queue < 4; queue++)
+                {
+                    /*queue threshold*/
+                    rtl8306e_qos_queFlcEnable_set(port, queue, TRUE);           
+                }
+            }
+                                      
+            break;
+            
+        default:
+            return RT_ERR_QUEUE_NUM;
+            
+    }
+
+    rtl8306e_qos_softReset_set();    
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_priSel_set
+ * Description:
+ *      Configure the priority order among different priority mechanisms.
+ * Input:
+ *      pPriDec - priority level for port, dscp, 802.1Q, ACL and VID based priority decision.
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - success
+ *      RT_ERR_NULL_POINTER  -   Input parameter is null pointer
+ *      RT_ERR_FAILED          - failure 
+ *      RT_ERR_QOS_SEL_PRI_SOURCE - Invalid priority decision source parameter.
+ * Note: 
+ *      (1)For 8306E, there are 5 types of priority mechanisms that could be set arbitration level, which are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority, Port-based priority, VID-based priority.
+ *      Each one could be set level from 1 to 5.
+ *      (2)ASIC will follow user's arbitration level setting of priority mechanisms to select internal priority for receiving frame. 
+ *      If two priority mechanisms are the same level, the ASIC will chose the priority mechanism with highest level to 
+ *      assign internal priority to receiving frame.
+ */
+rtk_api_ret_t rtk_qos_priSel_set(rtk_priority_select_t *pPriDec)
+{ 
+    rtk_api_ret_t retVal;
+    rtl8306e_qosPriArbitPara_t priArbit;
+
+    if (NULL == pPriDec)
+        return RT_ERR_NULL_POINTER;
+    if (pPriDec->port_pri > 5 || pPriDec->dot1q_pri > 5 || pPriDec->acl_pri > 5 || pPriDec->dscp_pri > 5 
+        || pPriDec->vid_pri > 5)
+        return RT_ERR_QOS_SEL_PRI_SOURCE;
+
+    priArbit.port_pri_lev = pPriDec->port_pri;
+    priArbit.acl_pri_lev = pPriDec->acl_pri;
+    priArbit.dscp_pri_lev = pPriDec->dscp_pri;
+    priArbit.dot1q_pri_lev = pPriDec->dot1q_pri;
+    priArbit.vid_pri_lev = pPriDec->vid_pri;
+
+    if ((retVal = rtl8306e_qos_priSrcArbit_set(priArbit)) != RT_ERR_OK)
+        return retVal;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_priSel_get
+ * Description:
+ *      Get the priority order configuration among different priority mechanism.
+ * Input:
+ *      None
+ * Output:
+ *      pPriDec - priority level for port, dscp, 802.1Q, ACL and VID based priority decision.
+ * Return:
+ *      RT_ERR_OK              - success
+ *      RT_ERR_NULL_POINTER  -   Input parameter is null pointer
+ *      RT_ERR_FAILED          - failure 
+ * Note:
+ *      (1)For 8306E, there are 5 types of priority mechanisms that could be set arbitration level, which are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority,Port-based priority, VID-based priority.
+ *      Each one could be set level from 1 to 5.
+ *      (2)ASIC will follow user's arbitration level setting of priority mechanisms to select internal priority for receiving frame. 
+ *      If two priority mechanisms are the same level, the ASIC will chose the priority mechanism with the highest level to 
+ *      assign internal priority to receiving frame.
+ */
+
+rtk_api_ret_t rtk_qos_priSel_get(rtk_priority_select_t *pPriDec)
+{
+    rtk_api_ret_t retVal;
+    rtl8306e_qosPriArbitPara_t priArbit;   
+
+    if (NULL == pPriDec)
+        return RT_ERR_NULL_POINTER;
+    
+    if ((retVal = rtl8306e_qos_priSrcArbit_get(&priArbit)) != RT_ERR_OK)
+        return retVal;
+    pPriDec->port_pri = priArbit.port_pri_lev;
+    pPriDec->dot1q_pri = priArbit.dot1q_pri_lev;
+    pPriDec->dmac_pri = priArbit.dscp_pri_lev;
+    pPriDec->acl_pri = priArbit.acl_pri_lev;
+    pPriDec->vid_pri = priArbit.vid_pri_lev;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_1pPriRemap_set
+ * Description:
+ *      Configure 1Q priorities mapping to internal absolute priority
+ * Input:
+ *      dot1p_pri   -  802.1p priority value
+ *      int_pri       -  internal priority value
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_VLAN_PRIORITY        -  Invalid 1p priority
+ *      RT_ERR_QOS_INT_PRIORITY   -  Invalid priority
+ * Note:
+ *      Priority of 802.1Q assignment for internal asic priority, and it is used for queue usage 
+ *      and packet scheduling.
+ */
+rtk_api_ret_t rtk_qos_1pPriRemap_set(rtk_pri_t dot1p_pri, rtk_pri_t int_pri)
+{
+    rtk_api_ret_t retVal;
+
+    if (int_pri > RTL8306_PRIO3)
+        return RT_ERR_QOS_INT_PRIORITY;
+    
+    if (dot1p_pri > RTL8306_1QTAG_PRIO7)
+        return  RT_ERR_VLAN_PRIORITY;
+    
+    if ((retVal = rtl8306e_qos_1pPriRemap_set(dot1p_pri, int_pri)) != SUCCESS)
+        return retVal;
+    
+    return RT_ERR_OK;    
+}
+
+/* Function Name:
+ *      rtk_qos_1pPriRemap_get
+ * Description:
+ *      Get 1Q priorities mapping to internal absolute priority
+ * Input:
+ *      dot1p_pri    -  802.1p priority value
+ * Output:
+ *      pInt_pri      -  the pointer of internal priority value
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_VLAN_PRIORITY        -  Invalid 1p priority
+ *      RT_ERR_NULL_POINTER         -   null pointer
+ * Note:
+ *      Priority of 802.1Q assignment for internal asic priority, and it is used for queue usage 
+ *      and packet scheduling.
+ */
+
+rtk_api_ret_t rtk_qos_1pPriRemap_get(rtk_pri_t dot1p_pri, rtk_pri_t *pInt_pri)
+{
+    rtk_api_ret_t retVal;
+    
+    if(NULL == pInt_pri)
+        return RT_ERR_NULL_POINTER;
+
+    if (dot1p_pri > RTL8306_1QTAG_PRIO7)
+        return  RT_ERR_VLAN_PRIORITY;
+    
+    if((retVal = rtl8306e_qos_1pPriRemap_get(dot1p_pri, pInt_pri)) != SUCCESS)
+        return retVal;
+    
+    return RT_ERR_OK;    
+}
+
+
+/* Function Name:
+ *      rtk_qos_dscpPriRemap_set
+ * Description:
+ *      Set DSCP-based priority
+ * Input:
+ *      code      -  dscp code
+ *      int_pri    -  internal priority value
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_QOS_INT_PRIORITY   -  invalid internal priority
+ *      RT_ERR_QOS_DSCP_VALUE    -   invalid DSCP value  
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *
+ *     The Differentiated Service Code Point is a selector for router's per-hop behaviors. As a selector, there is no implication that a numerically 
+ *     greater DSCP implies a better network service. As can be seen, the DSCP totally overlaps the old precedence field of TOS. So if values of 
+ *     DSCP are carefully chosen then backward compatibility can be achieved.         
+ */ 
+rtk_api_ret_t rtk_qos_dscpPriRemap_set(rtk_dscp_t dscp, rtk_pri_t int_pri)
+{
+    rtk_api_ret_t retVal;
+
+    if (int_pri > RTL8306_PRIO3 )
+        return RT_ERR_QOS_INT_PRIORITY; 
+
+    if (dscp > RTL8306_DSCP_BF)
+        return RT_ERR_QOS_DSCP_VALUE; 
+
+    if((retVal = rtl8306e_qos_dscpPriRemap_set(dscp, int_pri)) != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    return RT_ERR_OK;    
+}
+
+
+/* Function Name:
+ *      rtk_qos_dscpPriRemap_get
+ * Description:
+ *      Get DSCP-based priority
+ * Input:
+ *      dscp      -  dscp code
+ * Output:
+ *      pInt_pri  -  the pointer of internal priority value
+ * Return:
+ *      RT_ERR_OK                           -  Success
+ *      RT_ERR_FAILED                     -  Failure
+ *      RT_ERR_QOS_DSCP_VALUE      -  Invalid DSCP value
+ *      RT_ERR_NULL_POINTER           -  Input parameter is null pointer
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *     The Differentiated Service Code Point is a selector for router's per-hop behaviors. As a selector, there is no implication that a numerically 
+ *     greater DSCP implies a better network service. As can be seen, the DSCP totally overlaps the old precedence field of TOS. So if values of 
+ *     DSCP are carefully chosen then backward compatibility can be achieved.         
+ */ 
+rtk_api_ret_t rtk_qos_dscpPriRemap_get(rtk_dscp_t dscp, rtk_pri_t *pInt_pri)
+{
+    rtk_api_ret_t retVal;
+    
+    if (dscp > RTL8306_DSCP_BF)
+        return RT_ERR_QOS_DSCP_VALUE; 
+    
+    if(NULL == pInt_pri)
+        return RT_ERR_NULL_POINTER;
+
+    if((retVal = rtl8306e_qos_dscpPriRemap_get(dscp, pInt_pri)) != SUCCESS)
+        return RT_ERR_FAILED;
+    
+
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_qos_portPri_set
+ * Description:
+ *      Configure priority usage to each port
+ * Input:
+ *      port                - Port id.                
+ *      int_pri             -  internal priority value
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_PORT_ID                -   Error port id
+ *      RT_ERR_QOS_INT_PRIORITY  -   Error internal priority value
+ * Note:
+ *     The API can set priority of port assignments for queue usage and packet scheduling.
+ */
+rtk_api_ret_t rtk_qos_portPri_set(rtk_port_t port, rtk_pri_t int_pri)
+{
+    rtk_api_ret_t retVal;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if (int_pri > RTL8306_PRIO3 )
+        return RT_ERR_QOS_INT_PRIORITY; 
+
+    if((retVal = rtl8306e_qos_portPri_set(port, int_pri)) != SUCCESS)
+        return retVal;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_portPri_get
+ * Description:
+ *      Get priority usage to each port
+ * Input:
+ *      port                  - Port id.                
+ * Output:
+ *      pInt_pri             -  the pointer of internal priority value
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_PORT_ID                -   Error port id
+ *      RT_ERR_NULL_POINTER        -   null pointer
+ * Note:
+ *      The API can get priority of port assignments for queue usage and packet scheduling.
+ */
+
+rtk_api_ret_t rtk_qos_portPri_get(rtk_port_t port, rtk_pri_t *pInt_pri)
+{
+    rtk_api_ret_t retVal;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+    
+    if(NULL == pInt_pri)
+        return RT_ERR_NULL_POINTER;
+    
+    if((retVal = rtl8306e_qos_portPri_get(port, pInt_pri)) != SUCCESS)
+        return retVal;
+
+    return RT_ERR_OK;
+
+}
+
+/* Function Name:
+ *      rtk_qos_priMap_set
+ * Description:
+ *      Set internal priority mapping to queue ID for different queue number
+ * Input:
+ *      queue_num       - Queue number usage
+ *      pPri2qid            - Priority mapping to queue ID               
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_QUEUE_ID              -   Error queue id
+ *      RT_ERR_NULL_POINTER        -   null pointer
+ * Note:
+ *      ASIC supports priority mapping to queue with different queue number from 1 to 4.
+ *      For different queue numbers usage, ASIC supports different internal available queue IDs.
+ */
+
+rtk_api_ret_t rtk_qos_priMap_set(rtk_queue_num_t queue_num, rtk_qos_pri2queue_t *pPri2qid)
+{
+    rtk_api_ret_t retVal;
+    uint32 pri;
+
+    if((queue_num > 4) || (queue_num == 0))
+        return RT_ERR_QUEUE_NUM;           
+    
+    if(NULL == pPri2qid)
+        return RT_ERR_NULL_POINTER;
+
+    if((retVal = rtl8306e_qos_queueNum_set(queue_num)) != SUCCESS)
+        return RT_ERR_FAILED;
+
+    for(pri = RTL8306_PRIO0; pri <= RTL8306_PRIO3; pri++)
+    {
+        if(pPri2qid->pri2queue[pri] > (queue_num -1)) 
+            return RT_ERR_QUEUE_ID;
+        if((retVal = rtl8306e_qos_priToQueMap_set(pri, pPri2qid->pri2queue[pri])) != SUCCESS)
+            return RT_ERR_FAILED;
+    }
+            
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_qos_priMap_get
+ * Description:
+ *      Get priority to queue ID mapping table parameters
+ * Input:
+ *      queue_num       - Queue number usage
+ *      pPri2qid            - Priority mapping to queue ID               
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_QUEUE_ID              -   Error queue id
+ *      RT_ERR_NULL_POINTER        -   null pointer
+ * Note:
+ *      ASIC supports priority mapping to queue with different queue number from 1 to 4.
+ *      For different queue numbers usage, ASIC supports different internal available queue IDs.
+ */
+ 
+rtk_api_ret_t rtk_qos_priMap_get(rtk_queue_num_t queue_num, rtk_qos_pri2queue_t *pPri2qid)
+{
+    rtk_api_ret_t retVal;
+    uint32 pri;        
+
+    if((queue_num > 4) || (queue_num == 0))
+        return RT_ERR_QUEUE_NUM;           
+    
+    if(NULL == pPri2qid)
+        return RT_ERR_NULL_POINTER;
+
+    for(pri = RTL8306_PRIO0; pri <= RTL8306_PRIO3; pri++)
+    {
+        if((retVal = rtl8306e_qos_priToQueMap_get(pri, &(pPri2qid->pri2queue[pri]))) != SUCCESS)
+            return RT_ERR_FAILED;
+    }
+        
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_1pRemarkEnable_set
+ * Description:
+ *      Set 802.1P remarking ability
+ * Input:
+ *      port       -  port number (0~5)
+ *      enabled  -  TRUE or FALSE
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK              -  Success
+ *      RT_ERR_FAILED        -   Failure
+ *      RT_ERR_PORT_ID      -   Invalid port id
+ * Note:
+ *      
+ */
+rtk_api_ret_t rtk_qos_1pRemarkEnable_set(rtk_port_t port, rtk_enable_t enable)
+{
+    rtk_api_ret_t retVal;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+
+    if((retVal = rtl8306e_qos_1pRemarkEnable_set(port, enable)) != SUCCESS)
+        return RT_ERR_FAILED;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_1pRemarkEnable_get
+ * Description:
+ *      Get 802.1P remarking ability
+ * Input:
+ *      port        -  port number (0~5)
+ * Output:
+ *      pEnabled  -  pointer of the ability status
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED               -   Failure
+ *      RT_ERR_PORT_ID             -   Invalid port id
+ *      RT_ERR_NULL_POINTER     -   Input parameter is null pointer
+ * Note:
+ *      
+ */
+rtk_api_ret_t rtk_qos_1pRemarkEnable_get(rtk_port_t port, rtk_enable_t *pEnable)
+{
+    rtk_api_ret_t retVal;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+    if(NULL == pEnable)
+        return RT_ERR_NULL_POINTER;
+    if((retVal = rtl8306e_qos_1pRemarkEnable_get(port, (uint32 *)pEnable)) != SUCCESS)
+        return RT_ERR_FAILED;    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_1pRemark_set
+ * Description:
+ *      Set 802.1P remarking priority
+ * Input:
+ *      int_pri        -  Packet priority(0~4)
+ *      dot1p_pri    -  802.1P priority(0~7)
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                           - Success
+ *      RT_ERR_FAILED                      - Failure
+ *      RT_ERR_VLAN_PRIORITY          - Invalid 1p priority
+ *      RT_ERR_QOS_INT_PRIORITY     - Invalid internal priority 
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+rtk_api_ret_t rtk_qos_1pRemark_set(rtk_pri_t int_pri, rtk_pri_t dot1p_pri)
+{
+    rtk_api_ret_t retVal;
+
+    if (int_pri > RTL8306_PRIO3 )
+        return RT_ERR_QOS_INT_PRIORITY; 
+
+    if (dot1p_pri > RTL8306_1QTAG_PRIO7)
+        return RT_ERR_VLAN_PRIORITY; 
+
+    if((retVal = rtl8306e_qos_1pRemark_set(int_pri, dot1p_pri)) != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_qos_1pRemark_get
+ * Description:
+ *      Get 802.1P remarking priority
+ * Input:
+ *      int_pri        -  Packet priority(0~4)
+ * Output:
+ *      pDot1p_pri  -  the pointer of 802.1P priority(0~7)
+ * Return:
+ *      RT_ERR_OK                           -  Success
+ *      RT_ERR_FAILED                      -  Failure
+ *      RT_ERR_NULL_POINTER            -  Input parameter is null pointer
+ *      RT_ERR_QOS_INT_PRIORITY     -  Invalid internal priority 
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+rtk_api_ret_t rtk_qos_1pRemark_get(rtk_pri_t int_pri, rtk_pri_t *pDot1p_pri)
+{
+    rtk_api_ret_t retVal;
+    
+    if (int_pri > RTL8306_PRIO3)
+        return RT_ERR_QOS_INT_PRIORITY; 
+    if(NULL == pDot1p_pri)
+        return RT_ERR_NULL_POINTER;
+    
+    if((retVal = rtl8306e_qos_1pRemark_get(int_pri, pDot1p_pri)) != SUCCESS)
+        return RT_ERR_FAILED;
+    
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_trap_unknownMcastPktAction_set
+ * Description:
+ *      Set behavior of unknown multicast
+ * Input:
+ *      port                -   port id
+ *      type               -   unknown multicast packet type
+ *      mcast_action    -  unknown multicast action
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id    
+ *      RT_ERR_INPUT                 -  Invalid input parameter 
+ * Note:
+ *      When receives an unknown multicast packet, switch may trap, drop this packet
+ *      The unknown multicast packet type is as following:
+ *               - MCAST_IPV4
+ *               - MCAST_IPV6
+ *      The unknown multicast action is as following:
+ *               - MCAST_ACTION_FORWARD
+ *               - MCAST_ACTION_DROP
+ */
+rtk_api_ret_t rtk_trap_unknownMcastPktAction_set(rtk_port_t port, rtk_mcast_type_t type, rtk_trap_mcast_action_t mcast_action)
+{
+    rtk_api_ret_t retVal;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if(mcast_action > MCAST_ACTION_DROP)
+        return RT_ERR_INPUT;
+    
+    if((MCAST_L2 == type) || (type > MCAST_IPV6 ))
+        return RT_ERR_INPUT;
+
+    if(MCAST_IPV4 == type)
+    {
+        retVal = rtl8306e_trap_unknownIPMcastPktAction_set(RTL8306_IPV4_MULTICAST, 
+                   (MCAST_ACTION_FORWARD == mcast_action) ? RTL8306_ACT_PERMIT: RTL8306_ACT_DROP);
+        if(retVal != SUCCESS)
+            return RT_ERR_FAILED;
+    }
+    else if(MCAST_IPV6 == type)
+    {
+        retVal = rtl8306e_trap_unknownIPMcastPktAction_set(RTL8306_IPV6_MULTICAST, 
+                   (MCAST_ACTION_FORWARD == mcast_action) ? RTL8306_ACT_PERMIT: RTL8306_ACT_DROP);
+        if(retVal != SUCCESS)
+            return RT_ERR_FAILED;        
+    }
+           
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_trap_unknownMcastPktAction_get
+ * Description:
+ *      Get behavior of unknown multicast
+ * Input:
+ *      port                  -   port id
+ *      type                 -   unknown multicast packet type
+ * Output:
+ *      pMcast_action    -   the pointer of unknown multicast action
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id    
+ *      RT_ERR_NULL_POINTER      -  Input parameter is null pointer
+ * Note:
+ *      When receives an unknown multicast packet, switch may trap, drop this packet.
+ *      The unknown multicast packet type is as following:
+ *               - MCAST_IPV4
+ *               - MCAST_IPV6
+ *      The unknown multicast action is as following:
+ *               - MCAST_ACTION_FORWARD
+ *               - MCAST_ACTION_DROP
+ */
+rtk_api_ret_t rtk_trap_unknownMcastPktAction_get(rtk_port_t port, rtk_mcast_type_t type, rtk_trap_mcast_action_t *pMcast_action)
+{
+    rtk_api_ret_t retVal;
+    uint32 action;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if((MCAST_L2 == type) || (type > MCAST_IPV6 ))
+        return RT_ERR_INPUT;
+    
+    if(NULL == pMcast_action)
+        return RT_ERR_NULL_POINTER;
+
+    if(MCAST_IPV4 == type)
+    {
+        retVal = rtl8306e_trap_unknownIPMcastPktAction_get(RTL8306_IPV4_MULTICAST, &action);
+        if(retVal != SUCCESS)
+            return RT_ERR_FAILED;
+        *pMcast_action = (action == RTL8306_ACT_PERMIT) ? MCAST_ACTION_FORWARD: MCAST_ACTION_DROP;                        
+    }
+    else if(MCAST_IPV6 == type)
+    {
+        retVal = rtl8306e_trap_unknownIPMcastPktAction_get(RTL8306_IPV6_MULTICAST, &action);
+        if(retVal != SUCCESS)
+            return RT_ERR_FAILED;
+        *pMcast_action = (action == RTL8306_ACT_PERMIT) ? MCAST_ACTION_FORWARD: MCAST_ACTION_DROP;                        
+    }
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_trap_igmpCtrlPktAction_set
+ * Description:
+ *      Set IGMP/MLD trap function
+ * Input:
+ *      type                -   IGMP/MLD packet type
+ *      igmp_action      -   IGMP/MLD action
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_INPUT                 -  Invalid input parameter
+ *      RT_ERR_NOT_ALLOWED     -  Actions not allowed by the function
+ * Note:
+ *      This API can set both IPv4 IGMP/IPv6 MLD with/without PPPoE header trapping function.
+ *      All 4 kinds of IGMP/MLD function can be set separately.
+ *      The IGMP/MLD packet type is as following:
+ *          - IGMP_IPV4
+ *          - IGMP_MLD
+ *          - IGMP_PPPOE_IPV4
+ *          - IGMP_PPPOE_MLD
+ *      The IGMP/MLD action is as following:
+ *          - IGMP_ACTION_FORWARD
+ *          - IGMP_ACTION_TRAP2CPU
+ */ 
+rtk_api_ret_t rtk_trap_igmpCtrlPktAction_set(rtk_igmp_type_t type, rtk_trap_igmp_action_t igmp_action)
+{
+    rtk_api_ret_t retVal;
+    uint32 igmp_type, action;
+
+    if(type > IGMP_PPPOE_MLD)
+        return RT_ERR_INPUT;
+    if(igmp_action > IGMP_ACTION_TRAP2CPU)
+        return RT_ERR_NOT_ALLOWED;
+    
+    igmp_type = RTL8306_IGMP;
+    if(IGMP_IPV4 == type)
+    {
+        igmp_type = RTL8306_IGMP;
+    }
+    else if(IGMP_MLD == type)
+    {
+        igmp_type = RTL8306_MLD;
+    }
+    else if((IGMP_PPPOE_IPV4 == type) || (IGMP_PPPOE_MLD == type))
+    {
+        igmp_type = RTL8306_PPPOE_IGMPMLD;
+    }
+    action = (igmp_action == IGMP_ACTION_FORWARD) ? RTL8306_ACT_PERMIT: RTL8306_ACT_TRAPCPU;        
+    retVal = rtl8306e_trap_igmpCtrlPktAction_set(igmp_type, action);    
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_trap_igmpCtrlPktAction_get
+ * Description:
+ *      Get IGMP/MLD trap function
+ * Input:
+ *      type                -   IGMP/MLD packet type
+ * Output:
+ *      pIgmp_action    -   the pointer of IGMP/MLD action
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_INPUT                 -  Invalid input parameter
+ *      RT_ERR_NULL_POINTER      -  Input parameter is null pointer
+ * Note:
+ *      This API can get both IPv4 IGMP/IPv6 MLD with/without PPPoE header trapping function.
+ *      All 4 kinds of IGMP/MLD function can be set seperately.
+ *      The IGMP/MLD packet type is as following:
+ *          - IGMP_IPV4
+ *          - IGMP_MLD
+ *          - IGMP_PPPOE_IPV4
+ *          - IGMP_PPPOE_MLD
+ *      The IGMP/MLD action is as following:
+ *          - IGMP_ACTION_FORWARD
+ *          - IGMP_ACTION_TRAP2CPU
+ */
+rtk_api_ret_t rtk_trap_igmpCtrlPktAction_get(rtk_igmp_type_t type, rtk_trap_igmp_action_t *pIgmp_action)
+{
+    rtk_api_ret_t retVal;
+    uint32 igmp_type, action;
+
+    if(type > IGMP_PPPOE_MLD)
+        return RT_ERR_INPUT;
+    
+    if(NULL == pIgmp_action)
+        return RT_ERR_NULL_POINTER;
+    
+    igmp_type = RTL8306_IGMP;
+    if(IGMP_IPV4 == type)
+    {
+        igmp_type = RTL8306_IGMP;    
+    }
+    else if(IGMP_MLD == type)
+    {
+        igmp_type = RTL8306_MLD;
+    }
+    else if((IGMP_PPPOE_IPV4 == type) || (IGMP_PPPOE_MLD == type))
+    {
+        igmp_type = RTL8306_PPPOE_IGMPMLD;
+    }
+    retVal = rtl8306e_trap_igmpCtrlPktAction_get(igmp_type, &action);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    *pIgmp_action = (action == RTL8306_ACT_PERMIT) ? IGMP_ACTION_FORWARD: IGMP_ACTION_TRAP2CPU;
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_vlan_init
+ * Description:
+ *      Initialize VLAN
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED                -  Failure
+ * Note:
+ *      VLAN is disabled by default. User has to call this API to enable VLAN before
+ *      using it. And It will set a default VLAN(vid 1) including all ports and set 
+ *      all ports PVID to the default VLAN.
+ */
+
+rtk_api_ret_t rtk_vlan_init(void)
+{
+    uint32 i;
+    uint32 port;
+
+
+    /*clear vlan table*/
+    for(i = 0; i < 16; i++)
+        rtl8306e_vlan_entry_set(i, 0, 0, 0);
+
+    /*set switch default configuration:
+      *enable tag aware, disable ingress filter,
+      *admit all packet*/
+    rtl8306e_vlan_tagAware_set(TRUE);     
+    rtl8306e_vlan_IgrFilterEnable_set(FALSE);  
+    for (port = 0; port < 6; port++)
+    {
+        rtl8306e_vlan_portAcceptFrameType_set(port, RTL8306E_ACCEPT_ALL);
+    }
+
+    /*add a default vlan 1 which contains all ports*/
+    rtl8306e_vlan_entry_set(0, 1, 0x3F, 0);
+    
+    /*set all ports' vid to vlan 1*/
+    for(port = 0; port < 6; port++)
+        rtl8306e_vlan_portPvidIndex_set(port, 0);
+
+    /*set vlan enabled*/
+    rtl8306e_regbit_set(0, 18, 8, 0, 0);
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanConfig.enVlan = TRUE; 
+#endif
+    /*disable trunk*/
+    rtl8306e_regbit_set(0, 19, 11, 0, 1);
+    
+    return RT_ERR_OK;
+   
+}
+
+/* Function Name:
+ *      rtk_vlan_set
+ * Description:
+ *      Set a VLAN entry
+ * Input:
+ *      vid              - VLAN ID to configure, should be 1~4094
+ *      mbrmsk        - VLAN member set portmask
+ *      untagmsk     - VLAN untag set portmask
+ *      fid              -  filtering database id, could be any value for RTL8306E
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_VLAN_VID            -  Invalid vid
+ *      RT_ERR_INPUT                 -  Invalid input parameter 
+ *      RT_ERR_TBL_FULL            -  Input table full 
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ *     FID is for SVL/IVL usage, and the range is 0~4095, rtl8306E only supports SVL, 
+ *     so fid is no useage.
+ */
+rtk_api_ret_t rtk_vlan_set(rtk_vlan_t vid, rtk_portmask_t mbrmsk, rtk_portmask_t untagmsk, rtk_fid_t fid)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 index, hit_index, hit_flag;
+    uint32 fullflag;
+    int32 i;
+
+    /* vid must be 1~4094 */
+    if ((vid == 0) || (vid > (RTL8306_VIDMAX - 1)))
+        return RT_ERR_VLAN_VID;
+
+    if (mbrmsk.bits[0] > RTL8306_MAX_PORTMASK)
+        return RT_ERR_INPUT;
+
+    if (untagmsk.bits[0] > RTL8306_MAX_PORTMASK)
+        return RT_ERR_INPUT;
+
+
+    /*check if vid exists and check if vlan is full*/
+    fullflag = TRUE;
+    hit_flag = FALSE;
+    index = 16;
+    hit_index= 16;
+    for(i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if (0 == vid_val) 
+        {
+            index = (uint32)i; 
+            fullflag = FALSE;
+            continue;
+        }
+        
+        if (vid_val == vid)
+        {
+            hit_flag = TRUE;
+            hit_index = (uint32)i;
+            fullflag = FALSE;
+            break;
+        }            
+    }        
+    
+    if (fullflag)       
+        return RT_ERR_TBL_FULL;
+    else 
+    {
+        vid_val           = (uint32)vid;
+        mbrmsk_val     = mbrmsk.bits[0];
+        untagmsk_val  = untagmsk.bits[0];
+
+        /*both mbrmsk_val and untagmsk_val are zero will clear the vlan*/
+        if( (0 == mbrmsk_val) && (0 == untagmsk_val))
+            vid_val = 0;
+            
+        if (hit_flag)
+            rtl8306e_vlan_entry_set(hit_index, vid_val, mbrmsk_val, untagmsk_val);            
+        else
+            rtl8306e_vlan_entry_set(index, vid_val, mbrmsk_val, untagmsk_val);            
+    }
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_vlan_get
+ * Description:
+ *      Get a VLAN entry
+ * Input:
+ *      vid             - VLAN ID to configure
+ * Output:
+ *      pMbrmsk     - VLAN member set portmask
+ *      pUntagmsk  - VLAN untag set portmask
+ *      pFid           -  filtering database id
+ * Return:
+ *      RT_ERR_OK                                   -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_VLAN_VID                          -  Invalid vid
+ *      RT_ERR_NULL_POINTER                    -  Input parameter is null pointer
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND    -   Specified vlan entry not found
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ *     FID is for SVL/IVL usage, and the range is 0~4095, rtl8306E only supports SVL, 
+ *     so fid is no useage.
+ */
+ 
+rtk_api_ret_t rtk_vlan_get(rtk_vlan_t vid, rtk_portmask_t *pMbrmsk, rtk_portmask_t *pUntagmsk, rtk_fid_t *pFid)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    int32 i;
+
+    /* vid must be 1~4094 */
+    if ((vid == 0) || (vid > (RTL8306_VIDMAX - 1)))
+        return RT_ERR_VLAN_VID;
+
+    if ((NULL == pMbrmsk) || (NULL == pUntagmsk))
+        return RT_ERR_NULL_POINTER;
+
+    /*seach the vlan table*/
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((rtk_vlan_t)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == vid)
+        {
+            hit_flag = TRUE;
+            pMbrmsk->bits[0]    = mbrmsk_val;
+            pUntagmsk->bits[0] = untagmsk_val;         
+            *pFid = 0;
+            return RT_ERR_OK;
+        }
+    }
+
+    if(!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;
+        
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_vlan_destroy
+ * Description:
+ *      delete vid from vlan table
+ * Input:
+ *      vid             - VLAN ID to configure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                   -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_VLAN_VID                          -  Invalid vid
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND    -  Specified vlan entry not found
+ * Note:
+ * 
+ */
+rtk_api_ret_t rtk_vlan_destroy(rtk_vlan_t vid)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    int32 i;
+    
+    /* vid must be 1~4094 */
+    if ((vid == 0) || (vid > (RTL8306_VIDMAX - 1)))
+        return RT_ERR_VLAN_VID;
+
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == vid)
+        {
+            hit_flag = TRUE;
+            vid_val = 0;
+            mbrmsk_val = 0;
+            untagmsk_val = 0;
+            rtl8306e_vlan_entry_set((uint32)i, vid_val, mbrmsk_val, untagmsk_val);
+            return RT_ERR_OK;
+        }        
+    }
+
+    if(!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;    
+    else
+        return RT_ERR_OK;        
+
+}
+    
+
+/* Function Name:
+ *      rtk_vlan_portPvid_set
+ * Description:
+ *      Set port to specified VLAN ID(PVID)
+ * Input:
+ *      port             - Port id
+ *      pvid             - Specified VLAN ID
+ *      priority         - 802.1p priority for the PVID, 0~3 for RTL8306E 
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                   -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_VLAN_VID                          -  Invalid vid
+ *      RT_ERR_VLAN_PRIORITY                  -  Invalid 1p priority 
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND    -  Specified vlan entry not found
+ * Note:
+ *      The API is used for Port-based VLAN. The untagged frame received from the
+ *      port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+rtk_api_ret_t rtk_vlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    uint32 regVal;
+    int32 i;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if ((pvid == 0) || (pvid > (RTL8306_VIDMAX - 1)))
+        return RT_ERR_VLAN_VID;
+
+    if (priority > RTL8306_PRIO3)
+        return RT_ERR_VLAN_PRIORITY;
+
+    /*seach the vlan table*/
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == pvid)
+        {
+            hit_flag = TRUE;
+            rtl8306e_vlan_portPvidIndex_set(port, (uint32)i);
+            
+            /*802.1Q default priority for untag pkt*/
+            if (RTL8306_PORT5 == port)  
+                port ++ ;  
+            rtl8306e_reg_get(port, 17, 2, &regVal);
+            regVal = (regVal & 0x9FFF) | (priority << 13);
+            rtl8306e_reg_set(port, 17, 2, regVal);            
+            return RT_ERR_OK;
+        }
+    }
+
+    if (!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_vlan_portPvid_get
+ * Description:
+ *      Get VLAN ID(PVID) on specified port
+ * Input:
+ *      port             - Port id
+ * Output:
+ *      pPvid            - Specified VLAN ID
+ *      pPriority        - 802.1p priority for the PVID
+ * Return:
+ *      RT_ERR_OK                                   - Success
+ *      RT_ERR_FAILED                             -  Failure
+ *      RT_ERR_PORT_ID                           -  Invalid port id
+ *      RT_ERR_NULL_POINTER                   -  Input parameter is null pointer
+ * Note:
+ *    The API is used for Port-based VLAN. The untagged frame received from the
+ *    port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+
+rtk_api_ret_t rtk_vlan_portPvid_get(rtk_port_t port, rtk_vlan_t *pPvid, rtk_pri_t *pPriority)
+{
+    rtk_api_ret_t retVal;    
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 index;
+    uint32 regVal;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if((NULL == pPvid) || (NULL == pPriority))
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_vlan_portPvidIndex_get(port, &index);
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    retVal = rtl8306e_vlan_entry_get(index, &vid_val, &mbrmsk_val, &untagmsk_val);    
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    *pPvid = vid_val;
+
+    /*get 802.1Q default priority for untag pkt*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    rtl8306e_reg_get(port, 17, 2, &regVal);
+    *pPriority = (regVal & 0x6000) >> 13;    
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_vlan_portIgrFilterEnable_set
+ * Description:
+ *      Set VLAN ingress for each port
+ * Input:
+ *      port             - Port id
+ *      igr_filter        - VLAN ingress function enable status
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        - Success
+ *      RT_ERR_FAILED                  -  Failure
+ * Note:
+ *      RTL8306E use one ingress filter for whole system, not for each port, so 
+ *      any port you set will affect all ports ingress filter setting.
+ *      While VLAN function is enabled, ASIC will decide VLAN ID for each received frame 
+ *      and get belonged member ports from VLAN table. If received port is not belonged 
+ *      to VLAN member ports, ASIC will drop received frame if VLAN ingress function is enabled.
+ */
+rtk_api_ret_t rtk_vlan_portIgrFilterEnable_set(rtk_port_t port, rtk_enable_t igr_filter)
+{
+    rtk_api_ret_t retVal;    
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    retVal = rtl8306e_vlan_IgrFilterEnable_set(igr_filter);
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+            
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_vlan_portIgrFilterEnable_get
+ * Description:
+ *      get VLAN ingress for each port
+ * Input:
+ *      port             - Port id
+ * Output:
+ *      pIgr_filter     - the pointer of VLAN ingress function enable status
+ * Return:
+ *      RT_ERR_OK                 - Success
+ *      RT_ERR_FAILED           -  Failure
+ * Note:
+ *      RTL8306E use one ingress filter for whole system, not for each port, so 
+ *      any port you set will affect all ports ingress filter setting.
+ *      While VLAN function is enabled, ASIC will decide VLAN ID for each received frame 
+ *      and get belonged member ports from VLAN table. If received port is not belonged 
+ *      to VLAN member ports, ASIC will drop received frame if VLAN ingress function is enabled.
+ */
+rtk_api_ret_t rtk_vlan_portIgrFilterEnable_get(rtk_port_t port, rtk_enable_t *pIgr_filter)
+{
+    rtk_api_ret_t retVal;    
+    uint32 enabled;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    
+    if (NULL == pIgr_filter)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_vlan_IgrFilterEnable_get(&enabled);
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    *pIgr_filter = enabled ? ENABLED : DISABLED;
+        
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_vlan_portAcceptFrameType_set
+ * Description:
+ *      Set VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ *      accept_frame_type             - accept frame type
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                  - Success
+ *      RT_ERR_FAILED            -  Failure
+ *      RT_ERR_PORT_ID          -  Invalid port id
+ * Note:
+ *      The API is used for checking 802.1Q tagged frames.
+ *      The accept frame type as following:
+ *          - ACCEPT_FRAME_TYPE_ALL
+ *          - ACCEPT_FRAME_TYPE_TAG_ONLY
+ *          - ACCEPT_FRAME_TYPE_UNTAG_ONLY
+ */
+rtk_api_ret_t rtk_vlan_portAcceptFrameType_set(rtk_port_t port, rtk_vlan_acceptFrameType_t accept_frame_type)
+{
+    rtk_api_ret_t retVal;
+    rtl8306e_acceptFrameType_t accfrm_type;    
+
+    if ( port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+
+    switch (accept_frame_type)
+    {
+        case ACCEPT_FRAME_TYPE_ALL:
+            accfrm_type = RTL8306E_ACCEPT_ALL;
+            break;
+        case ACCEPT_FRAME_TYPE_TAG_ONLY:
+            accfrm_type = RTL8306E_ACCEPT_TAG_ONLY;
+            break;
+        case ACCEPT_FRAME_TYPE_UNTAG_ONLY:
+            accfrm_type = RTL8306E_ACCEPT_UNTAG_ONLY;
+            break;
+        default:
+            return RT_ERR_VLAN_ACCEPT_FRAME_TYPE;
+    }
+
+    retVal = rtl8306e_vlan_portAcceptFrameType_set(port, accfrm_type);
+    
+    return retVal;
+}
+
+/* Function Name:
+ *      rtk_vlan_portAcceptFrameType_get
+ * Description:
+ *      Get VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ *      accept_frame_type             - accept frame type
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                   - Success
+ *      RT_ERR_FAILED                             -  Failure
+ *      RT_ERR_PORT_ID                           -  Invalid port id
+ *      RT_ERR_VLAN_ACCEPT_FRAME_TYPE -  Invalid accept frame type 
+ * Note:
+ *    The API is used for checking 802.1Q tagged frames.
+ *    The accept frame type as following:
+ *    - ACCEPT_FRAME_TYPE_ALL
+ *    - ACCEPT_FRAME_TYPE_TAG_ONLY
+ *    - ACCEPT_FRAME_TYPE_UNTAG_ONLY
+ */
+ 
+rtk_api_ret_t rtk_vlan_portAcceptFrameType_get(rtk_port_t port, rtk_vlan_acceptFrameType_t *pAccept_frame_type)
+{
+    rtk_api_ret_t retVal;
+    rtl8306e_acceptFrameType_t accfrm_type;    
+
+    if ( port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+
+    if (NULL == pAccept_frame_type)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_vlan_portAcceptFrameType_get(port, &accfrm_type);
+    switch(accfrm_type)
+    {
+        case RTL8306E_ACCEPT_ALL:
+            *pAccept_frame_type = ACCEPT_FRAME_TYPE_ALL;
+            break;
+        case RTL8306E_ACCEPT_TAG_ONLY:
+            *pAccept_frame_type = ACCEPT_FRAME_TYPE_TAG_ONLY;
+            break;
+        case RTL8306E_ACCEPT_UNTAG_ONLY:
+            *pAccept_frame_type = ACCEPT_FRAME_TYPE_UNTAG_ONLY;
+            break;
+        default:
+            return RT_ERR_VLAN_ACCEPT_FRAME_TYPE;
+    }
+
+    return retVal;
+}    
+
+
+/* Function Name:
+ *      rtk_vlan_vlanBasedPriority_set
+ * Description:
+ *      Set VLAN priority for each CVLAN
+ * Input:
+ *      vid                -Specified VLAN ID
+ *      priority           -priority for the VID
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_VLAN_PRIORITY               -  Invalid 1p priority
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -  Specified vlan entry not found
+ * Note:
+ *      This API is used to set priority per VLAN.
+ */
+
+rtk_api_ret_t rtk_vlan_vlanBasedPriority_set(rtk_vlan_t vid, rtk_pri_t priority)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    int32 i;
+
+    /* vid must be 1~4094 */
+    if ((vid == 0) || (vid > (RTL8306_VIDMAX - 1)))
+        return RT_ERR_VLAN_VID;
+
+    if (priority > RTL8306_PRIO3)
+        return RT_ERR_VLAN_PRIORITY;    
+
+    /*seach the vlan table*/
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == vid)
+        {
+            hit_flag = TRUE;
+            rtl8306e_vlan_vlanBasedPriority_set((uint32)i, priority);            
+            return RT_ERR_OK;
+        }
+    }
+
+    if (!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;
+        
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_vlan_vlanBasedPriority_get
+ * Description:
+ *      Get VLAN priority for each CVLAN
+ * Input:
+ *      vid                -Specified VLAN ID
+ * Output:
+ *      pPriority         -the pointer of priority for the VID
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_NULL_POINTER                -   Input parameter is null pointer
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -   Specified vlan entry not found 
+ * Note:
+ *      This API is used to set priority per VLAN.
+ */
+
+rtk_api_ret_t rtk_vlan_vlanBasedPriority_get(rtk_vlan_t vid, rtk_pri_t *pPriority)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    int32 i;
+
+    /* vid must be 1~4094 */
+    if ((vid == 0) || (vid > (RTL8306_VIDMAX - 1)))
+        return RT_ERR_VLAN_VID;
+
+    if (NULL == pPriority)
+        return RT_ERR_NULL_POINTER;
+
+    /*seach the vlan table*/
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == vid)
+        {
+            hit_flag = TRUE;
+            rtl8306e_vlan_vlanBasedPriority_get((uint32)i, pPriority);            
+            return RT_ERR_OK;
+        }
+    }
+
+    if (!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_vlan_vidTranslation_set
+ * Description:
+ *      Set vid translated to new vid
+ * Input:
+ *      vid       -  old vid
+ *      nvid     -   new vid
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -   Specified vlan entry not found 
+ * Note:
+ *      This API is used to translate a vid to a new vid, the new vid could be 
+ *      used by Q-in-Q or vlan translation function.
+ */
+rtk_api_ret_t rtk_vlan_vidTranslation_set(rtk_vlan_t vid, rtk_vlan_t nvid)
+{
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    int32 i;
+    
+    if ((vid > RTL8306_VIDMAX ) || (nvid > RTL8306_VIDMAX ))
+        return RT_ERR_VLAN_VID;
+
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == vid)
+        {
+            hit_flag = TRUE;
+            rtl8306e_vlan_transVid_set((uint32)i, nvid);
+            return RT_ERR_OK;
+        }        
+    }
+
+    if(!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;            
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_vlan_vidTranslation_get
+ * Description:
+ *      Get vid translation new vid
+ * Input:
+ *      vid        -  old vid
+ * Output:
+ *      pNvid     -  the pointer of new vid
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_NULL_POINTER                -   NULL pointer
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -   Specified vlan entry not found 
+ * Note:
+ *      This API is used to translate a vid to a new vid, the new vid could be 
+ *      used by Q-in-Q or vlan translation function.
+ */
+rtk_api_ret_t rtk_vlan_vidTranslation_get(rtk_vlan_t vid, rtk_vlan_t *pNvid)
+{
+
+    uint32 vid_val, mbrmsk_val, untagmsk_val;
+    uint32 hit_flag;
+    int32 i;
+
+    if (vid > RTL8306_VIDMAX )
+        return RT_ERR_VLAN_VID;
+    
+    if (NULL == pNvid)
+        return RT_ERR_NULL_POINTER;
+
+    hit_flag = FALSE;
+    for (i = 15; i >= 0; i--)
+    {
+        rtl8306e_vlan_entry_get((uint32)i, &vid_val, &mbrmsk_val, &untagmsk_val);
+        if(vid_val == vid)
+        {
+            hit_flag = TRUE;
+            rtl8306e_vlan_transVid_get((uint32)i, pNvid);
+            return RT_ERR_OK;
+        }        
+    }
+
+    if(!hit_flag)
+        return RT_ERR_VLAN_ENTRY_NOT_FOUND;            
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_vlan_vidTranslationEnable_set
+ * Description:
+ *      Set vlan translation function enabled or disabled 
+ * Input:
+ *      enable        -  enable or disable
+ *      nniMask      -   NNI port mask
+ * Output:
+ *      pNvid     -  the pointer of new vid
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_PORT_MASK                   -   Error port mask
+ * Note:
+ *      VLAN translation only happens between UNI and NNI port, 
+ *      in nniMask, 1 means the port is NNI port, 0 means the port
+ *      is UNI port
+ */
+rtk_api_ret_t rtk_vlan_vidTranslationEnable_set(rtk_enable_t enable, rtk_portmask_t nniMask)
+{
+    rtk_api_ret_t retVal;
+    uint32 port;
+    
+    if (nniMask.bits[0] > RTL8306_MAX_PORTMASK)
+        return RT_ERR_PORT_MASK; 
+
+    /*set default vid and priority src*/
+    if(enable)
+    {
+        for (port = 0; port < 6; port ++)
+            rtl8306e_svlan_otagSrc_set(port, RTL8306E_VIDSRC_NVID, RTL8306E_PRISRC_1PRMK);
+    }
+
+    retVal = rtl8306e_vlan_transEnable_set((uint32) enable, nniMask.bits[0]);
+    
+    return retVal;
+
+}
+
+
+/* Function Name:
+ *      rtk_vlan_vidTranslationEnable_get
+ * Description:
+ *      Get vlan translation function enabled or disabled 
+ * Input:
+ *      none
+ * Output:
+ *      pEnable      -   the pointer of enable or disable
+ *      pNniMask    -   the pointer of NNI port mask
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_NULL_POINTER                -   NULL pointer
+ * Note:
+ *      VLAN translation only happens between UNI and NNI port, 
+ *      in nniMask, 1 means the port is NNI port, 0 means the port
+ *      is UNI port
+ */
+
+rtk_api_ret_t rtk_vlan_vidTranslationEnable_get(rtk_enable_t *pEnable, rtk_portmask_t *pNniMask)
+{
+    rtk_api_ret_t retVal;
+    uint32 enable, portmask;
+    
+    if((NULL == pEnable) || (NULL == pNniMask))
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_vlan_transEnable_get(&enable, &portmask);
+    *pEnable = enable ? ENABLED : DISABLED;
+    pNniMask->bits[0] = portmask;
+
+    return retVal;
+
+}
+
+/* Function Name:
+ *      rtk_vlan_tagSrc_set
+ * Description:
+ *      Set tag vid and priority source for Q-in-Q and VLAN translation
+ * Input:
+ *      port          -    port id
+ *      vidSrc       -    vid source
+ *      priSrc        -    priority source
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                 -  Success
+ *      RT_ERR_FAILED            -   Failure
+ *      RT_ERR_PORT_ID          -   error port id
+ * Note:
+ *      Q-in-Q(SVLAN) and VLAN translation will modify tag, 
+ *      the API could set outer tag or translated VLAN tag
+ *      vid/priority source.
+ *      - vidSrc: 
+ *                - RTL8306E_VIDSRC_POVID - port-based otag vid,     
+ *                - RTL8306E_VIDSRC_NVID   - new vid(translated vid)
+ *       - priSrc:
+ *                - RTL8306E_PRISRC_PPRI    - port-based otag priority, 
+ *                - RTL8306E_PRISRC_1PRMK - 1p remarking priority
+ */
+rtk_api_ret_t rtk_vlan_tagSrc_set(rtk_port_t port, rtk_vidSrc_t vidSrc, rtk_priSrc_t priSrc)    
+{
+    rtk_api_ret_t retVal;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    retVal = rtl8306e_svlan_otagSrc_set(port, vidSrc, priSrc);
+    
+    return retVal;
+}
+
+
+/* Function Name:
+ *      rtk_vlan_tagSrc_get
+ * Description:
+ *      Get tag vid and priority source for Q-in-Q and VLAN translation
+ * Input:
+ *      port          -    port id
+ * Output:
+ *      pVidSrc     -    the pointer of vid source
+ *      pPriSrc      -    the pointer of priority source
+ * Return:
+ *      RT_ERR_OK                 -  Success
+ *      RT_ERR_FAILED            -   Failure
+ *      RT_ERR_PORT_ID          -   error port id
+ * Note:
+ *      Q-in-Q(SVLAN) and VLAN translation will modify tag, 
+ *      the API could set outer tag or tranlated VLAN tag
+ *      vid/priority source.
+ *      vidSrc: 
+ *                RTL8306E_VIDSRC_POVID - port-based otag vid,     
+ *                RTL8306E_VIDSRC_NVID   - new vid(translated vid)
+ *       priSrc:
+ *                RTL8306E_PRISRC_PPRI    - port-based otag priority, 
+ *                RTL8306E_PRISRC_1PRMK - 1p remarking priority
+ */
+rtk_api_ret_t rtk_vlan_tagSrc_get(rtk_port_t port, rtk_vidSrc_t *pVidSrc, rtk_priSrc_t *pPriSrc)    
+{
+    rtk_api_ret_t retVal;
+    uint32 vidsrc, prisrc;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    if((NULL == pVidSrc) || (NULL == pPriSrc))
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_svlan_otagSrc_get(port, &vidsrc, &prisrc);
+    *pVidSrc = (rtk_vidSrc_t)vidsrc;
+    *pPriSrc  = (rtk_priSrc_t)prisrc;
+    
+    return retVal;
+}
+
+
+/* Function Name:
+ *      rtk_stp_mstpState_set
+ * Description:
+ *      Configure spanning tree state per port
+ * Input:
+ *      msti              - Multiple spanning tree instance, no use for RTL8306E
+ *      port              - Port id
+ *      stp_state       - Spanning tree state
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id
+ *      RT_ERR_MSTP_STATE        -  Invalid spanning tree status
+ * Note:
+ *      Because RTL8306E does not support multiple spanning tree, so msti is no use. 
+ *      There are four states supported by ASIC.
+ *          - STP_STATE_DISABLED
+ *          - STP_STATE_BLOCKING
+ *          - STP_STATE_LEARNING
+ *          - STP_STATE_FORWARDING
+ */
+rtk_api_ret_t rtk_stp_mstpState_set(rtk_stp_msti_id_t msti, rtk_port_t port, rtk_stp_state_t stp_state)
+{
+    rtk_api_ret_t retVal;
+    
+    if(port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+    
+    if(stp_state >= STP_STATE_END)
+        return RT_ERR_MSTP_STATE;
+
+    retVal = rtl8306e_stp_set(port, stp_state);
+    return retVal;
+
+}    
+
+/* Function Name:
+ *      rtk_stp_mstpState_get
+ * Description:
+ *      Get Configuration of spanning tree state per port
+ * Input:
+ *      msti              - Multiple spanning tree instance, no use for RTL8306E
+ *      port              - Port id
+ * Output:
+ *      pStp_state     - the pointer of Spanning tree state
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id
+ *      RT_ERR_NULL_POINTER      -  Input parameter is null pointer
+ * Note:
+ *      Because RTL8306E does not support multiple spanning tree, so msti is no use. 
+ *      There are four states supported by ASIC.
+ *          - STP_STATE_DISABLED
+ *          - STP_STATE_BLOCKING
+ *          - STP_STATE_LEARNING
+ *          - STP_STATE_FORWARDING
+ */
+rtk_api_ret_t rtk_stp_mstpState_get(rtk_stp_msti_id_t msti, rtk_port_t port, rtk_stp_state_t *pStp_state)
+{
+    rtk_api_ret_t retVal;
+    uint32 state;
+    
+    if(port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+    
+    if(NULL == pStp_state)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_stp_get(port, &state);
+    *pStp_state = (rtk_stp_state_t)state;
+
+    return retVal;
+}    
+
+/* Function Name:
+ *      rtk_l2_addr_add
+ * Description:
+ *      Set LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast(I/G bit is 0) mac address to be written into LUT
+ *      pL2_data          -   the mac address attributes
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                       -  Success
+ *      RT_ERR_FAILED                 -   Failure
+ *      RT_ERR_INPUT                  -   Invalid input parameter
+ *      RT_ERR_MAC                    -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_NULL_POINTER       -  Input parameter is null pointer    
+ *      RT_ERR_L2_INDEXTBL_FULL -  The L2 index table is full
+ * Note:
+ *      If the unicast mac address already existed in LUT, it will udpate the status of the entry. 
+ *      Otherwise, it will find an empty or asic auto learned entry to write. If all the entries 
+ *      with the same hash value can't be replaced, ASIC will return a RT_ERR_L2_INDEXTBL_FULL error.
+ *      for RTL8306E, pL2_data member fid and sa_block is no use, so it can be chosen any value.
+ */
+ 
+rtk_api_ret_t rtk_l2_addr_add(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_data)
+{
+    rtk_api_ret_t retVal;
+    uint32 entryAddr;
+        
+    /* must be unicast address */
+    if((NULL == pMac) || (pMac->octet[0] & 0x1))
+        return RT_ERR_MAC;
+    
+    if(NULL == pL2_data)
+        return RT_ERR_NULL_POINTER;
+
+    if(pL2_data->port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;    
+
+    if(pL2_data->is_static >= RTK_ENABLE_END)
+        return RT_ERR_INPUT; 
+
+    if(pL2_data->auth >= RTK_ENABLE_END)
+        return RT_ERR_INPUT; 
+        
+    retVal = rtl8306e_l2_unicastMac_add(pMac->octet, RTL8306_LUT_AGE300, pL2_data->is_static, pL2_data->auth, pL2_data->port, &entryAddr);
+    if(RTL8306_LUT_FULL == retVal)
+        return RT_ERR_L2_INDEXTBL_FULL;
+    else if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_l2_addr_get
+ * Description:
+ *      Get LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast(I/G bit is 0) mac address to be gotten
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+ *      pL2_data          -   the mac address attributes
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_NULL_POINTER              -   Input parameter is null pointer    
+ *      RT_ERR_L2_ENTRY_NOTFOUND    -   Specified entry not found
+ * Note:
+ *      If the unicast mac address existed in LUT, it will return the port where
+ *      the mac is learned, 802.1x authorized status and dynamic/static entry,
+ *      Otherwise, it will return a RT_ERR_L2_ENTRY_NOTFOUND error.
+ */
+
+rtk_api_ret_t rtk_l2_addr_get(rtk_mac_t *pMac, rtk_fid_t fid, rtk_l2_ucastAddr_t *pL2_data)
+{
+    rtk_api_ret_t retVal;
+    uint32 isStatic, isAuth, port, entryaddr;    
+
+    /* must be unicast address */
+    if((NULL == pMac) || (pMac->octet[0] & 0x1))
+        return RT_ERR_MAC;
+    
+    if(NULL == pL2_data)
+        return RT_ERR_NULL_POINTER;
+
+    pL2_data->auth = FALSE;    
+    pL2_data->fid = 1;
+    pL2_data->is_static = FALSE;
+    pL2_data->port = 0;
+    pL2_data->sa_block = FALSE;
+
+    retVal = rtl8306e_l2_mac_get(pMac->octet, &isStatic, &isAuth, &port, &entryaddr);
+    if(RTL8306_LUT_NOTEXIST == retVal)
+    {        
+        return RT_ERR_L2_ENTRY_NOTFOUND;        
+    }
+    else if(retVal != SUCCESS)
+    {
+        return RT_ERR_FAILED;
+    }
+
+    pL2_data->auth = isAuth;
+    pL2_data->port = port;
+    pL2_data->is_static = isStatic;
+    pL2_data->mac.octet[0] = pMac->octet[0];
+    pL2_data->mac.octet[1] = pMac->octet[1];
+    pL2_data->mac.octet[2] = pMac->octet[2];
+    pL2_data->mac.octet[3] = pMac->octet[3];
+    pL2_data->mac.octet[4] = pMac->octet[4];
+    pL2_data->mac.octet[5] = pMac->octet[5];    
+    
+    return RT_ERR_OK;
+    
+}
+
+
+/* Function Name:
+ *      rtk_l2_addr_del
+ * Description:
+ *      Delete LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast mac address to be deleted
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_NULL_POINTER              -   Input parameter is null pointer    
+ *      RT_ERR_L2_ENTRY_NOTFOUND    -   Specified entry not found 
+ * Note:
+ *      If the mac has existed in the LUT, it will be deleted.
+ *      Otherwise, it will return RT_ERR_L2_ENTRY_NOTFOUND.
+ */
+rtk_api_ret_t rtk_l2_addr_del(rtk_mac_t *pMac, rtk_fid_t fid)
+{
+    rtk_api_ret_t retVal;
+    uint32 entryAddr;
+
+    /* must be unicast address */
+    if((NULL == pMac) || (pMac->octet[0] & 0x1))
+        return RT_ERR_MAC;  
+
+    retVal = rtl8306e_l2_mac_del(pMac->octet, &entryAddr);
+    if(RTL8306_LUT_NOTEXIST == retVal)
+    {
+        return RT_ERR_L2_ENTRY_NOTFOUND;
+    }
+    else if(retVal != SUCCESS)
+    {
+        return RT_ERR_FAILED;
+    }
+
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_l2_mcastAddr_add
+ * Description:
+ *      Add LUT multicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast mac address to be deleted
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ *      portmask          -   Port mask to be forwarded to 
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_PORT_MASK                  -   Invalid port mask
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_L2_INDEXTBL_FULL         -   Hashed index is full of entries
+ * Note:
+ *      If the multicast mac address already existed in the LUT, it will udpate the
+ *      port mask of the entry. Otherwise, it will find an empty or asic auto learned
+ *      entry to write. If all the entries with the same hash value can't be replaced, 
+ *      ASIC will return a RT_ERR_L2_INDEXTBL_FULL error.
+ */
+rtk_api_ret_t rtk_l2_mcastAddr_add(rtk_mac_t *pMac, rtk_fid_t fid, rtk_portmask_t portmask)
+{
+    rtk_api_ret_t retVal;
+    uint32 entryAddr;
+
+    /* must be L2 multicast address */
+    if((NULL == pMac) || (!(pMac->octet[0] & 0x1)))
+        return RT_ERR_MAC;
+
+    if(portmask.bits[0] > RTK_MAX_PORT_MASK)
+        return RT_ERR_PORT_MASK;    
+
+    retVal = rtl8306e_l2_multicastMac_add(pMac->octet, TRUE, portmask.bits[0], &entryAddr);
+    if(RTL8306_LUT_FULL == retVal)
+    {
+        return RT_ERR_L2_INDEXTBL_FULL;
+    }
+    else if(retVal != SUCCESS)
+    {
+        return RT_ERR_FAILED;
+    }
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_l2_mcastAddr_get
+ * Description:
+ *      Get LUT multicast entry
+ * Input:
+ *      pMac               -   6 bytes multicast(I/G bit is 0) mac address to be gotten
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+ *      pPortmask         -   the pointer of port mask      
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_NULL_POINTER              -   Input parameter is null pointer    
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_L2_INDEXTBL_FULL         -   Hashed index is full of entries 
+ * Note:
+ *      If the multicast mac address existed in LUT, it will return the port mask where
+ *      the packet should be forwarded to, Otherwise, it will return a 
+ *      RT_ERR_L2_ENTRY_NOTFOUND error.
+ */
+
+rtk_api_ret_t rtk_l2_mcastAddr_get(rtk_mac_t *pMac, rtk_fid_t fid, rtk_portmask_t *pPortmask)
+{
+    rtk_api_ret_t retVal;
+    uint32 isStatic, isAuth, portmask, entryaddr;        
+
+    /* must be multicast address */
+    if((NULL == pMac) || !(pMac->octet[0] & 0x1))
+        return RT_ERR_MAC;  
+
+    
+    if(NULL == pPortmask)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_l2_mac_get(pMac->octet, &isStatic, &isAuth, &portmask, &entryaddr);
+    if(RTL8306_LUT_NOTEXIST == retVal)
+    {        
+        return RT_ERR_L2_ENTRY_NOTFOUND;        
+    }
+    else if(retVal != SUCCESS)
+    {
+        return RT_ERR_FAILED;
+    }
+
+    pPortmask->bits[0] = portmask;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_l2_mcastAddr_del
+ * Description:
+ *      Delete LUT multicast entry
+ * Input:
+ *      pMac               -   6 bytes multicast(I/G bit is 1) mac address to be gotten
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+*       none
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_L2_ENTRY_NOTFOUND     -   No such LUT entry
+ * Note:
+ *      If the mac has existed in the LUT, it will be deleted.
+ *      Otherwise, it will return RT_ERR_L2_ENTRY_NOTFOUND.
+ */
+
+rtk_api_ret_t rtk_l2_mcastAddr_del(rtk_mac_t *pMac, rtk_fid_t fid)
+{
+    rtk_api_ret_t retVal;
+    uint32 entryAddr;
+
+    /* must be multicast address */
+    if((NULL == pMac) || !(pMac->octet[0] & 0x1))
+        return RT_ERR_MAC;  
+
+    retVal = rtl8306e_l2_mac_del(pMac->octet, &entryAddr);
+    if(RTL8306_LUT_NOTEXIST == retVal)
+    {
+        return RT_ERR_L2_ENTRY_NOTFOUND;
+    }
+    else if(retVal != SUCCESS)
+    {
+        return RT_ERR_FAILED;
+    }
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_l2_limitLearningCnt_set
+ * Description:
+ *      Set per-Port auto learning limit number
+ * Input:
+ *      port - Port id.
+ *      mac_cnt - Auto learning entries limit number
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - set shared meter successfully
+ *      RT_ERR_FAILED          - FAILED to iset shared meter
+ *      RT_ERR_PORT_ID - Invalid port number.
+ *      RT_ERR_LIMITED_L2ENTRY_NUM - Invalid auto learning limit number
+ * Note:
+ *      (1)The API can set per-port ASIC auto learning limit number from 0(disable learning) 
+ *      to 0x1F(31). 
+ *      (2)If mac_cnt is set from 0 to 0x1F, per-port ASIC auto learning limit will be enabled;
+ *      if mac_cnt is set 0xFF, per-port ASIC auto learning limit will be disabled.
+ */
+rtk_api_ret_t rtk_l2_limitLearningCnt_set(rtk_port_t port, rtk_mac_cnt_t mac_cnt)
+{
+    rtk_api_ret_t retVal;
+    uint32 enabled;
+    
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+
+    if ((mac_cnt > RTK_MAX_NUM_OF_LEARN_LIMIT) && (0xFF != mac_cnt))
+        return RT_ERR_LIMITED_L2ENTRY_NUM;
+
+    enabled = (0xFF == mac_cnt ?  FALSE : TRUE);
+    if ((retVal = rtl8306e_l2_portMacLimit_set(port, enabled, mac_cnt)) != RT_ERR_OK)
+        return retVal; 
+    
+    return RT_ERR_OK;
+}    
+
+/* Function Name:
+ *      rtk_l2_limitLearningCnt_get
+ * Description:
+ *      Get per-Port auto learning limit number
+ * Input:
+ *      port - Port id.
+ * Output:
+ *      pMac_cnt - Auto learning entries limit number
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_PORT_ID - Invalid port number. 
+ * Note:
+ *      The API can get per-port ASIC auto learning limit number.
+ */
+rtk_api_ret_t rtk_l2_limitLearningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt)
+{
+    rtk_api_ret_t retVal;
+    uint32 enabled;
+
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+
+    if ((retVal = rtl8306e_l2_portMacLimit_get(port, &enabled, pMac_cnt)) != RT_ERR_OK)
+        return retVal;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_l2_limitLearningCntAction_set
+ * Description:
+ *      Configure auto learn over limit number action.
+ * Input:
+ *      port - Port id (must be RTK_WHOLE_SYSTEM)
+ *      action - Auto learning entries limit number
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_PORT_ID - Invalid port number.
+ *      RT_ERR_NOT_ALLOWED - Invalid learn over action
+ * Note:
+ *      (1)The API can set SA unknown packet action while auto learn limit number is over. 
+ *      The action symbol as following:
+ *      - LIMIT_LEARN_CNT_ACTION_DROP,
+ *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
+ *      (2)The action is global, so the port must be set as RTK_WHOLE_SYSTEM
+ */
+rtk_api_ret_t rtk_l2_limitLearningCntAction_set(rtk_port_t port, rtk_l2_limitLearnCntAction_t action)
+{
+    rtk_api_ret_t retVal;
+    uint32 data;
+    
+    if (port != RTK_WHOLE_SYSTEM)
+        return RT_ERR_PORT_ID;    
+    
+    if ( LIMIT_LEARN_CNT_ACTION_DROP == action )
+        data = RTL8306_ACT_DROP;
+    else if ( LIMIT_LEARN_CNT_ACTION_TO_CPU == action )
+        data = RTL8306_ACT_TRAPCPU;
+    else
+        return RT_ERR_NOT_ALLOWED;    
+
+    
+    if ((retVal = rtl8306e_l2_macLimitAction_set(data)) != RT_ERR_OK)
+        return retVal; 
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_l2_limitLearningCntAction_get
+ * Description:
+ *      Get auto learn over limit number action.
+ * Input:
+ *      port - Port id (must be RTK_WHOLE_SYSTEM)
+ * Output:
+ *      pAction - Learn over action
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_PORT_ID - Invalid port number. 
+ * Note:
+ *      (1)The API can get SA unknown packet action while auto learn limit number is over. 
+ *      The action symbol as following:
+ *      - LIMIT_LEARN_CNT_ACTION_DROP,
+ *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
+ *      (2)The action is global, so the port must be set as RTK_WHOLE_SYSTEM
+ */
+rtk_api_ret_t rtk_l2_limitLearningCntAction_get(rtk_port_t port, rtk_l2_limitLearnCntAction_t *pAction)
+{
+    rtk_api_ret_t retVal;
+    uint32 action;
+    
+    if (port != RTK_WHOLE_SYSTEM)
+        return RT_ERR_PORT_ID;    
+    
+    if ((retVal = rtl8306e_l2_macLimitAction_get(&action)) != RT_ERR_OK)
+        return retVal; 
+
+    if (RTL8306_ACT_DROP == action)
+        *pAction = LIMIT_LEARN_CNT_ACTION_DROP;
+    else if (RTL8306_ACT_TRAPCPU == action)
+        *pAction = LIMIT_LEARN_CNT_ACTION_TO_CPU;
+    else
+        return RT_ERR_FAILED; 
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_l2_learningCnt_get
+ * Description:
+ *      Get per-Port current auto learning number
+ * Input:
+ *      port - Port id.
+ * Output:
+ *      pMac_cnt - ASIC auto learning entries number
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_PORT_ID - Invalid port number. 
+ *      RT_ERR_NULL_POINTER   -   Input parameter is null pointer  
+ * Note:
+ *      The API can get per-port ASIC auto learning number
+ */
+rtk_api_ret_t rtk_l2_learningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt)
+{
+    uint32 regVal;
+    
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+    
+    if (NULL == pMac_cnt)
+        return RT_ERR_NULL_POINTER;
+    
+    if (5 == port)
+        port ++;
+
+    if (0 == port)
+    {
+        rtl8306e_reg_get(0, 27, 3, &regVal);
+        *pMac_cnt = (regVal & 0x7FF) ;
+    }
+    else
+    {
+        rtl8306e_reg_get(port, 31, 1, &regVal);
+        *pMac_cnt = (regVal & 0x7FF) ;
+    }
+ 
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_cpu_enable_set
+ * Description:
+ *      Set cpu port function enable or disable
+ * Input:
+ *      enable          - enable or disable
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ * Note:
+ *      The API can set CPU port function enable/disable
+ *      default port 4 is cpu port.
+ */
+rtk_api_ret_t rtk_cpu_enable_set(rtk_enable_t enable)
+{
+    rtk_api_ret_t retVal;
+
+    if (ENABLED == enable)
+        retVal = rtl8306e_cpu_set(RTL8306_PORT4, FALSE);
+    else
+        retVal = rtl8306e_cpu_set(RTL8306_NOCPUPORT, FALSE);
+    
+    return retVal;    
+}
+
+
+/* Function Name:
+ *      rtk_cpu_enable_get
+ * Description:
+ *      Get cpu port function enable or disable
+ * Input:
+ *      none
+ * Output:
+ *      pEnable          -  the pointer of enable or disable cpu port function
+ * Return:
+ *      RT_ERR_OK                   -  Success
+ *      RT_ERR_FAILED             -   Failure
+ * Note:
+ *      The API can set CPU port function enable/disable
+ */
+rtk_api_ret_t rtk_cpu_enable_get(rtk_enable_t *pEnable)
+{
+    rtk_api_ret_t retVal;
+    uint32 port, entag;
+    
+    if(NULL == pEnable)
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_cpu_get(&port, &entag);
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    if(RTL8306_NOCPUPORT == port)
+        *pEnable = DISABLED;
+    else
+        *pEnable = ENABLED;
+        
+    return RT_ERR_OK;    
+}
+
+/* Function Name:
+ *      rtk_cpu_tagPort_set
+ * Description:
+ *      Set CPU port and CPU tag insert mode
+ * Input:
+ *      port          -  Port id
+ *      mode        -  CPU tag insert for packets egress from CPU port
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                   -  Success
+ *      RT_ERR_FAILED             -   Failure
+ *      RT_ERR_PORT_ID           -   Invalid port id
+ * Note:
+ *      The API can set CPU port and inserting proprietary CPU tag mode (Length/Type 0x8899)
+ *      to the frame that transmitting to CPU port.
+ *      The inset cpu tag mode is as following:
+ *          - CPU_INSERT_TO_ALL
+ *          - CPU_INSERT_TO_TRAPPING
+ *          - CPU_INSERT_TO_NONE   
+ */
+ 
+rtk_api_ret_t rtk_cpu_tagPort_set(rtk_port_t port, rtk_cpu_insert_t mode)
+{
+    rtk_api_ret_t retVal;
+    uint32 regval;
+
+    if(port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+
+    switch(mode)
+    {
+        case CPU_INSERT_TO_ALL:
+            retVal = rtl8306e_cpu_set(port, TRUE);             
+            if(retVal != SUCCESS)
+                return RT_ERR_FAILED;
+            break;
+        case CPU_INSERT_TO_TRAPPING:
+            retVal = rtl8306e_cpu_set(port, FALSE);                        
+            if(retVal != SUCCESS)
+                return RT_ERR_FAILED;
+            /*enable insert cpu tag for trap pkt */
+            rtl8306e_reg_get(6, 30, 1, &regval);
+            regval |= (0x7F << 8);
+            rtl8306e_reg_set(6, 30, 1, regval);            
+            break;
+        case CPU_INSERT_TO_NONE:
+            retVal = rtl8306e_cpu_set(port, FALSE);                        
+            if(retVal != SUCCESS)
+                return RT_ERR_FAILED;
+            /*disable insert cpu tag for trap pkt */
+            rtl8306e_reg_get(6, 30, 1, &regval);
+            regval &= ~(0x7F << 8);
+            rtl8306e_reg_set(6, 30, 1, regval);                        
+            break;
+        default:
+            return RT_ERR_INPUT;
+    }
+                    
+    return RT_ERR_OK;        
+}
+
+
+/* Function Name:
+ *      rtk_cpu_tagPort_get
+ * Description:
+ *      Get CPU port and CPU tag insert mode
+ * Input:
+ *      port          -  Port id
+ * Output:
+ *      pMode       -  the pointer of CPU tag insert for packets egress from CPU port
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_NULL_POINTER      -   Input parameter is null pointer
+ * Note:
+ *      The API can set CPU port and inserting proprietary CPU tag mode (Length/Type 0x8899)
+ *      to the frame that transmitting to CPU port.
+ *      The inset cpu tag mode is as following:
+ *          CPU_INSERT_TO_ALL
+ *          CPU_INSERT_TO_TRAPPING
+ *          CPU_INSERT_TO_NONE   
+ */
+
+rtk_api_ret_t rtk_cpu_tagPort_get(rtk_port_t *pPort, rtk_cpu_insert_t *pMode)
+{
+    rtk_api_ret_t retVal;
+    uint32 enCputag;
+    uint32 regval;
+
+    if ((NULL == pPort) || (NULL == pMode))
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_cpu_get(pPort, &enCputag);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    if(enCputag)
+    {
+        *pMode = CPU_INSERT_TO_ALL;
+    }
+    else
+    {
+        /*enable insert cpu tag for trap pkt */
+        rtl8306e_reg_get(6, 30, 1, &regval);
+        if((0x7F << 8) == (regval & (0x7F << 8)))
+            *pMode = CPU_INSERT_TO_TRAPPING;
+        else
+            *pMode = CPU_INSERT_TO_NONE;
+    }
+    
+    return RT_ERR_OK;                    
+}
+
+
+
+/* Function Name:
+ *      rtk_mirror_portBased_set
+ * Description:
+ *      Set port mirror function
+ * Input:
+ *      mirroring_port                  - Monitor port, 7 means no monitor port
+ *      pMirrored_rx_portmask      - the pointer of Rx mirror port mask
+ *      pMirrored_tx_portmask      - the pointer of Tx mirror port mask
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_PORT_MASK         -   Invalid port mask
+ * Note:
+ *      The API is to set mirror function of source port and mirror port. 
+ */
+
+rtk_api_ret_t rtk_mirror_portBased_set(rtk_port_t mirroring_port, rtk_portmask_t *pMirrored_rx_portmask, rtk_portmask_t *pMirrored_tx_portmask)
+{
+    rtk_api_ret_t retVal;
+        
+    if ((NULL == pMirrored_rx_portmask) || (NULL == pMirrored_tx_portmask))
+        return RT_ERR_NULL_POINTER;
+    
+    if (pMirrored_rx_portmask->bits[0] > RTL8306_MAX_PORTMASK)
+        return RT_ERR_PORT_MASK; 
+
+    if (pMirrored_tx_portmask->bits[0] > RTL8306_MAX_PORTMASK)
+        return RT_ERR_PORT_MASK;
+
+    retVal = rtl8306e_mirror_portBased_set(mirroring_port, 
+                pMirrored_rx_portmask->bits[0],
+                pMirrored_tx_portmask->bits[0]);
+    return retVal;
+}
+
+/* Function Name:
+ *      rtk_mirror_portBased_get
+ * Description:
+ *      Get port mirror function
+ * Input:
+ *      none 
+ * Output:
+ *      pMirroring_port             - the pointer Monitor port, 7 means no monitor port
+ *      pMirrored_rx_portmask   - the pointer of Rx mirror port mask
+ *      pMirrored_tx_portmask   - the pointer of Tx mirror port mask 
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_PORT_MASK         -   Invalid port mask
+ *      RT_ERR_NULL_POINTER      -   Input parameter is null pointer 
+ * Note:
+ *      The API is to set mirror function of source port and mirror port. 
+ */
+rtk_api_ret_t rtk_mirror_portBased_get(rtk_port_t *pMirroring_port, rtk_portmask_t *pMirrored_rx_portmask, rtk_portmask_t *pMirrored_tx_portmask)
+{
+    rtk_api_ret_t retVal;
+    
+    if ((NULL == pMirrored_rx_portmask) || (NULL == pMirrored_tx_portmask) ||
+        (NULL == pMirroring_port))
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_mirror_portBased_get(pMirroring_port, 
+                &(pMirrored_rx_portmask->bits[0]),
+                &(pMirrored_tx_portmask->bits[0]));
+    
+    return retVal;
+}
+
+/* Function Name:
+ *      rtk_dot1x_unauthPacketOper_set
+ * Description:
+ *      Set 802.1x unauth action configuration
+ * Input:
+ *      port                 -   Port id, no use for RTL8306E switch
+ *      unauth_action   -   802.1X unauth action    
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_DOT1X_PROC        -   Unauthorized behavior error
+ * Note:
+ *      This API can set 802.1x unauth action configuration, 
+ *      for RTL8306E switch, the action is by whole system,
+ *      so port could be any value of 0~6.
+ *      The unauth action is as following:
+ *          - DOT1X_ACTION_DROP
+ *          - DOT1X_ACTION_TRAP2CPU
+ */
+rtk_api_ret_t rtk_dot1x_unauthPacketOper_set(rtk_port_t port, rtk_dot1x_unauth_action_t unauth_action)
+{
+    rtk_api_ret_t retVal;
+
+    if(unauth_action > DOT1X_ACTION_TRAP2CPU)
+        return RT_ERR_DOT1X_PROC;
+
+    if(DOT1X_ACTION_DROP == unauth_action)
+    {
+        retVal = rtl8306e_trap_abnormalPktAction_set(RTL8306_DOT1XUNAUTH, RTL8306_ACT_DROP);
+    }
+    else if(DOT1X_ACTION_TRAP2CPU == unauth_action)
+    {
+        retVal = rtl8306e_trap_abnormalPktAction_set(RTL8306_DOT1XUNAUTH, RTL8306_ACT_TRAPCPU);
+    }
+    else
+        retVal = RT_ERR_DOT1X_PROC;
+
+    return retVal;
+}
+
+/* Function Name:
+ *      rtk_dot1x_unauthPacketOper_get
+ * Description:
+ *      Get 802.1x unauth action configuration
+ * Input:
+ *      port                  -   Port id, no use for RTL8306E switch
+ * Output:
+ *      pUnauth_action   -  the pointer of 802.1X unauth action    
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_NULL_POINTER      -   Input parameter is null pointer
+ * Note:
+ *      This API can set 802.1x unauth action configuration, 
+ *      for RTL8306E switch, the action is by whole system,
+ *      so port could be any value of 0~6.
+ *      The unauth action is as following:
+ *          - DOT1X_ACTION_DROP
+ *          - DOT1X_ACTION_TRAP2CPU
+ */
+rtk_api_ret_t rtk_dot1x_unauthPacketOper_get(rtk_port_t port, rtk_dot1x_unauth_action_t *pUnauth_action)
+{
+    rtk_api_ret_t retVal;
+    uint32 action;
+    
+    if(NULL == pUnauth_action)
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_trap_abnormalPktAction_get(RTL8306_DOT1XUNAUTH, &action);
+
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    if(RTL8306_ACT_DROP == action)
+    {
+        *pUnauth_action = DOT1X_ACTION_DROP;
+    }
+    else 
+    {
+        *pUnauth_action = DOT1X_ACTION_TRAP2CPU;
+    }
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_dot1x_portBasedEnable_set
+ * Description:
+ *      Set 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ *      enable               -   enable or disable
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_PORT_ID              -   Invalid port id
+ * Note:
+ *      The API can update the port-based port enable register content. If a port is 802.1x 
+ *      port based network access control "enabled", it should be authenticated so packets 
+ *      from that port won't be dropped or trapped to CPU. 
+ *      The status of 802.1x port-based network access control is as following:
+ *          - DISABLED
+ *          - ENABLED
+ */    
+ 
+rtk_api_ret_t rtk_dot1x_portBasedEnable_set(rtk_port_t port, rtk_enable_t enable)
+{
+    rtk_api_ret_t retVal;
+    uint32 isAuth, direction, enDot1x;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    retVal = rtl8306e_dot1x_portBased_get(port, &enDot1x, &isAuth, &direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    retVal = rtl8306e_dot1x_portBased_set(port, (uint32)enable, isAuth, direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_portBasedEnable_get
+ * Description:
+ *      Get 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pEnable             -   the pointer of enable or disable
+ * Return:
+ *      RT_ERR_OK                -  Success
+ *      RT_ERR_FAILED          -   Failure
+ *      RT_ERR_PORT_ID        -   Invalid port id
+ * Note:
+ *      The API can update the port-based port enable register content. If a port is 802.1x 
+ *      port based network access control "enabled", it should be authenticated so packets 
+ *      from that port won't be dropped or trapped to CPU. 
+ *      The status of 802.1x port-based network access control is as following:
+ *          - DISABLED
+ *          - ENABLED
+ */    
+ 
+rtk_api_ret_t rtk_dot1x_portBasedEnable_get(rtk_port_t port, rtk_enable_t *pEnable)
+{
+    rtk_api_ret_t retVal;
+    uint32 isAuth, direction, enDot1x;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if(NULL == pEnable)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_dot1x_portBased_get(port, &enDot1x, &isAuth, &direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    *pEnable = enDot1x ? ENABLED : DISABLED;
+            
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_portBasedAuthStatus_set
+ * Description:
+ *      Set 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ *      port_auth          -  The status of 802.1x port
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                    -  Success
+ *      RT_ERR_FAILED                              -   Failure
+ *      RT_ERR_PORT_ID                            -   Invalid port id
+ *      RT_ERR_DOT1X_PORTBASEDAUTH      -   Port-based auth port error
+ * Note:
+ *      The authenticated status of 802.1x port-based network access control is as following:
+ *          - UNAUTH
+ *          - AUTH
+ */    
+rtk_api_ret_t rtk_dot1x_portBasedAuthStatus_set(rtk_port_t port, rtk_dot1x_auth_status_t port_auth)
+{
+    rtk_api_ret_t retVal;
+    uint32 isAuth, direction, enDot1x;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if(port_auth > AUTH_STATUS_END)
+        return RT_ERR_DOT1X_PORTBASEDAUTH;
+
+    retVal = rtl8306e_dot1x_portBased_get(port, &enDot1x, &isAuth, &direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    retVal = rtl8306e_dot1x_portBased_set(port, enDot1x, (uint32)port_auth, direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_portBasedAuthStatus_get
+ * Description:
+ *      Get 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pPort_auth         -   the pointer of the status of 802.1x port
+ * Return:
+ *      RT_ERR_OK                          -  Success
+ *      RT_ERR_FAILED                     -  Failure
+ *      RT_ERR_PORT_ID                   -  Invalid port id
+ *      RT_ERR_NULL_POINTER           -  Input parameter is null pointer
+ * Note:
+ *      The authenticated status of 802.1x port-based network access control is as following:
+ *          - UNAUTH
+ *          - AUTH
+ */    
+rtk_api_ret_t rtk_dot1x_portBasedAuthStatus_get(rtk_port_t port, rtk_dot1x_auth_status_t *pPort_auth)
+{
+    rtk_api_ret_t retVal;
+    uint32 isAuth, direction, enDot1x;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    if (NULL == pPort_auth)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_dot1x_portBased_get(port, &enDot1x, &isAuth, &direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    *pPort_auth = isAuth ? AUTH: UNAUTH;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_portBasedDirection_set
+ * Description:
+ *      Set 802.1x port-based operational direction configuration
+ * Input:
+ *      port                  -   Port id
+ *      port_direction     -   Operation direction
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                 -  Success
+ *      RT_ERR_FAILED                           -  Failure
+ *      RT_ERR_PORT_ID                         -  Invalid port id
+ *      RT_ERR_DOT1X_PORTBASEDOPDIR  -  Port-based opdir error
+ * Note:
+ *      The operate controlled direction of 802.1x port-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */    
+
+rtk_api_ret_t rtk_dot1x_portBasedDirection_set(rtk_port_t port, rtk_dot1x_direction_t port_direction)
+{
+    rtk_api_ret_t retVal;
+    uint32 isAuth, direction, enDot1x;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    
+    if(port_direction >= DIRECTION_END)
+        return RT_ERR_DOT1X_PORTBASEDOPDIR;
+
+    retVal = rtl8306e_dot1x_portBased_get(port, &enDot1x, &isAuth, &direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    retVal = rtl8306e_dot1x_portBased_set(port, enDot1x, isAuth, (uint32)port_direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_dot1x_portBasedDirection_get
+ * Description:
+ *      Get 802.1x port-based operational direction configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pPort_direction    -   the pointer of Operation direction
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_PORT_ID                  -  Invalid port id
+ *      RT_ERR_NULL_POINTER          -  Input parameter is null pointer
+ * Note:
+ *      The operate controlled direction of 802.1x port-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */    
+rtk_api_ret_t rtk_dot1x_portBasedDirection_get(rtk_port_t port, rtk_dot1x_direction_t *pPort_direction)
+{
+    rtk_api_ret_t retVal;
+    uint32 isAuth, direction, enDot1x;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if(NULL == pPort_direction)
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_dot1x_portBased_get(port, &enDot1x, &isAuth, &direction);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    *pPort_direction = (rtk_dot1x_direction_t)direction;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_macBasedEnable_set
+ * Description:
+ *      Set 802.1x mac-based port enable configuration
+ * Input:
+ *      port                  -   Port id
+ *      enable               -   The status of 802.1x mac-base funtion
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_PORT_ID                  -  Invalid port id
+ * Note:
+ *     If a port is 802.1x MAC based network access control "enabled", the incoming packets should 
+ *     be authenticated so packets from that port won't be dropped or trapped to CPU.
+ *     The status of 802.1x MAC-based network access control is as following:
+ *         - DISABLED
+ *         - ENABLED
+ */    
+rtk_api_ret_t rtk_dot1x_macBasedEnable_set(rtk_port_t port, rtk_enable_t enable)
+{
+    rtk_api_ret_t retVal;
+    uint32 direction, enMacBase;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+    
+    retVal = rtl8306e_dot1x_macBased_get(port, &enMacBase, &direction); 
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    retVal = rtl8306e_dot1x_macBased_set(port, (uint32)enable, direction);
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+       
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_macBasedEnable_get
+ * Description:
+ *      Get 802.1x mac-based port enable configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pEnable             -   the pointer of the status of 802.1x mac-base funtion
+ * Return:
+ *      RT_ERR_OK               -  Success
+ *      RT_ERR_FAILED         -   Failure
+ * Note:
+ *     If a port is 802.1x MAC based network access control "enabled", the incoming packets should 
+ *     be authenticated so packets from that port won't be dropped or trapped to CPU.
+ *     The status of 802.1x MAC-based network access control is as following:
+ *         - DISABLED
+ *         - ENABLED
+ */    
+rtk_api_ret_t rtk_dot1x_macBasedEnable_get(rtk_port_t port, rtk_enable_t *pEnable)
+{
+    rtk_api_ret_t retVal;
+    uint32 direction, enMacBase;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;    
+
+    if(NULL == pEnable)
+        return RT_ERR_NULL_POINTER;
+    
+    retVal = rtl8306e_dot1x_macBased_get(port, &enMacBase, &direction); 
+    if (retVal != SUCCESS)
+        return RT_ERR_FAILED;
+
+    *pEnable = enMacBase ? ENABLED: DISABLED;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_macBasedDirection_set
+ * Description:
+ *      Set 802.1x mac-based operational direction configuration
+ * Input:
+ *      mac_direction    -   Operation direction
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                    -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_DOT1X_MACBASEDOPDIR      -  MAC-based opdir error
+ * Note:
+ *      The operate controlled direction of 802.1x mac-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */    
+
+rtk_api_ret_t rtk_dot1x_macBasedDirection_set(rtk_dot1x_direction_t mac_direction)
+{
+    rtk_api_ret_t retVal;
+        
+    if(mac_direction > DIRECTION_END) 
+        return RT_ERR_DOT1X_MACBASEDOPDIR;    
+
+    retVal = rtl8306e_regbit_set(2, 22, 7, 3, mac_direction == BOTH ? 0:1);
+
+    return retVal;
+}
+    
+/* Function Name:
+ *      rtk_dot1x_macBasedDirection_get
+ * Description:
+ *      Get 802.1x mac-based operational direction configuration
+ * Input:
+ *      none
+ * Output:
+ *      pMac_direction    -   the pointer of Operation direction
+ * Return:
+ *      RT_ERR_OK                                    -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_NULL_POINTER                    -  Input parameter is null pointer
+ * Note:
+ *      The operate controlled direction of 802.1x mac-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */
+rtk_api_ret_t rtk_dot1x_macBasedDirection_get(rtk_dot1x_direction_t *pMac_direction)
+{
+    rtk_api_ret_t retVal;
+    uint32          dir;
+
+    if(NULL == pMac_direction)
+        return RT_ERR_NULL_POINTER;
+
+    retVal = rtl8306e_regbit_get(2, 22, 7, 3, &dir);
+    if(retVal != SUCCESS)
+        return RT_ERR_FAILED;
+    
+    *pMac_direction = dir ? IN: BOTH;
+    
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_dot1x_macBasedAuthMac_add
+ * Description:
+ *      Add an authenticated MAC to ASIC
+ * Input:
+ *      port            -  Port id
+ *      pAuth_mac   - The authenticated MAC
+ *      fid              -  no use for RTL8306E   
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                       - Success
+ *      RT_ERR_FAILED                                 -  Failure
+ *      RT_ERR_L2_ENTRY_NOTFOUND             -  Specified entry not found
+ *      RT_ERR_DOT1X_MAC_PORT_MISMATCH  - Auth MAC and port mismatch eror 
+ * Note:
+ *     The API can add a 802.1x authenticated MAC address to port. If the MAC does not exist in LUT, 
+ *     user can't add this MAC to auth status.
+ */    
+
+rtk_api_ret_t rtk_dot1x_macBasedAuthMac_add(rtk_port_t port, rtk_mac_t *pAuth_mac, rtk_fid_t fid)
+{
+    int32 i;
+    uint8 macAddr[6];
+    uint32 index,entryaddr;
+    uint32 isStatic,isAuth,age, srcPort;
+    uint32 isHit;
+
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+
+    if(NULL == pAuth_mac)
+        return RT_ERR_NULL_POINTER;
+
+    if(pAuth_mac->octet[0] & 0x1)
+        return RT_ERR_DOT1X_MAC_PORT_MISMATCH;
+
+    rtl8306e_l2_MacToIdx_get(pAuth_mac->octet, &index);   
+    
+    isHit = FALSE;
+    for (i = 3; i >= 0; i--) 
+    {
+        entryaddr = (index << 2) | (uint32)i;
+        if (rtl8306e_l2_unicastEntry_get(macAddr, entryaddr, &age, &isStatic, &isAuth, &srcPort) != SUCCESS) 
+        {
+            return RT_ERR_FAILED;
+        }
+        else if ((pAuth_mac->octet[0] == macAddr[0]) && (pAuth_mac->octet[1] == macAddr[1]) && 
+                   (pAuth_mac->octet[2] == macAddr[2]) && (pAuth_mac->octet[3] == macAddr[3]) &&
+                   (pAuth_mac->octet[4] == macAddr[4]) && (pAuth_mac->octet[5] == macAddr[5])) 
+        {
+            if(srcPort != port)
+                return RT_ERR_DOT1X_MAC_PORT_MISMATCH;
+            if (rtl8306e_l2_unicastEntry_set(pAuth_mac->octet, (uint32)i , age, isStatic, TRUE, port) != SUCCESS)
+                return RT_ERR_FAILED;
+            isHit = TRUE;
+            return RT_ERR_OK;
+        }
+    }
+
+    if(!isHit)
+        return RT_ERR_L2_ENTRY_NOTFOUND;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_dot1x_macBasedAuthMac_del
+ * Description:
+ *      Delete an authenticated MAC to ASIC
+ * Input:
+ *      port            -  Port id
+ *      pAuth_mac   - The authenticated MAC
+ *      fid              -  no use for RTL8306E   
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                       - Success
+ *      RT_ERR_FAILED                                 -  Failure
+ *      RT_ERR_L2_ENTRY_NOTFOUND             -  Specified entry not found
+ *      RT_ERR_DOT1X_MAC_PORT_MISMATCH  - Auth MAC and port mismatch eror 
+ * Note:
+ *     The API can delete a 802.1x authenticated MAC address to port. It only change the auth status of
+ *     the MAC and won't delete it from LUT.
+ */
+rtk_api_ret_t rtk_dot1x_macBasedAuthMac_del(rtk_port_t port, rtk_mac_t *pAuth_mac, rtk_fid_t fid)
+{
+    int32 i;
+    uint8 macAddr[6];
+    uint32 index,entryaddr;
+    uint32 isStatic,isAuth,age, srcPort;
+    uint32 isHit;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+
+    if(NULL == pAuth_mac)
+        return RT_ERR_NULL_POINTER;
+
+    if(pAuth_mac->octet[0] & 0x1)
+        return RT_ERR_DOT1X_MAC_PORT_MISMATCH;
+
+    rtl8306e_l2_MacToIdx_get(pAuth_mac->octet, &index);   
+    
+    isHit = FALSE;
+    for (i = 3; i >= 0; i--) 
+    {
+        entryaddr = (index << 2) | (uint32)i;
+        if (rtl8306e_l2_unicastEntry_get(macAddr, entryaddr, &age, &isStatic, &isAuth, &srcPort) != SUCCESS) 
+        {
+            return RT_ERR_FAILED;
+        }
+        else if ((pAuth_mac->octet[0] == macAddr[0]) && (pAuth_mac->octet[1] == macAddr[1]) && 
+                   (pAuth_mac->octet[2] == macAddr[2]) && (pAuth_mac->octet[3] == macAddr[3]) &&
+                   (pAuth_mac->octet[4] == macAddr[4]) && (pAuth_mac->octet[5] == macAddr[5])) 
+        {
+            if(srcPort != port)
+                return RT_ERR_DOT1X_MAC_PORT_MISMATCH;
+            if (rtl8306e_l2_unicastEntry_set(pAuth_mac->octet, (uint32)i , age, isStatic, FALSE, port) != SUCCESS)
+                return RT_ERR_FAILED;
+            isHit = TRUE;
+            return RT_ERR_OK;
+        }
+    }
+
+    if(!isHit)
+        return RT_ERR_L2_ENTRY_NOTFOUND;
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_svlan_init
+ * Description:
+ *      Initialize SVLAN Configuration
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ *      RT_ERR_INPUT
+ * Note:
+ *    Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 
+ *    0x9100 and 0x9200 for Q-in-Q SLAN design. User can set mathced ether 
+ *    type as service provider supported protocol. After call this API, all ports are 
+ *    set as CVLAN port. you can use rtk_svlan_servicePort_add to add SVLAN port. 
+ */
+rtk_api_ret_t rtk_svlan_init(void)
+{
+
+    uint32 regval;
+    uint32 port;
+    
+    /*enable Q_in_Q*/
+    rtl8306e_regbit_set(6, 30, 6, 3, 1);
+    rtl8306e_regbit_set(6, 30, 7, 3, 1);    
+
+   /*clear NNI port list*/
+   rtl8306e_reg_get(6, 30, 3, &regval);
+   regval &= (~0x3f);
+   rtl8306e_reg_set(6, 30, 3, regval);
+    
+   /*set default TPID*/
+    rtl8306e_reg_set(6, 28, 3, 0x88a8);
+
+   /*default use port-base otag PVID and priority as Otag source*/
+   for(port = 0; port < 6; port ++)
+        rtl8306e_svlan_otagSrc_set(port, 0, 0);
+
+   return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_svlan_servicePort_add
+ * Description:
+ *      Enable one service port in the specified device
+ * Input:
+ *      port     -  Port id
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ * Note:
+ *    This API is setting which port is connected to provider switch. All frames receiving from this port
+ *    will recognize Service Vlan Tag.
+ *    
+ */
+rtk_api_ret_t rtk_svlan_servicePort_add(rtk_port_t port)
+{
+    uint32 regval;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+
+    /*add the port to NNI port list*/
+    rtl8306e_reg_get(6, 30, 3, &regval);    
+    regval |= (1 << port);
+    rtl8306e_reg_set(6, 30, 3, regval);
+    
+    return RT_ERR_OK;    
+}
+
+
+/* Function Name:
+ *      rtk_svlan_servicePort_del
+ * Description:
+ *      Disable one service port in the specified device
+ * Input:
+ *      none
+ * Output:
+ *      pSvlan_portmask  - svlan ports mask
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ * Note:
+ */
+rtk_api_ret_t rtk_svlan_servicePort_del(rtk_port_t port)
+{
+    uint32 regval;
+
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+    
+    /*delete the port from NNI port list*/
+    rtl8306e_reg_get(6, 30, 3, &regval);    
+    regval &= (~(1 << port));
+    rtl8306e_reg_set(6, 30, 3, regval);
+        
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_svlan_servicePort_get
+ * Description:
+ *      Disable one service port in the specified device
+ * Input:
+ *      none
+ * Output:
+ *      pSvlan_portmask  - svlan ports mask
+ * Return:
+ *      RT_ERR_OK                 - success
+ *      RT_ERR_FAILED            -  fail
+ *      RT_ERR_NULL_POINTER  -  null pointer
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 
+ *      and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+rtk_api_ret_t rtk_svlan_servicePort_get(rtk_portmask_t *pSvlan_portmask)
+{
+    uint32 regval;
+
+    if(NULL == pSvlan_portmask)
+        return RT_ERR_NULL_POINTER;
+
+    rtl8306e_reg_get(6, 30, 3, &regval);
+    pSvlan_portmask->bits[0] = regval & 0x3F;
+
+    return RT_ERR_OK;
+}
+
+
+/* Function Name:
+ *      rtk_svlan_tpidEntry_set
+ * Description:
+ *      Configure accepted S-VLAN ether type. The default ether type of S-VLAN is 0x88a8
+ * Input:
+ *      svlan_tag_id  - Ether type of S-tag frame parsing in uplink ports
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 
+ *      and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+rtk_api_ret_t rtk_svlan_tpidEntry_set(rtk_svlan_tpid_t svlan_tag_id)
+{
+
+    rtl8306e_reg_set(6, 28, 3, (uint32)svlan_tag_id);
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_svlan_tpidEntry_get
+ * Description:
+ *      Get accepted S-VLAN ether type. The default ether type of S-VLAN is 0x88a8
+ * Input:
+ *      pSvlan_tag_id       - Ether type of S-tag frame parsing in uplink ports
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 
+ *      and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+rtk_api_ret_t rtk_svlan_tpidEntry_get(rtk_svlan_tpid_t *pSvlan_tag_id)
+{
+    uint32 regval;
+    
+    if(NULL == pSvlan_tag_id)
+        return RT_ERR_NULL_POINTER;
+    
+    rtl8306e_reg_get(6, 28, 3, &regval);
+    *pSvlan_tag_id = regval;    
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_svlan_portPvid_set
+ * Description:
+ *      Set port to specified VLAN ID(PVID) for Service Provider Port
+ * Input:
+ *      port             - Port id
+ *      pvid             - Specified Service VLAN ID
+ *      priority         - 802.1p priority for the PVID
+ *      dei               - Service VLAN tag DEI bit
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_VLAN_VID
+ *      RT_ERR_SMI 
+ *      RT_ERR_VLAN_PRIORITY 
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND
+ * Note:
+ *    The API is used for Port-based VLAN. The untagged frame received from the
+ *    port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+rtk_api_ret_t rtk_svlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority, rtk_dei_t dei)
+{
+    uint32 regval;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+    
+    /* vid must be 0~4095 */
+    if(pvid > 0x4095)
+        return RT_ERR_VLAN_VID;
+
+    /* priority must be 0~7 */
+    if(priority > 0x7)
+        return RT_ERR_VLAN_PRIORITY;
+
+    rtl8306e_reg_get(6, 26 + port, 0, &regval);
+    regval &= (1 << 12);
+    regval |= pvid | (priority << 13);
+    rtl8306e_reg_set(6, 26 + port, 0, regval);
+
+    return RT_ERR_OK;
+}
+
+
+
+/* Function Name:
+ *      rtk_svlan_portPvid_get
+ * Description:
+ *      Get Service VLAN ID(PVID) on specified port
+ * Input:
+ *      port             - Port id
+ *      pPvid            - Specified VLAN ID
+ *      pPriority        - 802.1p priority for the PVID
+ *      pDei             - DEI bit
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_NULL_POINTER 
+ * Note:
+ *    The API is used for Port-based VLAN. The untagged frame received from the
+ *    port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+rtk_api_ret_t rtk_svlan_portPvid_get(rtk_port_t port, rtk_vlan_t *pPvid, rtk_pri_t* pPriority, rtk_dei_t *pDei)
+{
+    uint32 regval;
+    
+    if(port > RTK_PORT_ID_MAX) 
+        return RT_ERR_PORT_ID;        
+    
+    if((NULL == pPvid) || (NULL == pPriority) || (NULL == pDei))
+        return RT_ERR_NULL_POINTER;
+    
+    rtl8306e_reg_get(6, 26 + port, 0, &regval);
+    *pPvid = regval & 0xfff;
+    *pPriority = (regval & (0x7 << 13)) >> 13;
+    *pDei = 0;
+
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_filter_igrAcl_init
+ * Description:
+ *       Initialize ACL 
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ * Note:
+ *      The API init ACL module.
+ */
+rtk_api_ret_t rtk_filter_igrAcl_init(void)
+{
+    uint32 entaddr;
+
+    /*empty the acl table*/
+    for (entaddr = 0; entaddr < RTL8306_ACL_ENTRYNUM; entaddr++ ) 
+    {
+        if (rtl8306e_acl_entry_set(entaddr, RTL8306_ACL_INVALID, RTL8306_ACT_DROP, RTL8306_ACL_ETHER, 0, 0) == FAILED)
+            return RT_ERR_FAILED;
+    }
+    
+    return RT_ERR_OK;
+}
+
+/* Function Name:
+ *      rtk_filter_igrAcl_rule_add
+ * Description:
+ *      Add an acl rule into acl table
+ * Input:
+ *      pRule    -  the pointer of rule structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_TBL_FULL
+ *      RT_ERR_NULL_POINTER
+ * Note:
+ *      The API add an  ACL rule. <nl>
+ *      phyport could be  0~5: port number,  RTL8306_ACL_ANYPORT: any port;<nl>
+ *      protocol could be RTL8306_ACL_ETHER(ether type), RTL8306_ACL_TCP(TCP), RTL8306_ACL_UDP(UDP), RTL8306_ACL_TCPUDP(TCP or UDP);<nl>
+ *      prority could be RTL8306_PRIO0~RTL8306_PRIO3;<nl>
+ *      action could be RTL8306_ACT_DROP/RTL8306_ACT_PERMIT/RTL8306_ACT_TRAPCPU/RTL8306_ACT_MIRROR;<nl>
+ */
+
+rtk_api_ret_t rtk_filter_igrAcl_rule_add(rtk_filter_rule_t *pRule)
+{
+    uint32 entaddr;
+    uint32 port, pro, val, pri, act;  
+    uint32 isFull ;
+
+    if(NULL == pRule)
+        return RT_ERR_NULL_POINTER;
+    
+    isFull = TRUE;
+    
+    /*if  exist an  acl entry of the same rule according by phyport, protocol,data,
+     *only update priority and action
+     */
+    for (entaddr = 0; entaddr < RTL8306_ACL_ENTRYNUM; entaddr ++ ) 
+    {
+        if (rtl8306e_acl_entry_get(entaddr, &port, &act, &pro, &val, &pri) != SUCCESS)
+            return RT_ERR_FAILED;
+
+        if ((pRule->phyport == port) && (pRule->protocol == pro) && (pRule->data == val)) 
+        {
+            if (rtl8306e_acl_entry_set(entaddr, pRule->phyport, pRule->action, pRule->protocol, pRule->data, pRule->priority) != SUCCESS )
+                 return RT_ERR_FAILED;
+            else
+                 return RT_ERR_OK;
+        }            
+    }    
+
+    /*if not exist the rule, find an invalid entry to write it , else return table full */
+    for (entaddr = 0; entaddr < RTL8306_ACL_ENTRYNUM; entaddr ++ )
+    {
+        if (rtl8306e_acl_entry_get(entaddr, &port, &act, &pro, &val, &pri) != SUCCESS)
+            return RT_ERR_FAILED;
+        
+        if (port == RTL8306_ACL_INVALID) 
+        {
+            if (rtl8306e_acl_entry_set(entaddr, pRule->phyport, pRule->action, pRule->protocol, pRule->data, pRule->priority) != SUCCESS)
+                 return RT_ERR_FAILED;
+            else 
+            {
+                isFull = FALSE;
+                break;
+             }                        
+        }            
+    }    
+
+    if (isFull)
+        return RT_ERR_TBL_FULL;
+    else
+        return SUCCESS;
+
+
+   
+}
+
+
+/* Function Name:
+ *      rtk_filter_igrAcl_rule_get
+ * Description:
+ *      Get ACL rule priority and action 
+ * Input:
+ *      pRule    -  the pointer of rule structure
+ * Output:
+ *      pRule    -  the pointer of rule structure
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ * Note:
+ *      The API add an  ACL rule. <nl>
+ *      phyport could be  0~5: port number,  RTL8306_ACL_ANYPORT: any port;<nl>
+ *      protocol could be RTL8306_ACL_ETHER(ether type), RTL8306_ACL_TCP(TCP), RTL8306_ACL_UDP(UDP), RTL8306_ACL_TCPUDP(TCP or UDP);<nl>
+ *      prority could be RTL8306_PRIO0~RTL8306_PRIO3;<nl>
+ *      action could be RTL8306_ACT_DROP/RTL8306_ACT_PERMIT/RTL8306_ACT_TRAPCPU/RTL8306_ACT_MIRROR;<nl>
+ */
+rtk_api_ret_t rtk_filter_igrAcl_rule_get(rtk_filter_rule_t *pRule)
+{
+    uint32 entaddr;
+    uint32 port, pro, val, pri, act;  
+
+
+    if(NULL == pRule)
+        return RT_ERR_NULL_POINTER;
+
+    /*if  exist an  acl entry of the same rule according by phyport, protocol,data,
+     *get the priority and action
+     */
+    for (entaddr = 0; entaddr < RTL8306_ACL_ENTRYNUM; entaddr ++ ) 
+    {
+        if (rtl8306e_acl_entry_get(entaddr, &port, &act, &pro, &val, &pri) != SUCCESS)
+            return RT_ERR_FAILED;
+
+        if ((pRule->phyport == port) && (pRule->protocol == pro) && (pRule->data == val)) 
+        {
+                 pRule->priority = pri;
+                 pRule->action = act;
+                 return RT_ERR_OK;
+        }            
+    }    
+
+    return RT_ERR_FAILED;
+}
+
+/* Function Name:
+ *      rtk_filter_igrAcl_rule_del
+ * Description:
+ *      Delete an acl rule into acl table
+ * Input:
+ *      pRule    -  the pointer of rule structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_INPUT
+ *      RT_ERR_NULL_POINTER
+ * Note:
+ *      The API delete an  ACL rule. <nl>
+ *      only phyport/protocol/data field in pRule needs to be specified.
+ */
+rtk_api_ret_t rtk_filter_igrAcl_rule_del(rtk_filter_rule_t *pRule)
+{
+    uint32 entaddr;
+    uint32 port, pro, val, pri, act;  
+    uint32 isHit;
+
+    if(NULL == pRule)
+        return RT_ERR_NULL_POINTER;
+    
+    isHit = FALSE;
+    
+    if (pRule->phyport == RTL8306_ACL_INVALID)
+        return RT_ERR_INPUT;
+    
+    for (entaddr = 0; entaddr < RTL8306_ACL_ENTRYNUM; entaddr ++ ) 
+    {
+        if (rtl8306e_acl_entry_get(entaddr, &port, &act, &pro, &val, &pri) != SUCCESS)
+            return RT_ERR_FAILED;
+        
+        if ((port == pRule->phyport) && (pro == pRule->protocol) && (val == pRule->data))
+        {
+            if (rtl8306e_acl_entry_set(entaddr, RTL8306_ACL_INVALID, RTL8306_ACT_DROP, RTL8306_ACL_ETHER, 0, 0) != SUCCESS)
+                return RT_ERR_FAILED;
+            isHit = TRUE;
+            break;
+        }                
+    }
+
+    if (isHit)
+        return RT_ERR_OK;
+    else
+        return RT_ERR_INPUT;
+    
+
+
+}
+
+/*add at 2012-2-13*/
+rtk_api_ret_t rtk_mib_get(rtk_port_t port, rtk_mib_counter_t counter, rtk_mib_cntValue_t *pValue)
+{
+     rtk_api_ret_t retVal;
+
+     if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+     if (counter >= MIB_CNT_END)
+        return RT_ERR_INPUT;
+     if (NULL == pValue)
+        return RT_ERR_NULL_POINTER;
+
+     if ((retVal = rtl8306e_mib_get(port, counter, pValue)) != SUCCESS)
+        return RT_ERR_FAILED;
+
+     return RT_ERR_OK;
+}
+
+rtk_api_ret_t rtk_mib_cntType_set(rtk_port_t port, rtk_mib_counter_t counter, rtk_mib_cntType_t type)
+{ 
+
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+    if (counter >= MIB_CNT_END)
+        return RT_ERR_INPUT;
+    if (type >= MIB_COUNTER_TYPE_END)
+        return RT_ERR_INPUT;
+
+    if (MIB_COUNTER_TYPE_BYTE == type)
+        rtl8306e_mibUnit_set(port, counter, RTL8306_MIB_BYTE);
+    else if (MIB_COUNTER_TYPE_PKT == type)
+        rtl8306e_mibUnit_set(port, counter, RTL8306_MIB_PKT);
+    
+    return RT_ERR_OK;
+}
+
+rtk_api_ret_t rtk_mib_cntType_get(rtk_port_t port, rtk_mib_counter_t counter, rtk_mib_cntType_t *pType)
+{
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID;
+    if (counter >= MIB_CNT_END)
+        return RT_ERR_INPUT;
+    if (NULL == pType)
+        return RT_ERR_NULL_POINTER;
+
+    rtl8306e_mibUnit_get(port, counter, pType);
+
+    return RT_ERR_OK;
+}
+
+rtk_api_ret_t rtk_mib_reset(rtk_port_t port)
+{
+    if (port > RTK_PORT_ID_MAX)
+        return RT_ERR_PORT_ID; 
+
+    rtl8306e_mib_reset(port);
+
+    return RT_ERR_OK;
+}
+
+
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api.h
new file mode 100644
index 0000000..7fc6286
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api.h
@@ -0,0 +1,1290 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 26789 $ 
+* $Date: 2012-02-21 09:13:30 +0800 (星期二, 2012-02-21) $
+*
+* Purpose : realtek common API header file
+*
+* Feature :  This file consists of following modules:
+*                
+*
+*/
+
+#ifndef __RTK_API_H__
+#define __RTK_API_H__
+
+
+/*
+ * Include Files
+ */
+#include "rtl8306e_types.h"
+#include "rtl8306e_asicdrv.h"
+#include "rtk_error.h"
+
+/*
+ * Data Type Declaration
+ */
+#define ENABLE                                                    1
+#define DISABLE                                                   0
+
+#define PHY_CONTROL_REG                                   0
+#define PHY_STATUS_REG                                      1
+#define PHY_AN_ADVERTISEMENT_REG                    4
+#define PHY_AN_LINKPARTNER_REG                        5
+#define PHY_1000_BASET_CONTROL_REG                9
+#define PHY_1000_BASET_STATUS_REG                   10
+#define PHY_RESOLVED_REG                                   17
+
+/*Qos related configuration define*/
+#define QOS_DEFAULT_TICK_PERIOD                     (19-1)
+#define QOS_DEFAULT_BYTE_PER_TOKEN                  34
+#define QOS_DEFAULT_LK_THRESHOLD                    (34*3) /* Why use 0x400? */
+
+
+#define QOS_DEFAULT_INGRESS_BANDWIDTH               0x3FFF /* 0x3FFF => unlimit */
+#define QOS_DEFAULT_EGRESS_BANDWIDTH                0x3D08 /*( 0x3D08 + 1) * 64Kbps => 1Gbps*/
+#define QOS_DEFAULT_PREIFP                          1
+#define QOS_DEFAULT_PACKET_USED_PAGES_FC            0x60
+#define QOS_DEFAULT_PACKET_USED_FC_EN               0
+#define QOS_DEFAULT_QUEUE_BASED_FC_EN               1
+
+#define QOS_DEFAULT_PRIORITY_SELECT_PORT            8
+#define QOS_DEFAULT_PRIORITY_SELECT_1Q              0
+#define QOS_DEFAULT_PRIORITY_SELECT_ACL             0
+#define QOS_DEFAULT_PRIORITY_SELECT_DSCP            0
+
+#define QOS_DEFAULT_DSCP_MAPPING_PRIORITY           0
+
+#define QOS_DEFAULT_1Q_REMARKING_ABILITY             0
+#define QOS_DEFAULT_DSCP_REMARKING_ABILITY          0
+#define QOS_DEFAULT_QUEUE_GAP                                20
+#define QOS_DEFAULT_QUEUE_NO_MAX                          6
+#define QOS_DEFAULT_AVERAGE_PACKET_RATE             0x3FFF
+#define QOS_DEFAULT_BURST_SIZE_IN_APR                   0x3F
+#define QOS_DEFAULT_PEAK_PACKET_RATE                    2
+#define QOS_DEFAULT_SCHEDULER_ABILITY_APR           1     /*disable*/
+#define QOS_DEFAULT_SCHEDULER_ABILITY_PPR           1    /*disable*/
+#define QOS_DEFAULT_SCHEDULER_ABILITY_WFQ          1    /*disable*/
+
+#define QOS_WEIGHT_MAX                              128
+
+#define LED_GROUP_MAX                               3
+
+#define RTK_FILTER_RAW_FIELD_NUMBEER                8
+
+#define ACL_DEFAULT_ABILITY                         0
+#define ACL_DEFAULT_UNMATCH_PERMIT                  1
+
+#define ACL_RULE_FREE                               0
+#define ACL_RULE_INAVAILABLE                        1
+
+#define FILTER_POLICING_MAX                         8
+#define FILTER_LOGGING_MAX                          8
+#define FILTER_PATTERN_MAX                          4
+
+#define STORM_UNUC_INDEX                            39
+#define STORM_UNMC_INDEX                            47
+#define STORM_MC_INDEX                              55
+#define STORM_BC_INDEX                              63
+
+#define RTK_MAX_NUM_OF_INTERRUPT_TYPE               1
+#define RTK_TOTAL_NUM_OF_WORD_FOR_1BIT_PORT_LIST    1
+#define RTK_MAX_NUM_OF_PRIORITY                    4
+#define RTK_MAX_NUM_OF_QUEUE                        4
+#define RTK_MAX_NUM_OF_TRUNK_HASH_VAL               1
+#define RTK_MAX_NUM_OF_PORT                         6
+#define RTK_PORT_ID_MAX                             (RTK_MAX_NUM_OF_PORT-1)
+#define RTK_PHY_ID_MAX                             (RTK_MAX_NUM_OF_PORT-1)
+#define RTK_MAX_NUM_OF_PROTO_TYPE                   0xFFFF
+#define RTK_MAX_NUM_OF_MSTI                         0xF
+#define RTK_MAX_NUM_OF_LEARN_LIMIT                  0x1F
+#define RTK_MAX_PORT_MASK                             0x3F
+
+#define RTK_FLOWCTRL_PAUSE_ALL                      1980
+#define RTK_FLOWCTRL_DROP_ALL                       2012
+#define RTK_FLOWCTRL_PAUSE_SYSTEM_ON                1200
+#define RTK_FLOWCTRL_PAUSE_SYSTEM_OFF               1000
+#define RTK_FLOWCTRL_DROP_SYSTEM_ON                 1200
+#define RTK_FLOWCTRL_DROP_SYSTEM_OFF                1000
+#define RTK_FLOWCTRL_PAUSE_SHARE_ON                 216
+#define RTK_FLOWCTRL_PAUSE_SHARE_OFF                208
+#define RTK_FLOWCTRL_DROP_SHARE_ON                  216
+#define RTK_FLOWCTRL_DROP_SHARE_OFF                 208
+#define RTK_FLOWCTRL_PAUSE_PORT_ON                  140
+#define RTK_FLOWCTRL_PAUSE_PORT_OFF                 132
+#define RTK_FLOWCTRL_DROP_PORT_ON                   140
+#define RTK_FLOWCTRL_DROP_PORT_OFF                  132
+#define RTK_FLOWCTRL_PAUSE_PORT_PRIVATE_ON          26
+#define RTK_FLOWCTRL_PAUSE_PORT_PRIVATE_OFF         22
+#define RTK_FLOWCTRL_DROP_PORT_PRIVATE_ON           26
+#define RTK_FLOWCTRL_DROP_PORT_PRIVATE_OFF          22
+#define RTK_FLOWCTRL_PORT_DROP_EGRESS               210
+#define RTK_FLOWCTRL_QUEUE_DROP_EGRESS              2047
+#define RTK_FLOWCTRL_PORT_GAP                       72
+#define RTK_FLOWCTRL_QUEUE_GAP                      18
+
+#define RTK_WHOLE_SYSTEM                            0xFF
+
+#define RTK_EXT_0                                   0
+#define RTK_EXT_1                                   1
+
+#define RTK_EXT_0_MAC                               9
+#define RTK_EXT_1_MAC                               8
+
+#ifndef MAC_ADDR_LEN
+#define MAC_ADDR_LEN                                6
+#endif
+
+#define IPV6_ADDR_LEN                               16
+#define IPV4_ADDR_LEN                               4
+
+#define RTK_DOT_1AS_TIMESTAMP_UNIT_IN_WORD_LENGTH   3UL
+
+#define RTK_IPV6_ADDR_WORD_LENGTH                   4UL
+
+#define ALLPORT 0xFF
+
+typedef enum rtk_chip_mode_e
+{
+    CHIP_8367 = 0,
+    CHIP_8370,
+    CHIP_8370M,
+    CHIP_8376, 
+    CHIP_8218, 
+    CHIP_8306E,
+    CHIP_END
+}rtk_chip_mode_t;
+
+typedef enum rtk_cpu_insert_e
+{
+    CPU_INSERT_TO_ALL = 0,
+    CPU_INSERT_TO_TRAPPING,
+    CPU_INSERT_TO_NONE,
+    CPU_INSERT_END
+}rtk_cpu_insert_t;
+
+typedef enum rtk_cpu_position_e
+{
+    CPU_POS_ATTER_DA = 0,
+    CPU_POS_AFTER_CRC,
+    CPU_POS_END
+}rtk_cpu_position_t;
+
+
+/* Type of port-based dot1x auth/unauth*/
+typedef enum rtk_dot1x_auth_status_e
+{
+    UNAUTH = 0,
+    AUTH,
+    AUTH_STATUS_END
+} rtk_dot1x_auth_status_t;
+
+typedef enum rtk_dot1x_direction_e
+{
+    BOTH = 0,
+    IN,
+    DIRECTION_END
+} rtk_dot1x_direction_t;
+
+typedef enum rtk_mode_ext_e
+{
+    MODE_EXT_DISABLE = 0,
+    MODE_EXT_RGMII,
+    MODE_EXT_MII_MAC,
+    MODE_EXT_MII_PHY, 
+    MODE_EXT_TMII_MAC,
+    MODE_EXT_TMII_PHY, 
+    MODE_EXT_GMII,
+    MODE_EXT_RMII,
+    MODE_EXT_END
+} rtk_mode_ext_t;
+
+typedef struct
+{
+    uint32 value[RTK_DOT_1AS_TIMESTAMP_UNIT_IN_WORD_LENGTH];
+} rtk_filter_dot1as_timestamp_t;
+
+/* unauth pkt action */
+typedef enum rtk_dot1x_unauth_action_e
+{
+    DOT1X_ACTION_DROP = 0,
+    DOT1X_ACTION_TRAP2CPU,
+    DOT1X_ACTION_GUESTVLAN,
+    DOT1X_ACTION_END
+} rtk_dot1x_unauth_action_t;
+
+typedef uint32  rtk_dscp_t;         /* dscp vlaue */
+
+typedef enum rtk_enable_e
+{
+    DISABLED = 0,
+    ENABLED,
+    RTK_ENABLE_END
+} rtk_enable_t;
+
+typedef uint32  rtk_fid_t;        /* filter id type */
+
+/* ethernet address type */
+typedef struct  rtk_mac_s
+{
+    uint8 octet[ETHER_ADDR_LEN];
+} rtk_mac_t;
+
+typedef enum rtk_filter_act_enable_e
+{
+    /* CVLAN */
+    FILTER_ENACT_INGRESS_CVLAN_INDEX = 0,
+    FILTER_ENACT_INGRESS_CVLAN_VID,
+
+    /* SVLAN */
+    FILTER_ENACT_EGRESS_SVLAN_INDEX,
+
+    /* Policing and Logging */
+    FILTER_ENACT_POLICING_0,   
+
+    /* Forward */
+    FILTER_ENACT_TRAP_CPU,
+    FILTER_ENACT_COPY_CPU,
+    FILTER_ENACT_REDIRECT,
+    FILTER_ENACT_DROP,    
+    FILTER_ENACT_MIRROR,    
+    FILTER_ENACT_ADD_DSTPORT,    
+
+    /* QoS */
+    FILTER_ENACT_PRIORITY,
+
+    FILTER_ENACT_MAX
+} rtk_filter_act_enable_t;
+
+typedef struct
+{
+    rtk_filter_act_enable_t actEnable[FILTER_ENACT_MAX];
+
+    /* CVLAN acton */
+    uint32        filterIngressCvlanIdx;
+    uint32        filterIngressCvlanVid;
+
+    /* SVLAN action */
+    uint32        filterEgressSvlanIdx; 
+
+    /* Policing action */
+    uint32        filterPolicingIdx[FILTER_POLICING_MAX];
+
+    /* Forwarding action */
+    uint32        filterRedirectPortmask;
+    uint32        filterAddDstPortmask;  
+    
+    /* QOS action */
+    uint32        filterPriority;    
+} rtk_filter_action_t;
+
+typedef struct
+{
+    uint32 value;
+    uint32 mask;
+} rtk_filter_flag_t;
+
+typedef enum rtk_filter_care_tag_index_e
+{
+    CARE_TAG_CTAG = 0,
+    CARE_TAG_STAG,
+    CARE_TAG_PPPOE,
+    CARE_TAG_IPV4,
+    CARE_TAG_IPV6,
+    CARE_TAG_TCP,
+    CARE_TAG_UDP,    
+    CARE_TAG_ICMP,    
+    CARE_TAG_IGMP,    
+    CARE_TAG_MAX
+} rtk_filter_care_tag_index_t;
+
+typedef struct
+{
+    rtk_filter_flag_t tagType[CARE_TAG_MAX];
+} rtk_filter_care_tag_t;
+
+typedef struct rtk_filter_field rtk_filter_field_t;
+
+typedef enum rtk_filter_field_data_type_e
+{
+    FILTER_FIELD_DATA_MASK = 0,
+    FILTER_FIELD_DATA_RANGE,        
+    FILTER_FIELD_DATA_MAX
+} rtk_filter_field_data_type;
+
+typedef struct
+{
+    uint32 dataType;
+    uint32 rangeStart;
+    uint32 rangeEnd;
+    uint32 value;
+    uint32 mask;
+} rtk_filter_ip_t;
+
+typedef struct
+{
+    uint32 dataType;
+    rtk_mac_t value;
+    rtk_mac_t mask;
+    rtk_mac_t rangeStart;
+    rtk_mac_t rangeEnd;
+} rtk_filter_mac_t;
+
+typedef uint32 rtk_filter_op_t;
+
+typedef struct rtk_filter_value_s
+{
+    uint32 dataType;
+    uint32 value;
+    uint32 mask;
+    uint32 rangeStart;
+    uint32 rangeEnd;
+} rtk_filter_value_t;
+
+typedef struct rtk_filter_tag_s
+{
+    rtk_filter_value_t pri;
+    rtk_filter_flag_t cfi;
+    rtk_filter_value_t vid;
+} rtk_filter_tag_t;
+
+typedef struct
+{
+    rtk_filter_flag_t mf;
+    rtk_filter_flag_t df;
+} rtk_filter_ipFlag_t;
+
+typedef struct
+{
+    uint32 addr[RTK_IPV6_ADDR_WORD_LENGTH];
+} rtk_filter_ip6_addr_t;
+
+typedef struct
+{
+    uint32 dataType;
+    rtk_filter_ip6_addr_t value;
+    rtk_filter_ip6_addr_t mask;
+    rtk_filter_ip6_addr_t rangeStart;
+    rtk_filter_ip6_addr_t rangeEnd;
+} rtk_filter_ip6_t;
+
+typedef uint32 rtk_filter_number_t;
+
+typedef struct
+{
+    uint32 value[FILTER_PATTERN_MAX];
+    uint32 mask[FILTER_PATTERN_MAX];
+} rtk_filter_pattern_t;
+
+typedef struct
+{
+    rtk_filter_flag_t urg;
+    rtk_filter_flag_t ack;
+    rtk_filter_flag_t psh;
+    rtk_filter_flag_t rst;
+    rtk_filter_flag_t syn;
+    rtk_filter_flag_t fin;
+    rtk_filter_flag_t ns;
+    rtk_filter_flag_t cwr;
+    rtk_filter_flag_t ece;    
+} rtk_filter_tcpFlag_t;
+
+typedef uint32 rtk_filter_field_raw_t;
+
+struct rtk_filter_field
+{
+    uint32 fieldType;
+    
+    union
+    {
+        /* L2 struct */
+        rtk_filter_mac_t       dmac;
+        rtk_filter_mac_t       smac;
+        rtk_filter_value_t     etherType;
+        rtk_filter_tag_t       ctag;
+        rtk_filter_tag_t       relayCtag;
+        rtk_filter_tag_t       stag;
+        rtk_filter_dot1as_timestamp_t dot1asTimeStamp;
+        
+        /* L3 struct */
+        rtk_filter_ip_t      sip;
+        rtk_filter_ip_t      dip;
+        rtk_filter_value_t   protocol;
+        rtk_filter_value_t   ipTos;
+        rtk_filter_ipFlag_t  ipFlag;
+        rtk_filter_value_t   ipOffset;
+        rtk_filter_ip6_t     sipv6;
+        rtk_filter_ip6_t     dipv6;
+        rtk_filter_value_t   ipv6TrafficClass;        
+        rtk_filter_value_t   ipv6NextHeader;
+        rtk_filter_value_t   flowLabel;
+        
+        /* L4 struct */
+        rtk_filter_value_t   tcpSrcPort;
+        rtk_filter_value_t   tcpDstPort;
+        rtk_filter_tcpFlag_t tcpFlag;
+        rtk_filter_value_t   tcpSeqNumber;
+        rtk_filter_value_t   tcpAckNumber;
+        rtk_filter_value_t   udpSrcPort;
+        rtk_filter_value_t   udpDatcPort;
+        rtk_filter_value_t   icmpCode;
+        rtk_filter_value_t   icmpType;
+        rtk_filter_value_t   igmpType;
+
+        /* pattern match */
+        rtk_filter_pattern_t pattern;
+    } filter_pattern_union;
+
+    struct rtk_filter_field *next;
+};
+
+typedef enum rtk_filter_field_type_e
+{
+    FILTER_FIELD_DMAC = 0,
+    FILTER_FIELD_SMAC,
+    FILTER_FIELD_ETHERTYPE,
+    FILTER_FIELD_CTAG,
+    FILTER_FIELD_STAG, 
+    
+    FILTER_FIELD_IPV4_SIP,
+    FILTER_FIELD_IPV4_DIP,
+    FILTER_FIELD_IPV4_TOS,
+    FILTER_FIELD_IPV4_PROTOCOL,
+    FILTER_FIELD_IPV4_FLAG,
+    FILTER_FIELD_IPV4_OFFSET,
+    FILTER_FIELD_IPV6_SIPV6,
+    FILTER_FIELD_IPV6_DIPV6,
+    FILTER_FIELD_IPV6_TRAFFIC_CLASS,
+    FILTER_FIELD_IPV6_NEXT_HEADER,
+    
+    FILTER_FIELD_TCP_SPORT,
+    FILTER_FIELD_TCP_DPORT,
+    FILTER_FIELD_TCP_FLAG,
+    FILTER_FIELD_UDP_SPORT,
+    FILTER_FIELD_UDP_DPORT,
+    FILTER_FIELD_ICMP_CODE,
+    FILTER_FIELD_ICMP_TYPE,
+    FILTER_FIELD_IGMP_TYPE,
+    FILTER_FIELD_MAX
+} rtk_filter_field_type_t;
+
+typedef enum rtk_filter_field_type_raw_e
+{
+    FILTER_FIELD_RAW_DMAC_47_32 = 0,
+    FILTER_FIELD_RAW_DMAC_31_16,
+    FILTER_FIELD_RAW_DMAC_15_0,    
+    FILTER_FIELD_RAW_SMAC_47_32 = 0,
+    FILTER_FIELD_RAW_SMAC_31_16,
+    FILTER_FIELD_RAW_SMAC_15_0,    
+    FILTER_FIELD_RAW_ETHERTYPE,
+    FILTER_FIELD_RAW_CTAG,
+    FILTER_FIELD_RAW_STAG, 
+    
+    FILTER_FIELD_RAW_IPV4_SIP_31_16,
+    FILTER_FIELD_RAW_IPV4_SIP_15_0,    
+    FILTER_FIELD_RAW_IPV4_DIP_31_16,
+    FILTER_FIELD_RAW_IPV4_DIP_15_0,    
+    FILTER_FIELD_RAW_IPV4_TOS_PROTOCOL,
+    FILTER_FIELD_RAW_IPV4_FLAG_OFFSET,
+    FILTER_FIELD_RAW_IPV6_SIP_127_112,
+    FILTER_FIELD_RAW_IPV6_SIP_111_96,    
+    FILTER_FIELD_RAW_IPV6_SIP_95_80,    
+    FILTER_FIELD_RAW_IPV6_SIP_79_64,
+    FILTER_FIELD_RAW_IPV6_SIP_63_48,
+    FILTER_FIELD_RAW_IPV6_SIP_47_32,
+    FILTER_FIELD_RAW_IPV6_SIP_31_16,
+    FILTER_FIELD_RAW_IPV6_SIP_15_0,
+    FILTER_FIELD_RAW_IPV6_DIP_127_112,
+    FILTER_FIELD_RAW_IPV6_DIP_111_96,    
+    FILTER_FIELD_RAW_IPV6_DIP_95_80,    
+    FILTER_FIELD_RAW_IPV6_DIP_79_64,
+    FILTER_FIELD_RAW_IPV6_DIP_63_48,
+    FILTER_FIELD_RAW_IPV6_DIP_47_32,
+    FILTER_FIELD_RAW_IPV6_DIP_31_16,
+    FILTER_FIELD_RAW_IPV6_DIP_15_0,
+    FILTER_FIELD_RAW_IPV6_TRAFFIC_CLASS_NEXT_HEADER,
+    
+    FILTER_FIELD_RAW_L4_SPORT,
+    FILTER_FIELD_RAW_L4_DPORT,
+    FILTER_FIELD_RAW_TCP_FLAG,
+    FILTER_FIELD_RAW_ICMP_CODE_TYPE,
+    FILTER_FIELD_RAW_IGMP_TYPE,
+    FILTER_FIELD_RAW_MAX
+} rtk_filter_field_type_raw_t;
+
+
+typedef enum rtk_filter_flag_care_type_e
+{
+    FILTER_FLAG_CARE_DONT_CARE = 0,
+    FILTER_FLAG_CARE_1,
+    FILTER_FLAG_CARE_0,
+    FILTER_FLAG_END
+} rtk_filter_flag_care_type_t;
+
+typedef uint32  rtk_filter_id_t;    /* filter id type */
+
+typedef enum rtk_filter_invert_e
+{
+    FILTER_INVERT_DISABLE = 0,
+    FILTER_INVERT_ENABLE,
+    FILTER_INVERT_END
+} rtk_filter_invert_t;
+
+typedef uint32 rtk_filter_port_t;
+
+typedef uint32 rtk_filter_state_t;
+
+typedef uint32 rtk_filter_unmatch_action_t;
+
+typedef enum rtk_filter_unmatch_action_e
+{
+    FILTER_UNMATCH_DROP = 0,
+    FILTER_UNMATCH_PERMIT,
+    FILTER_UNMATCH_END
+} rtk_filter_unmatch_action_type_t;
+
+typedef struct
+{
+    rtk_filter_field_t      *fieldHead;
+    rtk_filter_care_tag_t   careTag;
+    rtk_filter_value_t      activeport;
+
+    rtk_filter_invert_t     invert;
+} rtk_filter_cfg_t;
+
+typedef struct
+{
+    rtk_filter_field_raw_t      dataFieldRaw[RTK_FILTER_RAW_FIELD_NUMBEER];     
+    rtk_filter_field_raw_t      careFieldRaw[RTK_FILTER_RAW_FIELD_NUMBEER];
+    rtk_filter_field_type_raw_t fieldRawType[RTK_FILTER_RAW_FIELD_NUMBEER];
+    rtk_filter_care_tag_t       careTag;
+    rtk_filter_value_t          activeport;
+    rtk_filter_invert_t         invert;
+    rtk_enable_t                valid;
+} rtk_filter_cfg_raw_t;
+
+typedef enum rtk_igmp_type_e
+{
+    IGMP_IPV4 = 0,
+    IGMP_PPPOE_IPV4,
+    IGMP_MLD,
+    IGMP_PPPOE_MLD,
+    IGMP_TYPE_END
+} rtk_igmp_type_t;
+
+typedef uint32 rtk_int_info_t;
+
+typedef enum rtk_int_interrupt_type_e
+{
+    INT_TYPE_LINK_STATUS = 0,
+    INT_TYPE_METER_EXCEED,
+    INT_TYPE_LEARN_LIMIT,    
+    INT_TYPE_LINK_SPEED,
+    INT_TYPE_CONGEST,
+    INT_TYPE_GREEN_FEATURE,
+    INT_TYPE_LOOP_DETECT,
+    INT_TYPE_8051,
+    INT_TYPE_END
+}rtk_int_interrupt_type_t;
+
+typedef enum rtk_int_advType_e
+{
+    ADV_L2_LEARN_PORT_MASK = 0,
+    ADV_SPEED_CHANGE_PORT_MASK,
+    ADV_SPECIAL_CONGESTION_PORT_MASK,
+    ADV_PORT_LINKDOWN_PORT_MASK,
+    ADV_PORT_LINKUP_PORT_MASK,
+    ADV_METER0_15_MASK,
+    ADV_METER16_31_MASK,
+    ADV_METER32_47,_MASK,
+    ADV_METER48_63_MASK,
+    ADV_END
+} rtk_int_advType_t;
+
+typedef enum rtk_int_polarity_e
+{
+    INT_POLAR_HIGH = 0,
+    INT_POLAR_LOW,
+    INT_POLAR_END
+} rtk_int_polarity_t;
+
+typedef struct  rtk_int_status_s
+{
+    uint8 value[RTK_MAX_NUM_OF_INTERRUPT_TYPE];
+} rtk_int_status_t;
+
+typedef enum rtk_int_type_e
+{
+    INT_LINK_CHANGE = 0,
+    INT_SPEED_CHANGE,
+    INT_RLDP,
+    INT_METER,
+    INT_LEARN_LIMIT,
+    INT_END
+} rtk_int_type_t;
+
+typedef uint32 rtk_ipaddr_t;
+
+typedef enum rtk_l2_age_time_e
+{
+    AGE_TIME_300S= 0,
+    AGE_TIME_2,
+    AGE_TIME_3,
+    AGE_TIME_4,
+    AGE_TIME_END
+} rtk_l2_age_time_t;
+
+typedef enum rtk_l2_flood_type_e
+{
+    FLOOD_UNKNOWNDA = 0,
+    FLOOD_UNKNOWNMC,
+    FLOOD_BC,
+    FLOOD_END
+} rtk_l2_flood_type_t;
+
+typedef uint32 rtk_l2_flushItem_t;
+
+typedef enum rtk_l2_flushType_e
+{
+    FLUSH_TYPE_BY_PORT = 0,       /* physical port       */
+    FLUSH_TYPE_END
+} rtk_l2_flushType_t;
+
+
+typedef enum rtk_l2_hash_method_e
+{
+    HSAH_OPT0 = 0,
+    HASH_OPT1,
+    HASH_END
+} rtk_hash_method_t;
+
+/* l2 limit learning count action */
+typedef enum rtk_l2_limitLearnCntAction_e
+{
+    LIMIT_LEARN_CNT_ACTION_DROP = 0,
+    LIMIT_LEARN_CNT_ACTION_FLOOD,
+    LIMIT_LEARN_CNT_ACTION_TO_CPU,
+    LIMIT_LEARN_CNT_ACTION_END
+} rtk_l2_limitLearnCntAction_t;
+
+typedef enum rtk_l2_lookup_type_e
+{
+    LOOKUP_MAC = 0,
+    LOOKUP_SIP_DIP,
+    LOOKUP_DIP,  
+    LOOKUP_END
+} rtk_l2_lookup_type_t;
+
+/* l2 address table - unicast data structure */
+typedef struct rtk_l2_ucastAddr_s
+{
+    rtk_mac_t   mac;
+    uint32        fid;
+    uint32        port;
+    uint32        sa_block;
+    uint32        auth;
+    uint32        is_static;
+}rtk_l2_ucastAddr_t;
+
+
+typedef enum rtk_leaky_type_e
+{
+    LEAKY_BRG_GROUP = 0,
+    LEAKY_FD_PAUSE,
+    LEAKY_SP_MCAST,
+    LEAKY_1X_PAE,
+    LEAKY_UNDEF_BRG_04,
+    LEAKY_UNDEF_BRG_05,
+    LEAKY_UNDEF_BRG_06,
+    LEAKY_UNDEF_BRG_07,    
+    LEAKY_PROVIDER_BRIDGE_GROUP_ADDRESS,
+    LEAKY_UNDEF_BRG_09,
+    LEAKY_UNDEF_BRG_0A,
+    LEAKY_UNDEF_BRG_0B,
+    LEAKY_UNDEF_BRG_0C,    
+    LEAKY_PROVIDER_BRIDGE_GVRP_ADDRESS,    
+    LEAKY_8021AB,
+    LEAKY_UNDEF_BRG_0F,    
+    LEAKY_BRG_MNGEMENT,
+    LEAKY_UNDEFINED_11,
+    LEAKY_UNDEFINED_12,
+    LEAKY_UNDEFINED_13,
+    LEAKY_UNDEFINED_14,
+    LEAKY_UNDEFINED_15,
+    LEAKY_UNDEFINED_16,
+    LEAKY_UNDEFINED_17,
+    LEAKY_UNDEFINED_18,
+    LEAKY_UNDEFINED_19,
+    LEAKY_UNDEFINED_1A,
+    LEAKY_UNDEFINED_1B,
+    LEAKY_UNDEFINED_1C,
+    LEAKY_UNDEFINED_1D,
+    LEAKY_UNDEFINED_1E,
+    LEAKY_UNDEFINED_1F,
+    LEAKY_GMRP,
+    LEAKY_GVRP,
+    LEAKY_UNDEF_GARP_22,
+    LEAKY_UNDEF_GARP_23,
+    LEAKY_UNDEF_GARP_24,
+    LEAKY_UNDEF_GARP_25,
+    LEAKY_UNDEF_GARP_26,
+    LEAKY_UNDEF_GARP_27,
+    LEAKY_UNDEF_GARP_28,
+    LEAKY_UNDEF_GARP_29,
+    LEAKY_UNDEF_GARP_2A,
+    LEAKY_UNDEF_GARP_2B,
+    LEAKY_UNDEF_GARP_2C,
+    LEAKY_UNDEF_GARP_2D,
+    LEAKY_UNDEF_GARP_2E,
+    LEAKY_UNDEF_GARP_2F,
+    LEAKY_IGMP,
+    LEAKY_IPMULTICAST,
+    LEAKY_END
+}rtk_leaky_type_t;
+
+typedef enum rtk_led_blink_rate_e
+{
+    LED_BLINKRATE_32MS=0,         
+    LED_BLINKRATE_64MS,        
+    LED_BLINKRATE_128MS,
+    LED_BLINKRATE_256MS,
+    LED_BLINKRATE_512MS,
+    LED_BLINKRATE_1024MS,
+    LED_BLINKRATE_48MS,
+    LED_BLINKRATE_96MS,
+    LED_BLINKRATE_END
+}rtk_led_blink_rate_t;
+
+typedef enum rtk_led_group_e
+{
+    LED_GROUP_0 = 0,
+    LED_GROUP_1,
+    LED_GROUP_2,
+    LED_GROUP_END
+}rtk_led_group_t;    
+
+typedef enum rtk_led_mode_e
+{
+    LED_MODE_0 = 0,
+    LED_MODE_1,
+    LED_MODE_2,
+    LED_MODE_3,
+    LED_MODE_END
+}rtk_led_mode_t;    
+
+
+typedef enum rtk_led_force_mode_e
+{
+
+    LED_FORCE_NORMAL=0,
+    LED_FORCE_BLINK,
+    LED_FORCE_OFF,
+    LED_FORCE_ON,
+    LED_FORCE_END
+}rtk_led_force_mode_t;
+
+typedef uint32  rtk_mac_cnt_t;     /* meter id type  */
+
+typedef enum rtk_mcast_type_e
+{
+    MCAST_L2 = 0,
+    MCAST_IPV4,
+    MCAST_IPV6,
+    MCAST_END
+} rtk_mcast_type_t;
+
+typedef uint32  rtk_meter_id_t;     /* meter id type  */
+
+typedef uint32  rtk_mode_t; 
+
+typedef uint32  rtk_port_t;        /* port is type */
+
+typedef enum rtk_port_duplex_e
+{
+    PORT_HALF_DUPLEX = 0,
+    PORT_FULL_DUPLEX,
+    PORT_DUPLEX_END
+} rtk_port_duplex_t;
+
+typedef enum rtk_port_linkStatus_e
+{
+    PORT_LINKDOWN = 0,
+    PORT_LINKUP,
+    PORT_LINKSTATUS_END
+} rtk_port_linkStatus_t;
+
+typedef struct  rtk_port_mac_ability_s
+{
+    uint32 forcemode;
+    uint32 speed;
+    uint32 duplex;
+    uint32 link;    
+    uint32 nway;
+    uint32 symflc;
+    uint32 txpause;
+    uint32 rxpause;      
+}rtk_port_mac_ability_t;
+
+typedef struct rtk_port_phy_ability_s
+{   
+    uint32    AutoNegotiation;  /*PHY register 0.12 setting for auto-negotiation process*/
+    uint32    Half_10;          /*PHY register 4.5 setting for 10BASE-TX half duplex capable*/
+    uint32    Full_10;          /*PHY register 4.6 setting for 10BASE-TX full duplex capable*/
+    uint32    Half_100;         /*PHY register 4.7 setting for 100BASE-TX half duplex capable*/
+    uint32    Full_100;         /*PHY register 4.8 setting for 100BASE-TX full duplex capable*/
+    uint32    Full_1000;        /*PHY register 9.9 setting for 1000BASE-T full duplex capable*/
+    uint32    FC;               /*PHY register 4.10 setting for flow control capability*/
+    uint32    AsyFC;            /*PHY register 4.11 setting for  asymmetric flow control capability*/
+} rtk_port_phy_ability_t;
+
+typedef uint32  rtk_port_phy_data_t;     /* phy page  */
+
+typedef uint32  rtk_port_phy_page_t;     /* phy page  */
+
+typedef enum rtk_port_phy_reg_e  
+{
+    PHY_REG_CONTROL             = 0,
+    PHY_REG_STATUS,
+    PHY_REG_IDENTIFIER_1,
+    PHY_REG_IDENTIFIER_2,
+    PHY_REG_AN_ADVERTISEMENT,
+    PHY_REG_AN_LINKPARTNER,
+    PHY_REG_1000_BASET_CONTROL  = 9,
+    PHY_REG_1000_BASET_STATUS,
+    PHY_REG_END                 = 32
+} rtk_port_phy_reg_t;
+
+typedef enum rtk_port_phy_test_mode_e  
+{
+    PHY_TEST_MODE_NORMAL= 0,
+    PHY_TEST_MODE_1,
+    PHY_TEST_MODE_2,
+    PHY_TEST_MODE_3,
+    PHY_TEST_MODE_4,
+    PHY_TEST_MODE_END           
+} rtk_port_phy_test_mode_t;
+
+typedef enum rtk_port_speed_e
+{
+    PORT_SPEED_10M = 0,
+    PORT_SPEED_100M,
+    PORT_SPEED_1000M,
+    PORT_SPEED_END
+} rtk_port_speed_t;
+
+typedef struct rtk_portmask_s
+{
+    uint32  bits[RTK_TOTAL_NUM_OF_WORD_FOR_1BIT_PORT_LIST];
+} rtk_portmask_t;
+
+typedef uint32  rtk_pri_t;         /*priority value */
+typedef uint32  rtk_dei_t;        /*dei value*/
+
+typedef struct rtk_priority_select_s
+{   
+    uint32 port_pri;
+    uint32 dot1q_pri;
+    uint32 acl_pri;
+    uint32 dscp_pri;
+    uint16 cvlan_pri;
+    uint32 svlan_pri;
+    uint32 dmac_pri;
+    uint32 smac_pri;
+    uint32 vid_pri;
+} rtk_priority_select_t;
+
+
+typedef uint32  rtk_qid_t;        /* queue id type */
+
+typedef struct rtk_qos_pri2queue_s
+{
+    uint32 pri2queue[RTK_MAX_NUM_OF_PRIORITY];
+} rtk_qos_pri2queue_t;
+
+typedef struct rtk_qos_queue_weights_s
+{
+    uint32 weights[RTK_MAX_NUM_OF_QUEUE];
+} rtk_qos_queue_weights_t;
+
+typedef enum rtk_qos_scheduling_type_e
+{
+    WFQ = 0,        /* Weighted-Fair-Queue */
+    WRR,            /* Weighted-Round-Robin */
+    SCHEDULING_TYPE_END
+} rtk_qos_scheduling_type_t;
+
+typedef uint32  rtk_queue_num_t;    /* queue number*/
+
+typedef enum rtk_rate_storm_group_e
+{
+    STORM_GROUP_UNKNOWN_UNICAST = 0,
+    STORM_GROUP_UNKNOWN_MULTICAST,
+    STORM_GROUP_MULTICAST,
+    STORM_GROUP_BROADCAST,
+    STORM_GROUP_END
+} rtk_rate_storm_group_t;
+
+typedef uint32  rtk_rate_t;     /* rate type  */
+
+typedef rtk_u_long_t rtk_stat_counter_t;
+
+#ifndef EMBEDDED_SUPPORT
+/* global statistic counter structure */
+typedef struct rtk_stat_global_cntr_s
+{
+    uint64 dot1dTpLearnedEntryDiscards;
+}rtk_stat_global_cntr_t;
+#endif
+
+typedef enum rtk_stat_global_type_e
+{
+    DOT1D_TP_LEARNED_ENTRY_DISCARDS_INDEX = 36,
+    MIB_GLOBAL_CNTR_END
+}rtk_stat_global_type_t;
+
+#ifndef EMBEDDED_SUPPORT
+/* port statistic counter structure */
+typedef struct rtk_stat_port_cntr_s
+{
+    uint64 ifInOctets;
+    uint32 dot3StatsFCSErrors;
+    uint32 dot3StatsSymbolErrors;
+    uint32 dot3InPauseFrames;
+    uint32 dot3ControlInUnknownOpcodes;
+    uint32 etherStatsFragments;
+    uint32 etherStatsJabbers;
+    uint32 ifInUcastPkts;
+    uint32 etherStatsDropEvents;
+    uint64 etherStatsOctets;
+    uint32 etherStatsUndersizePkts;
+    uint32 etherStatsOversizePkts;
+    uint32 etherStatsPkts64Octets;
+    uint32 etherStatsPkts65to127Octets;
+    uint32 etherStatsPkts128to255Octets;
+    uint32 etherStatsPkts256to511Octets;
+    uint32 etherStatsPkts512to1023Octets;
+    uint32 etherStatsPkts1024toMaxOctets;
+    uint32 etherStatsMcastPkts;
+    uint32 etherStatsBcastPkts;
+    uint64 ifOutOctets;
+    uint32 dot3StatsSingleCollisionFrames;
+    uint32 dot3StatsMultipleCollisionFrames;
+    uint32 dot3StatsDeferredTransmissions;
+    uint32 dot3StatsLateCollisions;
+    uint32 etherStatsCollisions;
+    uint32 dot3StatsExcessiveCollisions;
+    uint32 dot3OutPauseFrames;
+    uint32 dot1dBasePortDelayExceededDiscards;
+    uint32 dot1dTpPortInDiscards;
+    uint32 ifOutUcastPkts;
+    uint32 ifOutMulticastPkts;
+    uint32 ifOutBrocastPkts;
+    uint32 outOampduPkts;
+    uint32 inOampduPkts;
+    uint32 pktgenPkts;
+}rtk_stat_port_cntr_t;
+#endif
+
+/* port statistic counter index */
+typedef enum rtk_stat_port_type_e
+{
+    STAT_IfInOctets = 0,
+    STAT_Dot3StatsFCSErrors,
+    STAT_Dot3StatsSymbolErrors,
+    STAT_Dot3InPauseFrames,
+    STAT_Dot3ControlInUnknownOpcodes,        
+    STAT_EtherStatsFragments,
+    STAT_EtherStatsJabbers,
+    STAT_IfInUcastPkts,
+    STAT_EtherStatsDropEvents,
+    STAT_EtherStatsOctets,
+    STAT_EtherStatsUnderSizePkts,
+    STAT_EtherOversizeStats,
+    STAT_EtherStatsPkts64Octets,
+    STAT_EtherStatsPkts65to127Octets,
+    STAT_EtherStatsPkts128to255Octets,
+    STAT_EtherStatsPkts256to511Octets,
+    STAT_EtherStatsPkts512to1023Octets,
+    STAT_EtherStatsPkts1024to1518Octets,
+    STAT_EtherStatsMulticastPkts,
+    STAT_EtherStatsBroadcastPkts,    
+    STAT_IfOutOctets,
+    STAT_Dot3StatsSingleCollisionFrames,
+    STAT_Dot3StatsMultipleCollisionFrames,
+    STAT_Dot3StatsDeferredTransmissions,
+    STAT_Dot3StatsLateCollisions,
+    STAT_EtherStatsCollisions,
+    STAT_Dot3StatsExcessiveCollisions,
+    STAT_Dot3OutPauseFrames,
+    STAT_Dot1dBasePortDelayExceededDiscards,
+    STAT_Dot1dTpPortInDiscards,
+    STAT_IfOutUcastPkts,
+    STAT_IfOutMulticastPkts,
+    STAT_IfOutBroadcastPkts,
+    STAT_OutOampduPkts,
+    STAT_InOampduPkts,
+    STAT_PktgenPkts,
+    STAT_PORT_CNTR_END
+}rtk_stat_port_type_t;
+
+typedef uint32  rtk_stg_t;        /* spanning tree instance id type */
+
+typedef enum rtk_storm_bypass_e
+{
+    BYPASS_BRG_GROUP = 0,
+    BYPASS_FD_PAUSE,
+    BYPASS_SP_MCAST,
+    BYPASS_1X_PAE,
+    BYPASS_UNDEF_BRG_04,
+    BYPASS_UNDEF_BRG_05,
+    BYPASS_UNDEF_BRG_06,
+    BYPASS_UNDEF_BRG_07,    
+    BYPASS_PROVIDER_BRIDGE_GROUP_ADDRESS,
+    BYPASS_UNDEF_BRG_09,
+    BYPASS_UNDEF_BRG_0A,
+    BYPASS_UNDEF_BRG_0B,
+    BYPASS_UNDEF_BRG_0C,    
+    BYPASS_PROVIDER_BRIDGE_GVRP_ADDRESS,    
+    BYPASS_8021AB,
+    BYPASS_UNDEF_BRG_0F,    
+    BYPASS_BRG_MNGEMENT,
+    BYPASS_UNDEFINED_11,
+    BYPASS_UNDEFINED_12,
+    BYPASS_UNDEFINED_13,
+    BYPASS_UNDEFINED_14,
+    BYPASS_UNDEFINED_15,
+    BYPASS_UNDEFINED_16,
+    BYPASS_UNDEFINED_17,
+    BYPASS_UNDEFINED_18,
+    BYPASS_UNDEFINED_19,
+    BYPASS_UNDEFINED_1A,
+    BYPASS_UNDEFINED_1B,
+    BYPASS_UNDEFINED_1C,
+    BYPASS_UNDEFINED_1D,
+    BYPASS_UNDEFINED_1E,
+    BYPASS_UNDEFINED_1F,
+    BYPASS_GMRP,
+    BYPASS_GVRP,
+    BYPASS_UNDEF_GARP_22,
+    BYPASS_UNDEF_GARP_23,
+    BYPASS_UNDEF_GARP_24,
+    BYPASS_UNDEF_GARP_25,
+    BYPASS_UNDEF_GARP_26,
+    BYPASS_UNDEF_GARP_27,
+    BYPASS_UNDEF_GARP_28,
+    BYPASS_UNDEF_GARP_29,
+    BYPASS_UNDEF_GARP_2A,
+    BYPASS_UNDEF_GARP_2B,
+    BYPASS_UNDEF_GARP_2C,
+    BYPASS_UNDEF_GARP_2D,
+    BYPASS_UNDEF_GARP_2E,
+    BYPASS_UNDEF_GARP_2F,
+    BYPASS_IGMP,
+    BYPASS_END
+}rtk_storm_bypass_t;
+
+typedef uint32  rtk_stp_msti_id_t;     /* MSTI ID  */
+
+typedef enum rtk_stp_state_e
+{
+    STP_STATE_DISABLED = 0,
+    STP_STATE_BLOCKING,
+    STP_STATE_LEARNING,
+    STP_STATE_FORWARDING,
+    STP_STATE_END
+} rtk_stp_state_t;
+
+typedef uint32 rtk_svlan_index_t;
+
+typedef struct rtk_svlan_memberCfg_s{
+    uint32 svid;   
+    uint32 memberport;
+    uint32 fid;
+    uint32 priority;
+    uint32 reserved1;     
+    uint32 reserved2;    
+    uint32 reserved3; 
+    uint32 reserved4;   
+}rtk_svlan_memberCfg_t;
+
+typedef enum rtk_svlan_pri_ref_e
+{
+    REF_INTERNAL_PRI = 0,
+    REF_CTAG_PRI,
+    REF_SVLAN_PRI,
+    REF_PRI_END
+} rtk_svlan_pri_ref_t;
+
+
+typedef uint32 rtk_svlan_tpid_t;
+
+typedef enum rtk_switch_maxPktLen_e
+{
+    MAXPKTLEN_1522B = 0,
+    MAXPKTLEN_1536B,
+    MAXPKTLEN_1552B,
+    MAXPKTLEN_2000B, 
+    MAXPKTLEN_16000B,   
+    MAXPKTLEN_END   
+} rtk_switch_maxPktLen_t;
+
+typedef enum rtk_trap_igmp_action_e
+{
+    IGMP_ACTION_FORWARD = 0,
+    IGMP_ACTION_TRAP2CPU,
+    IGMP_ACTION_DROP,
+    IGMP_ACTION_FORWARD_EXCLUDE_CPU,
+    IGMP_ACTION_END
+} rtk_trap_igmp_action_t;
+
+typedef enum rtk_trap_mcast_action_e
+{
+    MCAST_ACTION_FORWARD = 0,
+    MCAST_ACTION_DROP,
+    MCAST_ACTION_TRAP2CPU,
+    MCAST_ACTION_END
+} rtk_trap_mcast_action_t;
+
+typedef enum rtk_trap_reason_type_e
+{
+    TRAP_REASON_RMA = 0,
+    TRAP_REASON_IPV4IGMP,
+    TRAP_REASON_IPV6MLD,
+    TRAP_REASON_1XEAPOL,
+    TRAP_REASON_VLANERR,
+    TRAP_REASON_SLPCHANGE,
+    TRAP_REASON_MULTICASTDLF,
+    TRAP_REASON_CFI,
+    TRAP_REASON_1XUNAUTH,
+    TRAP_REASON_END
+} rtk_trap_reason_type_t;
+
+
+typedef enum rtk_trap_rma_action_e
+{
+    RMA_ACTION_FORWARD = 0,
+    RMA_ACTION_TRAP2CPU,
+    RMA_ACTION_DROP,
+    RMA_ACTION_FORWARD_EXCLUDE_CPU,
+    RMA_ACTION_END
+} rtk_trap_rma_action_t;
+
+typedef enum rtk_trap_ucast_action_e
+{
+    UCAST_ACTION_FORWARD = 0,
+    UCAST_ACTION_DROP,
+    UCAST_ACTION_TRAP2CPU,
+    UCAST_ACTION_END
+} rtk_trap_ucast_action_t;
+
+typedef enum rtk_trap_ucast_type_e
+{
+    UCAST_UNKNOWNDA = 0,
+    UCAST_UNKNOWNSA,
+    UCAST_UNMATCHSA,
+    UCAST_END
+} rtk_trap_ucast_type_t;
+
+typedef enum rtk_trunk_group_e
+{
+    TRUNK_GROUP0 = 0,
+    TRUNK_GROUP1,
+    TRUNK_GROUP2,
+    TRUNK_GROUP3,
+    TRUNK_GROUP_END
+} rtk_trunk_group_t;
+
+typedef struct  rtk_trunk_hashVal2Port_s
+{
+    uint8 value[RTK_MAX_NUM_OF_TRUNK_HASH_VAL];
+} rtk_trunk_hashVal2Port_t;
+
+typedef uint32  rtk_vlan_proto_type_t;     /* protocol and port based VLAN protocol type  */
+
+
+typedef enum rtk_vlan_acceptFrameType_e
+{
+    ACCEPT_FRAME_TYPE_ALL = 0,             /* untagged, priority-tagged and tagged */
+    ACCEPT_FRAME_TYPE_TAG_ONLY,         /* tagged */
+    ACCEPT_FRAME_TYPE_UNTAG_ONLY,     /* untagged and priority-tagged */
+    ACCEPT_FRAME_TYPE_END
+} rtk_vlan_acceptFrameType_t;
+
+
+/* frame type of protocol vlan - reference 802.1v standard */
+typedef enum rtk_vlan_protoVlan_frameType_e
+{
+    FRAME_TYPE_ETHERNET = 0,
+    FRAME_TYPE_LLCOTHER,
+    FRAME_TYPE_RFC1042,
+    FRAME_TYPE_END
+} rtk_vlan_protoVlan_frameType_t;
+
+typedef uint32  rtk_vlan_t;        /* vlan id type */
+
+/* Protocol-and-port-based Vlan structure */
+typedef struct rtk_vlan_protoAndPortInfo_s
+{
+    uint32                         proto_type;
+    rtk_vlan_protoVlan_frameType_t frame_type;
+    rtk_vlan_t                     cvid;
+    rtk_pri_t                     cpri;
+}rtk_vlan_protoAndPortInfo_t;
+
+/* tagged mode of VLAN - reference realtek private specification */
+typedef enum rtk_vlan_tagMode_e
+{
+    VLAN_TAG_MODE_ORIGINAL = 0,
+    VLAN_TAG_MODE_KEEP_FORMAT,
+    VLAN_TAG_MODE_REAL_KEEP_FORMAT,
+    VLAN_TAG_MODE_PRI,
+    VLAN_TAG_MODE_END
+} rtk_vlan_tagMode_t;
+
+typedef uint32 rtk_mib_cntValue_t;
+typedef enum rtk_mib_cntType_e
+{
+    MIB_COUNTER_TYPE_BYTE = 0,
+    MIB_COUNTER_TYPE_PKT,
+    MIB_COUNTER_TYPE_END
+}rtk_mib_cntType_t;
+
+typedef enum rtk_mib_counter_e
+{
+    MIB_CNT1 = 0,
+    MIB_CNT2,
+    MIB_CNT3,
+    MIB_CNT4,
+    MIB_CNT5,
+    MIB_CNT_END
+}rtk_mib_counter_t;
+
+/*some type for RTL8306E*/
+
+typedef   rtl8306e_vidSrc_t   rtk_vidSrc_t;
+typedef   rtl8306e_priSrc_t    rtk_priSrc_t;    
+
+typedef struct rtk_filter_rule_e
+{
+    uint32 phyport;   /*the physical port where packet received*/
+    uint32 protocol;  /*Acl protocol which is in the packet*/
+    uint32 data;       /*16bit ether type or TCP/UDP source port, destination port value*/
+    uint32 priority;   /*Acl priority assigned to the packet*/
+    uint32 action;     /*How to deal with the packet*/
+} rtk_filter_rule_t;
+    
+
+
+#endif  /*__RTK_API_H__*/
+
+
+
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api_ext.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api_ext.h
new file mode 100644
index 0000000..f2927a1
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_api_ext.h
@@ -0,0 +1,2384 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 26807 $ 
+* $Date: 2012-02-22 09:24:59 +0800 (星期三, 2012-02-22) $
+*
+* Purpose : Realtek common API function list supported by RTL8306E switch, 
+*               they could also be applied to chips 
+*               RTL8306M/RTL8305N/RTL8303/RTL8304E/RTL8306N
+* 
+* Feature : This file consists of following modules:
+*              (1)   Port Configuration              
+*              (2)   Rate Limit
+*              (3)   QOS
+*              (4)   TRAP
+*              (5)   VLAN
+*              (6)   Spanning Tree
+*              (7)   Address Table
+*              (8)   CPU Port
+*              (9)   Mirror
+*              (10)  IEEE 802.1x
+*              (11)  SVLAN
+*/
+
+
+#ifndef __RTK_API_EXT_H__
+#define __RTK_API_EXT_H__
+
+#include "rtl8306e_types.h"
+#include "rtk_api.h"
+
+/*
+ * Function Declaration
+ */
+ 
+/*Misc*/
+
+/* Function Name:
+ *      rtk_switch_init
+ * Description:
+ *      Set chip to default configuration enviroment
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED               -  Failure
+ * Note:
+ *     The API can set chip registers to default configuration for
+ *     different release chip model.
+ */ 
+extern rtk_api_ret_t rtk_switch_init(void);
+
+/* Function Name:
+ *      rtk_switch_maxPktLen_set
+ * Description:
+ *      Set the max packet length of the specific unit
+ * Input:
+ *      len       -       max packet length
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                    -  Success
+ *      RT_ERR_FAILED               -  Failure
+ *      RT_ERR_INPUT                -  Invalid input parameter
+ * Note:
+ *      The API can set max packet length of the specific unit to
+ *          MAXPKTLEN_1522B,
+ *          MAXPKTLEN_1536B,
+ *          MAXPKTLEN_1552B,
+ *          MAXPKTLEN_2000B, 
+ */ 
+extern rtk_api_ret_t rtk_switch_maxPktLen_set(rtk_switch_maxPktLen_t len); 
+
+/* Function Name:
+ *      rtk_switch_maxPktLen_get
+ * Description:
+ *      Get the max packet length of the specific unit
+ * Input:
+ *      none
+ * Output:
+ *      pLen                             -    the pointer of max packet length
+ * Return: 
+ *      RT_ERR_OK                    -  Success
+ *      RT_ERR_FAILED               -  Failure
+ *      RT_ERR_NULL_POINTER     -  Input parameter is null pointer 
+ * Note:
+ *      The API can set max packet length of the specific unit to
+ *          MAXPKTLEN_1522B,
+ *          MAXPKTLEN_1536B,
+ *          MAXPKTLEN_1552B,
+ *          MAXPKTLEN_2000B, 
+ */
+ extern rtk_api_ret_t rtk_switch_maxPktLen_get(rtk_switch_maxPktLen_t *pLen);
+
+/* Function Name:
+ *      rtk_port_phyReg_set
+ * Description:
+ *      Set PHY register data of the specific port
+ * Input:
+ *      phy                - phy number, 0 ~ 6 
+ *      reg                 - Register id
+ *      regData           - Register data
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK         -  Success
+ *      RT_ERR_FAILED   -   Failure
+ * Note:
+ *      This API can set PHY register data of the specific port.
+ *      RTL8306E switch has 5 FE port, and port 4 could be set as
+ *      phy mode or mac mode, port 5 is mac mode which connect
+ *      with mii interface. so parameter phy 0 ~4 means port 0 ~4
+ *      phy register, 5 means port 4 mac mode, 6 means port 5.
+ *      
+ */
+extern rtk_api_ret_t rtk_port_phyReg_set(rtk_port_t port, rtk_port_phy_reg_t reg, rtk_port_phy_data_t value);
+
+/* Function Name:
+ *      rtk_port_phyReg_get
+ * Description:
+ *      Get PHY register data of the specific port
+ * Input:
+ *      phy                  - phy number, 0 ~ 6
+ *      reg                   - Register id
+ * Output:
+ *      pData               - the pointer of Register data
+ * Return:
+ *      RT_ERR_OK        -  Success
+ *      RT_ERR_FAILED   -  Failure
+ * Note:
+ *      This API can set PHY register data of the specific port.
+ *      RTL8306E switch has 5 FE port, and port 4 could be set as
+ *      phy mode or mac mode, port 5 is mac mode which connect
+ *      with mii interface. so parameter phy 0 ~4 means port 0 ~4
+ *      phy register, 5 means port 4 mac mode, 6 means port 5.
+ *      
+ */
+extern rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t port, rtk_port_phy_reg_t reg, rtk_port_phy_data_t *pData); 
+
+/* Function Name:
+ *      rtk_port_phyAutoNegoAbility_set
+ * Description:
+ *      Set ethernet PHY auto-negotiation desired ability
+ * Input:
+ *      port       -  Port id
+ *      pAbility   -  Ability structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In auto-negotiation mode, phy autoNegotiation ability must be enabled
+ */ 
+extern rtk_api_ret_t rtk_port_phyAutoNegoAbility_set(rtk_port_t port, rtk_port_phy_ability_t *pAbility);
+
+/* Function Name:
+ *      rtk_port_phyAutoNegoAbility_get
+ * Description:
+ *      Get ethernet PHY auto-negotiation desired ability
+ * Input:
+ *      port       -  Port id
+ * Output:
+ *      pAbility   -  Ability structure
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_PHY_AUTO_NEGO_MODE
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In auto-negotiation mode, phy autoNegotiation ability must be enabled
+ */  
+extern rtk_api_ret_t rtk_port_phyAutoNegoAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility);
+
+/* Function Name:
+ *     rtk_port_phyForceModeAbility_set
+ * Description:
+ *      Set the port PHY force mode, config its speed/duplex mode/pause/asy_pause 
+ * Input:
+ *      port       -  Port id
+ *      pAbility   -  Ability structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_PHY_FORCE_1000
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In force mode,  phy autoNegotiation ability must be disabled.
+ */
+extern rtk_api_ret_t rtk_port_phyForceModeAbility_set(rtk_port_t port, rtk_port_phy_ability_t *pAbility);
+
+/* Function Name:
+ *      rtk_port_phyForceModeAbility_get
+ * Description:
+ *      Get the port PHY speed/duplex mode/pause/asy_pause in force mode
+ * Input:
+ *      port       -  Port id
+ * Output:
+ *      pAbility   -  Ability structure
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_PHY_REG_ID
+ *      RT_ERR_NULL_POINTER
+ *      RT_ERR_BUSYWAIT_TIMEOUT
+ *     
+ * Note:
+ *      (1) RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ *      (2) In force mode, phy autoNegotiation ability must be disabled.
+ */
+extern rtk_api_ret_t rtk_port_phyForceModeAbility_get(rtk_port_t port, rtk_port_phy_ability_t *pAbility);
+
+/* Function Name:
+ *      rtk_port_phyStatus_get
+ * Description:
+ *      Get ethernet PHY linking status
+ * Input:
+ *      port             -  Port id
+ * Output:
+ *      pLinkStatus   -  the pointer of PHY link status 
+ *      pSpeed         -  the pointer of PHY link speed
+ *      pDuplex        -  the pointer of PHY duplex 
+ * Return:
+ *      RT_ERR_OK                        
+ *      RT_ERR_FAILED                  
+ *      RT_ERR_SMI       
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_NULL_POINTER
+ *     
+ * Note:
+ *      RTL8306E switch only has 5 phy, so the input port id should be 0~4.
+ */
+extern rtk_api_ret_t rtk_port_phyStatus_get(rtk_port_t port, rtk_port_linkStatus_t *pLinkStatus, rtk_port_speed_t *pSpeed, rtk_port_duplex_t *pDuplex);
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt0_set
+ * Description:
+ *      Set external interface 1(MAC 5) force linking configuration.
+ * Input:
+ *      mode - external interface mode
+ *      pPortability - port ability configuration
+ * Output:
+ *      None 
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure
+ *      RT_ERR_INPUT       - Invalid input parameters.
+ * Note:
+ *      (1) This API can set external interface 1(MAC 5) force mode properties,
+ *      including link status,speed,duplex,and tx pause and tx pause ability.
+ *      In force mode, autoNegotiation ability must be disabled.
+ *      (2) For 8306E, the external interface 1(MAC 5) operating mode can be
+ *      MAC Mode (T)MII, PHY Mode (T)MII and RMII. The operating mode is 
+ *      determined by strapping pin upon reset, and can not be configured 
+ *      by software, except the selection of MII or TMII. 
+ *      (3)The input parament mode here is only used to select MII or TMII.
+ *      When operating mode is configured as MAC Mode (T)MII or PHY Mode (T)MII
+ *      via strapping pin, then the selection of MII or TMII can be done via software.
+ *      For example, set mode MODE_EXT_TMII_MAC to select TMII, and set mode
+ *      MODE_EXT_MII_MAC to select MII.
+ */
+extern rtk_api_ret_t rtk_port_macForceLinkExt0_set(rtk_mode_ext_t mode, rtk_port_mac_ability_t *pPortability);
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt0_get
+ * Description:
+ *      Get external interface 1(MAC 5) force linking configuration.
+ * Input:
+ *      None
+ * Output:
+ *      pMode - external interface mode
+ *      pPortability - port ability configuration
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_INPUT - Invalid input parameters.
+ * Note:
+ *      This API can get external interface 1 (MAC 5) force mode properties.
+ *      The external interface 1 operating mode can be:
+ *      - MODE_EXT_MII_MAC,
+ *      - MODE_EXT_MII_PHY, 
+ *      - MODE_EXT_TMII_MAC,
+ *      - MODE_EXT_TMII_PHY, 
+ *      - MODE_EXT_RMII, 
+ */
+extern rtk_api_ret_t rtk_port_macForceLinkExt0_get(rtk_mode_ext_t *pMode, rtk_port_mac_ability_t *pPortability);
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt_set
+ * Description:
+ *      Set external interface force linking configuration.
+ * Input:
+ *      port    -   port number
+ *      mode - external interface mode
+ *      pPortability - port ability configuration
+ * Output:
+ *      None 
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure
+ *      RT_ERR_INPUT       - Invalid input parameters.
+ * Note:
+ *      (1) This API can set external interface 0 and 1(MAC4 and MAC 5)force mode properties,
+ *      including link status,speed,duplex,and tx pause and tx pause ability.
+ *      In force mode, autoNegotiation ability must be disabled.
+ *      (2) For 8306E, the external interface 0(MAC 4) operating mode can be
+ *      MAC Mode MII, PHY Mode MII and RMII. The operating mode is 
+ *      determined by strapping pin upon reset, and can not be configured 
+ *      by software.  
+ *      (3) For 8306E, the external interface 1(MAC 5) operating mode can be
+ *      MAC Mode (T)MII, PHY Mode (T)MII and RMII. The operating mode is 
+ *      determined by strapping pin upon reset, and can not be configured 
+ *      by software, except the selection of MII or TMII. 
+ *      (4)The input parament mode here is only used to select MII or TMII. And it only takes effect
+ *      for external interface 1, neither for external interface 0.
+ *      When operating mode is configured as MAC Mode (T)MII or PHY Mode (T)MII
+ *      via strapping pin, then the selection of MII or TMII can be done via software.
+ *      For example, set mode MODE_EXT_TMII_MAC to select TMII, and set mode
+ *      MODE_EXT_MII_MAC to select MII.
+ */
+extern rtk_api_ret_t rtk_port_macForceLinkExt_set(rtk_port_t port, rtk_mode_ext_t mode, rtk_port_mac_ability_t *pPortability);
+
+/* Function Name:
+ *      rtk_port_macForceLinkExt_get
+ * Description:
+ *      Get external interface force linking configuration.
+ * Input:
+ *      port    -   port number
+ * Output:
+ *      pMode - external interface mode
+ *      pPortability - port ability configuration
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_INPUT - Invalid input parameters.
+ * Note:
+ *      This API can get external interface 0 (MAC 4) and 1 (MAC 5) force mode properties.
+ *      The external interface 0 operating mode can be:
+ *      - MODE_EXT_MII_MAC,
+ *      - MODE_EXT_MII_PHY, 
+ *      - MODE_EXT_RMII,     
+ *      The external interface 1 operating mode can be:
+ *      - MODE_EXT_MII_MAC,
+ *      - MODE_EXT_MII_PHY, 
+ *      - MODE_EXT_TMII_MAC,
+ *      - MODE_EXT_TMII_PHY, 
+ *      - MODE_EXT_RMII, 
+ */
+extern rtk_api_ret_t rtk_port_macForceLinkExt_get(rtk_port_t port, rtk_mode_ext_t *pMode, rtk_port_mac_ability_t *pPortability);
+
+#ifdef CHIP_RTL8304E
+/* Function Name:
+ *      rtk_port_mii1Disable_set
+ * Description:
+ *      Disable MII1 for RTL8304E by trunk
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ * Note:
+ *      Strapping pin 49 can be used to force MII1 link down for RTL8306E.
+ *      But there are no strapping pins or registers for RTL8304E to do so.
+ *      To disable MII1 for RTL8304E, trunk can be used. First enable trunk function,
+ *      Then trunk rtl8306e's port3 and port4 to be a trunk port. After this port2(MII1) is 
+ *      forced to be linking down for RTL8304E.    
+*/
+extern rtk_api_ret_t rtk_port_mii1Disable_set(void);
+#endif
+
+/* Function Name:
+ *      rtk_port_isolation_set
+ * Description:
+ *      Set permitted port isolation portmask
+ * Input:
+ *      port                - port id, 0 ~ 5 
+ *      portmask         - Permit port mask
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK             -   Success
+ *      RT_ERR_PORT_ID     -   Invalid port number
+ *      RT_ERR_PORT_MASK -   Invalid portmask
+ *      RT_ERR_FAILED        -   Failure
+ * Note:
+ *      This API set the port mask that a port can trasmit packet to of each port.
+ *      A port can only transmit packet to ports included in permitted portmask  
+ */
+extern rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t portmask);
+
+/* Function Name:
+ *      rtk_port_isolation_get
+ * Description:
+ *      Get permitted port isolation portmask
+ * Input:
+ *      port                - port id, 0 ~ 5 
+ * Output:
+ *      pPortmask       - the pointer of permit port mask
+ * Return:
+ *      RT_ERR_OK                  -   Success
+ *      RT_ERR_PORT_ID          -   Invalid port number
+ *      RT_ERR_NULL_POINTER  -   Input parameter is null pointer
+ *      RT_ERR_FAILED             -   Failure
+ * Note:
+ *      This API get the port mask that a port can trasmit packet to of each port.
+ *      A port can only transmit packet to ports included in permitted portmask  
+ */
+ 
+extern rtk_api_ret_t rtk_port_isolation_get(rtk_port_t port, rtk_portmask_t *pPortmask);
+
+/* Function Name:
+ *      rtk_stat_port_reset
+ * Description:
+ *      Reset per port MIB counter by port.
+ * Input:
+ *      port - port id.
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - set shared meter successfully
+ *      RT_ERR_FAILED          - FAILED to iset shared meter
+ * Note:
+ */
+extern rtk_api_ret_t rtk_stat_port_reset(rtk_port_t port);
+
+
+/* Function Name:
+ *      rtk_rate_igrBandwidthCtrlRate_set
+ * Description:
+ *      Set port ingress bandwidth control
+ * Input:
+ *      port            -  Port id
+ *      rate            -  Rate of share meter
+ *      ifg_include   -  Rate's calculation including IFG, ENABLE:include DISABLE:exclude
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK              -  Success
+ *      RT_ERR_PORT_ID      -  Invalid port number
+ *      RT_ERR_FAILED        -  Failure
+ *      RT_ERR_ENABLE       -  Invalid IFG parameter
+ *      RT_ERR_INBW_RATE -  Invalid ingress rate parameter
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */ 
+extern rtk_api_ret_t rtk_rate_igrBandwidthCtrlRate_set( rtk_port_t port, rtk_rate_t rate,  rtk_enable_t ifg_include);
+
+/* Function Name:
+ *      rtk_rate_igrBandwidthCtrlRate_get
+ * Description:
+ *      Get port ingress bandwidth control
+ * Input:
+ *      port             -  Port id
+ * Output:
+ *      pRate           -  the pointer of rate of share meter
+ *      pIfg_include   -  Rate's calculation including IFG, ENABLE:include DISABLE:exclude
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_PORT_ID              -  Invalid port number
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_ENABLE               -  Invalid IFG parameter
+ *      RT_ERR_NULL_POINTER      -  null pointer
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+extern rtk_api_ret_t rtk_rate_igrBandwidthCtrlRate_get(rtk_port_t port, rtk_rate_t *pRate, rtk_enable_t *pIfg_include);
+
+/* Function Name:
+ *      rtk_rate_egrBandwidthCtrlRate_set
+ * Description:
+ *      Set port egress bandwidth control
+ * Input:
+ *      port            -  Port id
+ *      rate            -  Rate of bandwidth control
+ *      ifg_include   -  Rate's calculation including IFG, ENABLE:include DISABLE:exclude
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                   -  Success
+ *      RT_ERR_PORT_ID           -  Invalid port number
+ *      RT_ERR_FAILED             -  Failure
+ *      RT_ERR_ENABLE             -  Invalid IFG parameter
+ *      RT_ERR_QOS_EBW_RATE -  Invalid egress rate parameter
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+extern rtk_api_ret_t rtk_rate_egrBandwidthCtrlRate_set(rtk_port_t port, rtk_rate_t rate,  rtk_enable_t ifg_include);
+
+/* Function Name:
+ *      rtk_rate_igrBandwidthCtrlRate_get
+ * Description:
+ *      Get port ingress bandwidth control
+ * Input:
+ *      port             -  Port id
+ * Output:
+ *      pRate           -  the pointer of rate of bandwidth control
+ *      pIfg_include   -  Rate's calculation including IFG, ENABLE:include DISABLE:exclude
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_PORT_ID             -  Invalid port number
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_NULL_POINTER      -  null pointer
+ * Note:
+ *      The rate unit is 64Kbps and the range is from 64Kbps to 100Mbps. The granularity of rate is 64Kbps. 
+ *      The ifg_include parameter is used for rate calculation with/without inter-frame-gap and preamble. 
+ */
+extern rtk_api_ret_t rtk_rate_egrBandwidthCtrlRate_get(rtk_port_t port, rtk_rate_t *pRate, rtk_enable_t *pIfg_include);
+
+/* QoS */
+
+/* Function Name:
+ *      rtk_qos_init
+ * Description:
+ *      Configure Qos default settings with queue number assigment to each port
+ * Input:
+ *      queueNum     -  Queue number of each port
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_QUEUE_NUM         -  Error queue number
+ * Note:
+ *    This API will initialize related Qos setting with queue number assigment.
+ *    The queue number is from 1 to 4.
+ */ 
+extern rtk_api_ret_t rtk_qos_init(rtk_queue_num_t queueNum);
+
+/* Function Name:
+ *      rtk_qos_1pPriRemap_set
+ * Description:
+ *      Configure 1Q priorities mapping to internal absolute priority
+ * Input:
+ *      dot1p_pri   -  802.1p priority value
+ *      int_pri       -  internal priority value
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_VLAN_PRIORITY        -  Invalid 1p priority
+ *      RT_ERR_QOS_INT_PRIORITY   -  Invalid priority
+ * Note:
+ *      Priority of 802.1Q assignment for internal asic priority, and it is used for queue usage 
+ *      and packet scheduling.
+ */ 
+extern rtk_api_ret_t rtk_qos_1pPriRemap_set(rtk_pri_t dot1p_pri, rtk_pri_t int_pri);
+
+/* Function Name:
+ *      rtk_qos_priSel_set
+ * Description:
+ *      Configure the priority order among different priority mechanisms.
+ * Input:
+ *      pPriDec - priority level for port, dscp, 802.1Q, ACL and VID based priority decision.
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - success
+ *      RT_ERR_NULL_POINTER  -   Input parameter is null pointer
+ *      RT_ERR_FAILED          - failure 
+ *      RT_ERR_QOS_SEL_PRI_SOURCE - Invalid priority decision source parameter.
+ * Note: 
+ *      (1)For 8306E, there are 5 types of priority mechanisms that could be set arbitration level, which are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority, Port-based priority, VID-based priority.
+ *      Each one could be set level from 1 to 5.
+ *      (2)ASIC will follow user's arbitration level setting of priority mechanisms to select internal priority for receiving frame. 
+ *      If two priority mechanisms are the same level, the ASIC will chose the priority mechanism with highest level to 
+ *      assign internal priority to receiving frame.
+ */
+extern rtk_api_ret_t rtk_qos_priSel_set(rtk_priority_select_t *pPriDec);
+
+/* Function Name:
+ *      rtk_qos_priSel_get
+ * Description:
+ *      Get the priority order configuration among different priority mechanism.
+ * Input:
+ *      None
+ * Output:
+ *      pPriDec - priority level for port, dscp, 802.1Q, ACL and VID based priority decision.
+ * Return:
+ *      RT_ERR_OK              - success
+ *      RT_ERR_NULL_POINTER  -   Input parameter is null pointer
+ *      RT_ERR_FAILED          - failure 
+ * Note:
+ *      (1)For 8306E, there are 5 types of priority mechanisms that could be set arbitration level, which are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority,Port-based priority, VID-based priority.
+ *      Each one could be set level from 1 to 5.
+ *      (2)ASIC will follow user's arbitration level setting of priority mechanisms to select internal priority for receiving frame. 
+ *      If two priority mechanisms are the same level, the ASIC will chose the priority mechanism with the highest level to 
+ *      assign internal priority to receiving frame.
+ */
+extern rtk_api_ret_t rtk_qos_priSel_get(rtk_priority_select_t *pPriDec);
+
+/* Function Name:
+ *      rtk_qos_1pPriRemap_get
+ * Description:
+ *      Get 1Q priorities mapping to internal absolute priority
+ * Input:
+ *      dot1p_pri    -  802.1p priority value
+ * Output:
+ *      pInt_pri      -  the pointer of internal priority value
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_VLAN_PRIORITY        -  Invalid 1p priority
+ *      RT_ERR_NULL_POINTER         -   null pointer
+ * Note:
+ *      Priority of 802.1Q assignment for internal asic priority, and it is used for queue usage 
+ *      and packet scheduling.
+ */
+extern rtk_api_ret_t rtk_qos_1pPriRemap_get(rtk_pri_t dot1p_pri, rtk_pri_t *pInt_pri);
+
+/* Function Name:
+ *      rtk_qos_dscpPriRemap_set
+ * Description:
+ *      Set DSCP-based priority
+ * Input:
+ *      code      -  dscp code
+ *      int_pri    -  internal priority value
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_QOS_INT_PRIORITY   -  invalid internal priority
+ *      RT_ERR_QOS_DSCP_VALUE    -   invalid DSCP value  
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *
+ *     The Differentiated Service Code Point is a selector for router's per-hop behaviors. As a selector, there is no implication that a numerically 
+ *     greater DSCP implies a better network service. As can be seen, the DSCP totally overlaps the old precedence field of TOS. So if values of 
+ *     DSCP are carefully chosen then backward compatibility can be achieved.         
+ */ 
+extern rtk_api_ret_t rtk_qos_dscpPriRemap_set(rtk_dscp_t dscp, rtk_pri_t int_pri);
+
+/* Function Name:
+ *      rtk_qos_dscpPriRemap_get
+ * Description:
+ *      Get DSCP-based priority
+ * Input:
+ *      dscp      -  dscp code
+ * Output:
+ *      pInt_pri  -  the pointer of internal priority value
+ * Return:
+ *      RT_ERR_OK                           -  Success
+ *      RT_ERR_FAILED                     -  Failure
+ *      RT_ERR_QOS_DSCP_VALUE      -  Invalid DSCP value
+ *      RT_ERR_NULL_POINTER           -  Input parameter is null pointer
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *     The Differentiated Service Code Point is a selector for router's per-hop behaviors. As a selector, there is no implication that a numerically 
+ *     greater DSCP implies a better network service. As can be seen, the DSCP totally overlaps the old precedence field of TOS. So if values of 
+ *     DSCP are carefully chosen then backward compatibility can be achieved.         
+ */ 
+extern rtk_api_ret_t rtk_qos_dscpPriRemap_get(rtk_dscp_t dscp, rtk_pri_t *pInt_pri);
+
+/* Function Name:
+ *      rtk_qos_portPri_set
+ * Description:
+ *      Configure priority usage to each port
+ * Input:
+ *      port                - Port id.                
+ *      int_pri             -  internal priority value
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_PORT_ID                -   Error port id
+ *      RT_ERR_QOS_INT_PRIORITY  -   Error internal priority value
+ * Note:
+ *     The API can set priority of port assignments for queue usage and packet scheduling.
+ */
+ 
+extern rtk_api_ret_t rtk_qos_portPri_set(rtk_port_t port, rtk_pri_t int_pri) ;
+
+/* Function Name:
+ *      rtk_qos_portPri_get
+ * Description:
+ *      Get priority usage to each port
+ * Input:
+ *      port                  - Port id.                
+ * Output:
+ *      pInt_pri             -  the pointer of internal priority value
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_PORT_ID                -   Error port id
+ *      RT_ERR_NULL_POINTER        -   null pointer
+ * Note:
+ *      The API can get priority of port assignments for queue usage and packet scheduling.
+ */
+ 
+extern rtk_api_ret_t rtk_qos_portPri_get(rtk_port_t port, rtk_pri_t *pInt_pri) ;
+
+/* Function Name:
+ *      rtk_qos_priMap_set
+ * Description:
+ *      Set internal priority mapping to queue ID for different queue number
+ * Input:
+ *      queue_num       - Queue number usage
+ *      pPri2qid            - Priority mapping to queue ID               
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_QUEUE_ID              -   Error queue id
+ *      RT_ERR_NULL_POINTER        -   null pointer
+ * Note:
+ *      ASIC supports priority mapping to queue with different queue number from 1 to 4.
+ *      For different queue numbers usage, ASIC supports different internal available queue IDs.
+ */
+
+extern rtk_api_ret_t rtk_qos_priMap_set(rtk_queue_num_t queue_num, rtk_qos_pri2queue_t *pPri2qid);
+
+/* Function Name:
+ *      rtk_qos_priMap_get
+ * Description:
+ *      Get priority to queue ID mapping table parameters
+ * Input:
+ *      queue_num       - Queue number usage
+ *      pPri2qid            - Priority mapping to queue ID               
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ *      RT_ERR_QUEUE_ID              -   Error queue id
+ *      RT_ERR_NULL_POINTER        -   null pointer
+ * Note:
+ *      ASIC supports priority mapping to queue with different queue number from 1 to 4.
+ *      For different queue numbers usage, ASIC supports different internal available queue IDs.
+ */
+ 
+extern rtk_api_ret_t rtk_qos_priMap_get(rtk_queue_num_t queue_num, rtk_qos_pri2queue_t *pPri2qid);
+
+/* Function Name:
+ *      rtk_qos_1pRemarkEnable_set
+ * Description:
+ *      Set 802.1P remarking ability
+ * Input:
+ *      port       -  port number (0~5)
+ *      enabled  -  TRUE or FALSE
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK              -  Success
+ *      RT_ERR_FAILED        -   Failure
+ *      RT_ERR_PORT_ID      -   Invalid port id
+ * Note:
+ *      
+ */
+extern rtk_api_ret_t rtk_qos_1pRemarkEnable_set(rtk_port_t port, rtk_enable_t enable); 
+
+/* Function Name:
+ *      rtk_qos_1pRemarkEnable_get
+ * Description:
+ *      Get 802.1P remarking ability
+ * Input:
+ *      port        -  port number (0~5)
+ * Output:
+ *      pEnabled  -  pointer of the ability status
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED               -   Failure
+ *      RT_ERR_PORT_ID             -   Invalid port id
+ *      RT_ERR_NULL_POINTER     -   Input parameter is null pointer
+ * Note:
+ *      
+ */
+extern rtk_api_ret_t rtk_qos_1pRemarkEnable_get(rtk_port_t port, rtk_enable_t *pEnable);
+
+/* Function Name:
+ *      rtk_qos_1pRemark_set
+ * Description:
+ *      Set 802.1P remarking priority
+ * Input:
+ *      int_pri        -  Packet priority(0~4)
+ *      dot1p_pri    -  802.1P priority(0~7)
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                           - Success
+ *      RT_ERR_FAILED                      - Failure
+ *      RT_ERR_VLAN_PRIORITY          - Invalid 1p priority
+ *      RT_ERR_QOS_INT_PRIORITY     - Invalid internal priority 
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */ 
+extern rtk_api_ret_t rtk_qos_1pRemark_set(rtk_pri_t int_pri, rtk_pri_t dot1p_pri);
+
+/* Function Name:
+ *      rtk_qos_1pRemark_get
+ * Description:
+ *      Get 802.1P remarking priority
+ * Input:
+ *      int_pri        -  Packet priority(0~4)
+ * Output:
+ *      pDot1p_pri  -  the pointer of 802.1P priority(0~7)
+ * Return:
+ *      RT_ERR_OK                           -  Success
+ *      RT_ERR_FAILED                      -  Failure
+ *      RT_ERR_NULL_POINTER            -  Input parameter is null pointer
+ *      RT_ERR_QOS_INT_PRIORITY     -  Invalid internal priority 
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+extern rtk_api_ret_t rtk_qos_1pRemark_get(rtk_pri_t int_pri, rtk_pri_t *pDot1p_pri);
+
+/* Trap & Reserved Multicast Address (More Action like leaky, bypass storm not define) */
+
+/* Function Name:
+ *      rtk_trap_unknownMcastPktAction_set
+ * Description:
+ *      Set behavior of unknown multicast
+ * Input:
+ *      port                -   port id
+ *      type               -   unknown multicast packet type
+ *      mcast_action    -  unknown multicast action
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id    
+ *      RT_ERR_INPUT                 -  Invalid input parameter 
+ * Note:
+ *      When receives an unknown multicast packet, switch may trap, drop this packet
+ *      The unknown multicast packet type is as following:
+ *               - MCAST_IPV4
+ *               - MCAST_IPV6
+ *      The unknown multicast action is as following:
+ *               - MCAST_ACTION_FORWARD
+ *               - MCAST_ACTION_DROP
+ */
+extern rtk_api_ret_t rtk_trap_unknownMcastPktAction_set(rtk_port_t port, rtk_mcast_type_t type, rtk_trap_mcast_action_t mcast_action);
+
+/* Function Name:
+ *      rtk_trap_unknownMcastPktAction_get
+ * Description:
+ *      Get behavior of unknown multicast
+ * Input:
+ *      port                  -   port id
+ *      type                 -   unknown multicast packet type
+ * Output:
+ *      pMcast_action    -   the pointer of unknown multicast action
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id    
+ *      RT_ERR_NULL_POINTER      -  Input parameter is null pointer
+ * Note:
+ *      When receives an unknown multicast packet, switch may trap, drop this packet.
+ *      The unknown multicast packet type is as following:
+ *               - MCAST_IPV4
+ *               - MCAST_IPV6
+ *      The unknown multicast action is as following:
+ *               - MCAST_ACTION_FORWARD
+ *               - MCAST_ACTION_DROP
+ */
+extern rtk_api_ret_t rtk_trap_unknownMcastPktAction_get(rtk_port_t port, rtk_mcast_type_t type, rtk_trap_mcast_action_t *pMcast_action);
+
+/* Function Name:
+ *      rtk_trap_igmpCtrlPktAction_set
+ * Description:
+ *      Set IGMP/MLD trap function
+ * Input:
+ *      type                -   IGMP/MLD packet type
+ *      igmp_action      -   IGMP/MLD action
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_INPUT                 -  Invalid input parameter
+ *      RT_ERR_NOT_ALLOWED     -  Actions not allowed by the function
+ * Note:
+ *      This API can set both IPv4 IGMP/IPv6 MLD with/without PPPoE header trapping function.
+ *      All 4 kinds of IGMP/MLD function can be set separately.
+ *      The IGMP/MLD packet type is as following:
+ *          - IGMP_IPV4
+ *          - IGMP_MLD
+ *          - IGMP_PPPOE_IPV4
+ *          - IGMP_PPPOE_MLD
+ *      The IGMP/MLD action is as following:
+ *          - IGMP_ACTION_FORWARD
+ *          - IGMP_ACTION_TRAP2CPU
+ */  
+extern rtk_api_ret_t rtk_trap_igmpCtrlPktAction_set(rtk_igmp_type_t type, rtk_trap_igmp_action_t igmp_action);
+
+/* Function Name:
+ *      rtk_trap_igmpCtrlPktAction_get
+ * Description:
+ *      Get IGMP/MLD trap function
+ * Input:
+ *      type                -   IGMP/MLD packet type
+ * Output:
+ *      pIgmp_action    -   the pointer of IGMP/MLD action
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_INPUT                 -  Invalid input parameter
+ *      RT_ERR_NULL_POINTER      -  Input parameter is null pointer
+ * Note:
+ *      This API can get both IPv4 IGMP/IPv6 MLD with/without PPPoE header trapping function.
+ *      All 4 kinds of IGMP/MLD function can be set separately.
+ *      The IGMP/MLD packet type is as following:
+ *          - IGMP_IPV4
+ *          - IGMP_MLD
+ *          - IGMP_PPPOE_IPV4
+ *          - IGMP_PPPOE_MLD
+ *      The IGMP/MLD action is as following:
+ *          - IGMP_ACTION_FORWARD
+ *          - IGMP_ACTION_TRAP2CPU
+ */
+extern rtk_api_ret_t rtk_trap_igmpCtrlPktAction_get(rtk_igmp_type_t type, rtk_trap_igmp_action_t *pIgmp_action);
+
+
+/* CVLAN */
+
+/* Function Name:
+ *      rtk_vlan_init
+ * Description:
+ *      Initialize VLAN
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED                -  Failure
+ * Note:
+ *      VLAN is disabled by default. User has to call this API to enable VLAN before
+ *      using it. And It will set a default VLAN(vid 1) including all ports and set 
+ *      all ports PVID to the default VLAN.
+ */
+extern rtk_api_ret_t rtk_vlan_init(void);
+
+/* Function Name:
+ *      rtk_vlan_set
+ * Description:
+ *      Set a VLAN entry
+ * Input:
+ *      vid              - VLAN ID to configure, should be 1~4094
+ *      mbrmsk        - VLAN member set portmask
+ *      untagmsk     - VLAN untag set portmask
+ *      fid              -  filtering database id, could be any value for RTL8306E
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                     -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_VLAN_VID            -  Invalid vid
+ *      RT_ERR_INPUT                 -  Invalid input parameter 
+ *      RT_ERR_TBL_FULL            -  Input table full 
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ *     FID is for SVL/IVL usage, and the range is 0~4095, rtl8306E only supports SVL, 
+ *     so fid is no useage.
+ */
+extern rtk_api_ret_t rtk_vlan_set(rtk_vlan_t vid, rtk_portmask_t mbrmsk, rtk_portmask_t untagmsk, rtk_fid_t fid);
+
+/* Function Name:
+ *      rtk_vlan_get
+ * Description:
+ *      Get a VLAN entry
+ * Input:
+ *      vid             - VLAN ID to configure
+ * Output:
+ *      pMbrmsk     - VLAN member set portmask
+ *      pUntagmsk  - VLAN untag set portmask
+ *      pFid           -  filtering database id
+ * Return:
+ *      RT_ERR_OK                                   -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_VLAN_VID                          -  Invalid vid
+ *      RT_ERR_NULL_POINTER                    -  Input parameter is null pointer
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND    -   Specified vlan entry not found
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ *     FID is for SVL/IVL usage, and the range is 0~4095, rtl8306E only supports SVL, 
+ *     so fid is no useage.
+ */
+extern rtk_api_ret_t rtk_vlan_get(rtk_vlan_t vid, rtk_portmask_t *pMbrmsk, rtk_portmask_t *pUntagmsk, rtk_fid_t *pFid);
+
+/* Function Name:
+ *      rtk_vlan_destroy
+ * Description:
+ *      delete vid from vlan table
+ * Input:
+ *      vid             - VLAN ID to configure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                   -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_VLAN_VID                          -  Invalid vid
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND    -  Specified vlan entry not found
+ * Note:
+ * 
+ */ 
+extern rtk_api_ret_t rtk_vlan_destroy(rtk_vlan_t vid);
+
+/* Function Name:
+ *      rtk_vlan_portPvid_set
+ * Description:
+ *      Set port to specified VLAN ID(PVID)
+ * Input:
+ *      port             - Port id
+ *      pvid             - Specified VLAN ID
+ *      priority         - 802.1p priority for the PVID, 0~3 for RTL8306E 
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                   -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_VLAN_VID                          -  Invalid vid
+ *      RT_ERR_VLAN_PRIORITY                  -  Invalid 1p priority 
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND    -  Specified vlan entry not found
+ * Note:
+ *      The API is used for Port-based VLAN. The untagged frame received from the
+ *      port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+extern rtk_api_ret_t rtk_vlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority);
+
+/* Function Name:
+ *      rtk_vlan_portPvid_get
+ * Description:
+ *      Get VLAN ID(PVID) on specified port
+ * Input:
+ *      port             - Port id
+ * Output:
+ *      pPvid            - Specified VLAN ID
+ *      pPriority        - 802.1p priority for the PVID
+ * Return:
+ *      RT_ERR_OK                                   - Success
+ *      RT_ERR_FAILED                             -  Failure
+ *      RT_ERR_PORT_ID                           -  Invalid port id
+ *      RT_ERR_NULL_POINTER                   -  Input parameter is null pointer
+ * Note:
+ *    The API is used for Port-based VLAN. The untagged frame received from the
+ *    port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+extern rtk_api_ret_t rtk_vlan_portPvid_get(rtk_port_t port, rtk_vlan_t *pPvid, rtk_pri_t *pPriority);
+
+/* Function Name:
+ *      rtk_vlan_portIgrFilterEnable_set
+ * Description:
+ *      Set VLAN ingress for each port
+ * Input:
+ *      port             - Port id
+ *      igr_filter        - VLAN ingress function enable status
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        - Success
+ *      RT_ERR_FAILED                  -  Failure
+ * Note:
+ *      RTL8306E use one ingress filter for whole system, not for each port, so 
+ *      any port you set will affect all ports ingress filter setting.
+ *      While VLAN function is enabled, ASIC will decide VLAN ID for each received frame 
+ *      and get belonged member ports from VLAN table. If received port is not belonged 
+ *      to VLAN member ports, ASIC will drop received frame if VLAN ingress function is enabled.
+ */
+extern rtk_api_ret_t rtk_vlan_portIgrFilterEnable_set(rtk_port_t port, rtk_enable_t igr_filter);
+
+/* Function Name:
+ *      rtk_vlan_portIgrFilterEnable_get
+ * Description:
+ *      get VLAN ingress for each port
+ * Input:
+ *      port             - Port id
+ * Output:
+ *      pIgr_filter     - the pointer of VLAN ingress function enable status
+ * Return:
+ *      RT_ERR_OK                 - Success
+ *      RT_ERR_FAILED           -  Failure
+ * Note:
+ *      RTL8306E use one ingress filter for whole system, not for each port, so 
+ *      any port you set will affect all ports ingress filter setting.
+ *      While VLAN function is enabled, ASIC will decide VLAN ID for each received frame 
+ *      and get belonged member ports from VLAN table. If received port is not belonged 
+ *      to VLAN member ports, ASIC will drop received frame if VLAN ingress function is enabled.
+ */
+extern rtk_api_ret_t rtk_vlan_portIgrFilterEnable_get(rtk_port_t port, rtk_enable_t *pIgr_filter);
+
+/* Function Name:
+ *      rtk_vlan_portAcceptFrameType_set
+ * Description:
+ *      Set VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ *      accept_frame_type             - accept frame type
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                  - Success
+ *      RT_ERR_FAILED            -  Failure
+ *      RT_ERR_PORT_ID          -  Invalid port id
+ * Note:
+ *      The API is used for checking 802.1Q tagged frames.
+ *      The accept frame type as following:
+ *          - ACCEPT_FRAME_TYPE_ALL
+ *          - ACCEPT_FRAME_TYPE_TAG_ONLY
+ *          - ACCEPT_FRAME_TYPE_UNTAG_ONLY
+ */
+extern rtk_api_ret_t rtk_vlan_portAcceptFrameType_set(rtk_port_t port, rtk_vlan_acceptFrameType_t accept_frame_type);
+
+/* Function Name:
+ *      rtk_vlan_portAcceptFrameType_get
+ * Description:
+ *      Get VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ *      accept_frame_type             - accept frame type
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                   - Success
+ *      RT_ERR_FAILED                             -  Failure
+ *      RT_ERR_PORT_ID                           -  Invalid port id
+ *      RT_ERR_VLAN_ACCEPT_FRAME_TYPE -  Invalid accept frame type 
+ * Note:
+ *    The API is used for checking 802.1Q tagged frames.
+ *    The accept frame type as following:
+ *    - ACCEPT_FRAME_TYPE_ALL
+ *    - ACCEPT_FRAME_TYPE_TAG_ONLY
+ *    - ACCEPT_FRAME_TYPE_UNTAG_ONLY
+ */
+extern rtk_api_ret_t rtk_vlan_portAcceptFrameType_get(rtk_port_t port, rtk_vlan_acceptFrameType_t *pAccept_frame_type);
+
+/* Function Name:
+ *      rtk_vlan_vlanBasedPriority_set
+ * Description:
+ *      Set VLAN priority for each CVLAN
+ * Input:
+ *      vid                -Specified VLAN ID
+ *      priority           -priority for the VID
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_VLAN_PRIORITY               -  Invalid 1p priority
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -  Specified vlan entry not found
+ * Note:
+ *      This API is used to set priority per VLAN.
+ */ 
+extern rtk_api_ret_t rtk_vlan_vlanBasedPriority_set(rtk_vlan_t vid, rtk_pri_t priority);
+
+/* Function Name:
+ *      rtk_vlan_vlanBasedPriority_get
+ * Description:
+ *      Get VLAN priority for each CVLAN
+ * Input:
+ *      vid                -Specified VLAN ID
+ * Output:
+ *      pPriority         -the pointer of priority for the VID
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_NULL_POINTER                -   Input parameter is null pointer
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -   Specified vlan entry not found 
+ * Note:
+ *      This API is used to set priority per VLAN.
+ */ 
+extern rtk_api_ret_t rtk_vlan_vlanBasedPriority_get(rtk_vlan_t vid, rtk_pri_t *pPriority);
+
+/* Function Name:
+ *      rtk_vlan_vidTranslation_set
+ * Description:
+ *      Set vid translated to new vid
+ * Input:
+ *      vid       -  old vid
+ *      nvid     -   new vid
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -   Specified vlan entry not found 
+ * Note:
+ *      This API is used to translate a vid to a new vid, the new vid could be 
+ *      used by Q-in-Q or vlan translation function.
+ */
+extern rtk_api_ret_t rtk_vlan_vidTranslation_set(rtk_vlan_t vid, rtk_vlan_t nvid);
+
+/* Function Name:
+ *      rtk_vlan_vidTranslation_get
+ * Description:
+ *      Get vid translation new vid
+ * Input:
+ *      vid        -  old vid
+ * Output:
+ *      pNvid     -  the pointer of new vid
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_VLAN_VID                       -  Invalid vid 
+ *      RT_ERR_NULL_POINTER                -   NULL pointer
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND -   Specified vlan entry not found 
+ * Note:
+ *      This API is used to translate a vid to a new vid, the new vid could be 
+ *      used by Q-in-Q or vlan translation function.
+ */
+extern rtk_api_ret_t rtk_vlan_vidTranslation_get(rtk_vlan_t vid, rtk_vlan_t *pNvid);
+
+
+/* Function Name:
+ *      rtk_vlan_vidTranslationEnable_set
+ * Description:
+ *      Set vlan translation function enabled or disabled 
+ * Input:
+ *      enable        -  enable or disable
+ *      nniMask      -   NNI port mask
+ * Output:
+ *      pNvid     -  the pointer of new vid
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_PORT_MASK                   -   Error port mask
+ * Note:
+ *      VLAN translation only happens between UNI and NNI port, 
+ *      in nniMask, 1 means the port is NNI port, 0 means the port
+ *      is UNI port
+ */
+extern rtk_api_ret_t rtk_vlan_vidTranslationEnable_set(rtk_enable_t enable, rtk_portmask_t nniMask);
+
+/* Function Name:
+ *      rtk_vlan_vidTranslationEnable_get
+ * Description:
+ *      Get vlan translation function enabled or disabled 
+ * Input:
+ * Output:
+ *      pEnable      -   the pointer of enable or disable
+ *      pNniMask    -   the pointer of NNI port mask
+ * Return:
+ *      RT_ERR_OK                                -  Success
+ *      RT_ERR_FAILED                          -   Failure
+ *      RT_ERR_NULL_POINTER                -   NULL pointer
+ * Note:
+ *      VLAN translation only happens between UNI and NNI port, 
+ *      in nniMask, 1 means the port is NNI port, 0 means the port
+ *      is UNI port
+ */
+
+extern rtk_api_ret_t rtk_vlan_vidTranslationEnable_get(rtk_enable_t *pEnable, rtk_portmask_t *pNniMask);
+
+
+/* Function Name:
+ *      rtk_vlan_tagSrc_set
+ * Description:
+ *      Set tag vid and priority source for Q-in-Q and VLAN translation
+ * Input:
+ *      port          -    port id
+ *      vidSrc       -    vid source
+ *      priSrc        -    priority source
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                 -  Success
+ *      RT_ERR_FAILED            -   Failure
+ *      RT_ERR_PORT_ID          -   error port id
+ * Note:
+ *     Q-in-Q(SVLAN) and VLAN translation will modify tag, 
+ *      the API could set outer tag or translated VLAN tag
+ *      vid/priority source.
+ *      - vidSrc: 
+ *                - RTL8306E_VIDSRC_POVID - port-based otag vid,     
+ *                - RTL8306E_VIDSRC_NVID   - new vid(translated vid)
+ *       - priSrc:
+ *                - RTL8306E_PRISRC_PPRI    - port-based otag priority, 
+ *                - RTL8306E_PRISRC_1PRMK - 1p remarking priority
+ */
+extern rtk_api_ret_t rtk_vlan_tagSrc_set(rtk_port_t port, rtk_vidSrc_t vidSrc, rtk_priSrc_t priSrc);
+
+/* Function Name:
+ *      rtk_vlan_tagSrc_get
+ * Description:
+ *      Get tag vid and priority source for Q-in-Q and VLAN translation
+ * Input:
+ *      port          -    port id
+ * Output:
+ *      pVidSrc     -    the pointer of vid source
+ *      pPriSrc      -    the pointer of priority source
+ * Return:
+ *      RT_ERR_OK                 -  Success
+ *      RT_ERR_FAILED            -   Failure
+ *      RT_ERR_PORT_ID          -   error port id
+ * Note:
+ *      Q-in-Q(SVLAN) and VLAN translation will modify tag, 
+ *      the API could set outer tag or tranlated VLAN tag
+ *      vid/priority source.
+ *      - vidSrc: 
+ *                - RTL8306E_VIDSRC_POVID - port-based otag vid,     
+ *                - RTL8306E_VIDSRC_NVID   - new vid(translated vid)
+ *       - priSrc:
+ *                - RTL8306E_PRISRC_PPRI    - port-based otag priority, 
+ *                - RTL8306E_PRISRC_1PRMK - 1p remarking priority
+ */
+extern rtk_api_ret_t rtk_vlan_tagSrc_get(rtk_port_t port, rtk_vidSrc_t *pVidSrc, rtk_priSrc_t *pPriSrc);    
+
+
+
+/*Spanning Tree*/
+
+/* Function Name:
+ *      rtk_stp_mstpState_set
+ * Description:
+ *      Configure spanning tree state per port
+ * Input:
+ *      msti              - Multiple spanning tree instance, no use for RTL8306E
+ *      port              - Port id
+ *      stp_state       - Spanning tree state
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id
+ *      RT_ERR_MSTP_STATE        -  Invalid spanning tree status
+ * Note:
+ *      Because RTL8306E does not support multiple spanning tree, so msti is no use. 
+ *      There are four states supported by ASIC.
+ *          - STP_STATE_DISABLED
+ *          - STP_STATE_BLOCKING
+ *          - STP_STATE_LEARNING
+ *          - STP_STATE_FORWARDING
+ */
+extern rtk_api_ret_t rtk_stp_mstpState_set(rtk_stp_msti_id_t msti, rtk_port_t port, rtk_stp_state_t stp_state);
+
+/* Function Name:
+ *      rtk_stp_mstpState_get
+ * Description:
+ *      Get Configuration of spanning tree state per port
+ * Input:
+ *      msti              - Multiple spanning tree instance, no use for RTL8306E
+ *      port              - Port id
+ * Output:
+ *      pStp_state     - the pointer of Spanning tree state
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -  Failure
+ *      RT_ERR_PORT_ID              -  Invalid port id
+ *      RT_ERR_NULL_POINTER      -  Input parameter is null pointer
+ * Note:
+ *      Because RTL8306E does not support multiple spanning tree, so msti is no use. 
+ *      There are four states supported by ASIC.
+ *          - STP_STATE_DISABLED
+ *          - STP_STATE_BLOCKING
+ *          - STP_STATE_LEARNING
+ *          - STP_STATE_FORWARDING
+ */
+extern rtk_api_ret_t rtk_stp_mstpState_get(rtk_stp_msti_id_t msti, rtk_port_t port, rtk_stp_state_t *pStp_state);
+
+/* LUT */
+
+/* Function Name:
+ *      rtk_l2_addr_add
+ * Description:
+ *      Set LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast(I/G bit is 0) mac address to be written into LUT
+ *      pL2_data          -   the mac address attributes
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                       -  Success
+ *      RT_ERR_FAILED                 -   Failure
+ *      RT_ERR_INPUT                  -   Invalid input parameter
+ *      RT_ERR_MAC                    -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_NULL_POINTER       -  Input parameter is null pointer    
+ *      RT_ERR_L2_INDEXTBL_FULL -  The L2 index table is full
+ * Note:
+ *      If the unicast mac address already existed in LUT, it will udpate the status of the entry. 
+ *      Otherwise, it will find an empty or asic auto learned entry to write. If all the entries 
+ *      with the same hash value can't be replaced, ASIC will return a RT_ERR_L2_INDEXTBL_FULL error.
+ *      for RTL8306E, pL2_data member fid and sa_block is no use, so it can be chosen any value.
+ */
+extern rtk_api_ret_t rtk_l2_addr_add(rtk_mac_t *pMac, rtk_l2_ucastAddr_t *pL2_data);
+
+/* Function Name:
+ *      rtk_l2_addr_get
+ * Description:
+ *      Get LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast(I/G bit is 0) mac address to be gotten
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+ *      pL2_data          -   the mac address attributes
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_NULL_POINTER              -   Input parameter is null pointer    
+ *      RT_ERR_L2_ENTRY_NOTFOUND    -   Specified entry not found
+ * Note:
+ *      If the unicast mac address existed in LUT, it will return the port where
+ *      the mac is learned, 802.1x authorized status and dynamic/static entry,
+ *      Otherwise, it will return a RT_ERR_L2_ENTRY_NOTFOUND error.
+ */
+extern rtk_api_ret_t rtk_l2_addr_get(rtk_mac_t *pMac, rtk_fid_t fid, rtk_l2_ucastAddr_t *pL2_data);
+
+/* Function Name:
+ *      rtk_l2_addr_del
+ * Description:
+ *      Delete LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast mac address to be deleted
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_NULL_POINTER              -   Input parameter is null pointer    
+ *      RT_ERR_L2_ENTRY_NOTFOUND    -   Specified entry not found 
+ * Note:
+ *      If the mac has existed in the LUT, it will be deleted.
+ *      Otherwise, it will return RT_ERR_L2_ENTRY_NOTFOUND.
+ */
+extern rtk_api_ret_t rtk_l2_addr_del(rtk_mac_t *pMac, rtk_fid_t fid); 
+
+/* Function Name:
+ *      rtk_l2_mcastAddr_add
+ * Description:
+ *      Add LUT multicast entry
+ * Input:
+ *      pMac               -   6 bytes unicast mac address to be deleted
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ *      portmask          -   Port mask to be forwarded to 
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_PORT_MASK                  -   Invalid port mask
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_L2_INDEXTBL_FULL         -   Hashed index is full of entries
+ * Note:
+ *      If the multicast mac address already existed in the LUT, it will udpate the
+ *      port mask of the entry. Otherwise, it will find an empty or asic auto learned
+ *      entry to write. If all the entries with the same hash value can't be replaced, 
+ *      ASIC will return a RT_ERR_L2_INDEXTBL_FULL error.
+ */
+extern rtk_api_ret_t rtk_l2_mcastAddr_add(rtk_mac_t *pMac, rtk_fid_t fid, rtk_portmask_t portmask);
+
+/* Function Name:
+ *      rtk_l2_mcastAddr_get
+ * Description:
+ *      Get LUT multicast entry
+ * Input:
+ *      pMac               -   6 bytes multicast(I/G bit is 0) mac address to be gotten
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+ *      pPortmask         -   the pointer of port mask      
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_NULL_POINTER              -   Input parameter is null pointer    
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_L2_INDEXTBL_FULL         -   Hashed index is full of entries 
+ * Note:
+ *      If the multicast mac address existed in LUT, it will return the port mask where
+ *      the packet should be forwarded to, Otherwise, it will return a 
+ *      RT_ERR_L2_ENTRY_NOTFOUND error.
+ */
+extern rtk_api_ret_t rtk_l2_mcastAddr_get(rtk_mac_t *pMac, rtk_fid_t fid, rtk_portmask_t *pPortmask);
+
+/* Function Name:
+ *      rtk_l2_mcastAddr_del
+ * Description:
+ *      Delete LUT unicast entry
+ * Input:
+ *      pMac               -   6 bytes multicast(I/G bit is 1) mac address to be gotten
+ *      fid                   -   filtering database id, could be any value for RTL8306E switch
+ * Output:
+*       none
+ * Return:
+ *      RT_ERR_OK                               -  Success
+ *      RT_ERR_FAILED                         -   Failure
+ *      RT_ERR_INPUT                          -   Invalid input parameter
+ *      RT_ERR_MAC                            -   Wrong mac address, must be unicast mac        
+ *      RT_ERR_L2_ENTRY_NOTFOUND     -   No such LUT entry
+ * Note:
+ *      If the mac has existed in the LUT, it will be deleted.
+ *      Otherwise, it will return RT_ERR_L2_ENTRY_NOTFOUND.
+ */
+extern rtk_api_ret_t rtk_l2_mcastAddr_del(rtk_mac_t *pMac, rtk_fid_t fid);    
+
+/* Function Name:
+ *      rtk_l2_limitLearningCnt_set
+ * Description:
+ *      Set per-Port auto learning limit number
+ * Input:
+ *      port - Port id.
+ *      mac_cnt - Auto learning entries limit number
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - set shared meter successfully
+ *      RT_ERR_FAILED          - FAILED to iset shared meter
+ *      RT_ERR_PORT_ID - Invalid port number.
+ *      RT_ERR_LIMITED_L2ENTRY_NUM - Invalid auto learning limit number
+ * Note:
+ *      (1)The API can set per-port ASIC auto learning limit number from 0(disable learning) 
+ *      to 0x1F(31). 
+ *      (2)If mac_cnt is set from 0 to 0x1F, per-port ASIC auto learning limit will be enabled;
+ *      if mac_cnt is set 0xFF, per-port ASIC auto learning limit will be disabled.
+ */
+extern rtk_api_ret_t rtk_l2_limitLearningCnt_set(rtk_port_t port, rtk_mac_cnt_t mac_cnt);
+
+/* Function Name:
+ *      rtk_l2_limitLearningCnt_get
+ * Description:
+ *      Get per-Port auto learning limit number
+ * Input:
+ *      port - Port id.
+ * Output:
+ *      pMac_cnt - Auto learning entries limit number
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_PORT_ID - Invalid port number. 
+ * Note:
+ *      The API can get per-port ASIC auto learning limit number.
+ */
+extern rtk_api_ret_t rtk_l2_limitLearningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt);
+
+/* Function Name:
+ *      rtk_l2_limitLearningCntAction_set
+ * Description:
+ *      Configure auto learn over limit number action.
+ * Input:
+ *      port - Port id (must be RTK_WHOLE_SYSTEM)
+ *      action - Auto learning entries limit number
+ * Output:
+ *      None
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_PORT_ID - Invalid port number.
+ *      RT_ERR_NOT_ALLOWED - Invalid learn over action
+ * Note:
+ *      (1)The API can set SA unknown packet action while auto learn limit number is over. 
+ *      The action symbol as following:
+ *      - LIMIT_LEARN_CNT_ACTION_DROP,
+ *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
+ *      (2)The action is global, so the port must be set as RTK_WHOLE_SYSTEM
+ */
+extern rtk_api_ret_t rtk_l2_limitLearningCntAction_set(rtk_port_t port, rtk_l2_limitLearnCntAction_t action);
+
+/* Function Name:
+ *      rtk_l2_limitLearningCntAction_get
+ * Description:
+ *      Get auto learn over limit number action.
+ * Input:
+ *      port - Port id (must be RTK_WHOLE_SYSTEM)
+ * Output:
+ *      pAction - Learn over action
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_FAILED          - Failure 
+ *      RT_ERR_PORT_ID - Invalid port number. 
+ * Note:
+ *      (1)The API can get SA unknown packet action while auto learn limit number is over. 
+ *      The action symbol as following:
+ *      - LIMIT_LEARN_CNT_ACTION_DROP,
+ *      - LIMIT_LEARN_CNT_ACTION_TO_CPU,
+ *      (2)The action is global, so the port must be set as RTK_WHOLE_SYSTEM
+ */
+extern rtk_api_ret_t rtk_l2_limitLearningCntAction_get(rtk_port_t port, rtk_l2_limitLearnCntAction_t *pAction);
+
+/* Function Name:
+ *      rtk_l2_learningCnt_get
+ * Description:
+ *      Get per-Port current auto learning number
+ * Input:
+ *      port - Port id.
+ * Output:
+ *      pMac_cnt - ASIC auto learning entries number
+ * Return:
+ *      RT_ERR_OK              - Success
+ *      RT_ERR_PORT_ID - Invalid port number. 
+ *      RT_ERR_NULL_POINTER   -   Input parameter is null pointer  
+ * Note:
+ *      The API can get per-port ASIC auto learning number
+ */
+extern rtk_api_ret_t rtk_l2_learningCnt_get(rtk_port_t port, rtk_mac_cnt_t *pMac_cnt);
+
+/* CPU Port */
+
+/* Function Name:
+ *      rtk_cpu_enable_set
+ * Description:
+ *      Set cpu port function enable or disable
+ * Input:
+ *      enable          - enable or disable
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                        -  Success
+ *      RT_ERR_FAILED                  -   Failure
+ * Note:
+ *      The API can set CPU port function enable/disable
+ *      default port 4 is cpu port.
+ */
+extern rtk_api_ret_t rtk_cpu_enable_set(rtk_enable_t enable);
+
+/* Function Name:
+ *      rtk_cpu_enable_get
+ * Description:
+ *      Get cpu port function enable or disable
+ * Input:
+ *      none
+ * Output:
+ *      pEnable          -  the pointer of enable or disable cpu port function
+ * Return:
+ *      RT_ERR_OK                   -  Success
+ *      RT_ERR_FAILED             -   Failure
+ * Note:
+ *      The API can set CPU port function enable/disable
+ */
+extern rtk_api_ret_t rtk_cpu_enable_get(rtk_enable_t *pEnable);
+
+/* Function Name:
+ *      rtk_cpu_tagPort_set
+ * Description:
+ *      Set CPU port and CPU tag insert mode
+ * Input:
+ *      port          -  Port id
+ *      mode        -  CPU tag insert for packets egress from CPU port
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                   -  Success
+ *      RT_ERR_FAILED             -   Failure
+ *      RT_ERR_PORT_ID           -   Invalid port id
+ * Note:
+ *      The API can set CPU port and inserting proprietary CPU tag mode (Length/Type 0x8899)
+ *      to the frame that transmitting to CPU port.
+ *      The inset cpu tag mode is as following:
+ *          - CPU_INSERT_TO_ALL
+ *          - CPU_INSERT_TO_TRAPPING
+ *          - CPU_INSERT_TO_NONE   
+ */ 
+extern rtk_api_ret_t rtk_cpu_tagPort_set(rtk_port_t port, rtk_cpu_insert_t mode);
+
+/* Function Name:
+ *      rtk_cpu_tagPort_get
+ * Description:
+ *      Get CPU port and CPU tag insert mode
+ * Input:
+ *      port          -  Port id
+ * Output:
+ *      pMode       -  the pointer of CPU tag insert for packets egress from CPU port
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_NULL_POINTER      -   Input parameter is null pointer
+ * Note:
+ *      The API can set CPU port and inserting proprietary CPU tag mode (Length/Type 0x8899)
+ *      to the frame that transmitting to CPU port.
+ *      The inset cpu tag mode is as following:
+ *          - CPU_INSERT_TO_ALL
+ *          - CPU_INSERT_TO_TRAPPING
+ *          - CPU_INSERT_TO_NONE    
+ */
+
+extern rtk_api_ret_t rtk_cpu_tagPort_get(rtk_port_t *pPort, rtk_cpu_insert_t *pMode);
+
+
+/*Port Mirror */
+
+/* Function Name:
+ *      rtk_mirror_portBased_set
+ * Description:
+ *      Set port mirror function
+ * Input:
+ *      mirroring_port                  - Monitor port, 7 means no monitor port
+ *      pMirrored_rx_portmask      - the pointer of Rx mirror port mask
+ *      pMirrored_tx_portmask      - the pointer of Tx mirror port mask
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_PORT_MASK         -   Invalid port mask
+ * Note:
+ *      The API is to set mirror function of source port and mirror port. 
+ */
+extern rtk_api_ret_t rtk_mirror_portBased_set(rtk_port_t mirroring_port, rtk_portmask_t *pMirrored_rx_portmask, rtk_portmask_t *pMirrored_tx_portmask);
+
+/* Function Name:
+ *      rtk_mirror_portBased_get
+ * Description:
+ *      Get port mirror function
+ * Input:
+ *      none 
+ * Output:
+ *      pMirroring_port             - the pointer Monitor port, 7 means no monitor port
+ *      pMirrored_rx_portmask   - the pointer of Rx mirror port mask
+ *      pMirrored_tx_portmask   - the pointer of Tx mirror port mask 
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_PORT_MASK         -   Invalid port mask
+ *      RT_ERR_NULL_POINTER      -   Input parameter is null pointer 
+ * Note:
+ *      The API is to set mirror function of source port and mirror port. 
+ */
+extern rtk_api_ret_t rtk_mirror_portBased_get(rtk_port_t* pMirroring_port, rtk_portmask_t *pMirrored_rx_portmask, rtk_portmask_t *pMirrored_tx_portmask);
+
+/* 802.1X */
+
+/* Function Name:
+ *      rtk_dot1x_unauthPacketOper_set
+ * Description:
+ *      Set 802.1x unauth action configuration
+ * Input:
+ *      port                 -   Port id, no use for RTL8306E switch
+ *      unauth_action   -   802.1X unauth action    
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_DOT1X_PROC
+ * Note:
+ *      This API can set 802.1x unauth action configuration, 
+ *      for RTL8306E switch, the action is by whole system,
+ *      so port could be any value of 0~6.
+ *      The unauth action is as following:
+ *          - DOT1X_ACTION_DROP
+ *          - DOT1X_ACTION_TRAP2CPU
+ */
+
+extern rtk_api_ret_t rtk_dot1x_unauthPacketOper_set(rtk_port_t port, rtk_dot1x_unauth_action_t unauth_action);
+
+/* Function Name:
+ *      rtk_dot1x_unauthPacketOper_get
+ * Description:
+ *      Get 802.1x unauth action configuration
+ * Input:
+ *      port                  -   Port id, no use for RTL8306E switch
+ * Output:
+ *      pUnauth_action   -  the pointer of 802.1X unauth action    
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_NULL_POINTER      -   Input parameter is null pointer
+ * Note:
+ *      This API can set 802.1x unauth action configuration, 
+ *      for RTL8306E switch, the action is by whole system,
+ *      so port could be any value of 0~6.
+ *      The unauth action is as following:
+ *          - DOT1X_ACTION_DROP
+ *          - DOT1X_ACTION_TRAP2CPU
+ */
+extern rtk_api_ret_t rtk_dot1x_unauthPacketOper_get(rtk_port_t port, rtk_dot1x_unauth_action_t *pUnauth_action);
+
+/* Function Name:
+ *      rtk_dot1x_portBasedEnable_set
+ * Description:
+ *      Set 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ *      enable               -   enable or disable
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                      -  Success
+ *      RT_ERR_FAILED                -   Failure
+ *      RT_ERR_PORT_ID              -   Invalid port id
+ * Note:
+ *      The API can update the port-based port enable register content. If a port is 802.1x 
+ *      port based network access control "enabled", it should be authenticated so packets 
+ *      from that port won't be dropped or trapped to CPU. 
+ *      The status of 802.1x port-based network access control is as following:
+ *          - DISABLED
+ *          - ENABLED
+ */    
+extern rtk_api_ret_t rtk_dot1x_portBasedEnable_set(rtk_port_t port, rtk_enable_t enable);
+
+/* Function Name:
+ *      rtk_dot1x_portBasedEnable_get
+ * Description:
+ *      Get 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pEnable             -   the pointer of enable or disable
+ * Return:
+ *      RT_ERR_OK                -  Success
+ *      RT_ERR_FAILED          -   Failure
+ *      RT_ERR_PORT_ID        -   Invalid port id
+ * Note:
+ *      The API can update the port-based port enable register content. If a port is 802.1x 
+ *      port based network access control "enabled", it should be authenticated so packets 
+ *      from that port won't be dropped or trapped to CPU. 
+ *      The status of 802.1x port-based network access control is as following:
+ *          - DISABLED
+ *          - ENABLED
+ */    
+extern rtk_api_ret_t rtk_dot1x_portBasedEnable_get(rtk_port_t port, rtk_enable_t *pEnable);
+
+/* Function Name:
+ *      rtk_dot1x_portBasedAuthStatus_set
+ * Description:
+ *      Set 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ *      port_auth          -  The status of 802.1x port
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                    -  Success
+ *      RT_ERR_FAILED                              -   Failure
+ *      RT_ERR_PORT_ID                            -   Invalid port id
+ *      RT_ERR_DOT1X_PORTBASEDAUTH      -   Port-based auth port error
+ * Note:
+ *      The authenticated status of 802.1x port-based network access control is as following:
+ *          - UNAUTH
+ *          - AUTH
+ */    
+extern rtk_api_ret_t rtk_dot1x_portBasedAuthStatus_set(rtk_port_t port, rtk_dot1x_auth_status_t port_auth);
+
+/* Function Name:
+ *      rtk_dot1x_portBasedAuthStatus_get
+ * Description:
+ *      Get 802.1x port-based enable configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pPort_auth         -   the pointer of the status of 802.1x port
+ * Return:
+ *      RT_ERR_OK                          -  Success
+ *      RT_ERR_FAILED                     -  Failure
+ *      RT_ERR_PORT_ID                   -  Invalid port id
+ *      RT_ERR_NULL_POINTER           -  Input parameter is null pointer
+ * Note:
+ *      The authenticated status of 802.1x port-based network access control is as following:
+ *          - UNAUTH
+ *          - AUTH
+ */    
+extern rtk_api_ret_t rtk_dot1x_portBasedAuthStatus_get(rtk_port_t port, rtk_dot1x_auth_status_t *pPort_auth);
+
+/* Function Name:
+ *      rtk_dot1x_portBasedDirection_set
+ * Description:
+ *      Set 802.1x port-based operational direction configuration
+ * Input:
+ *      port                  -   Port id
+ *      port_direction     -   Operation direction
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                 -  Success
+ *      RT_ERR_FAILED                           -  Failure
+ *      RT_ERR_PORT_ID                         -  Invalid port id
+ *      RT_ERR_DOT1X_PORTBASEDOPDIR  -  Port-based opdir error
+ * Note:
+ *      The operate controlled direction of 802.1x port-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */    
+extern rtk_api_ret_t rtk_dot1x_portBasedDirection_set(rtk_port_t port, rtk_dot1x_direction_t port_direction);
+
+/* Function Name:
+ *      rtk_dot1x_portBasedDirection_get
+ * Description:
+ *      Get 802.1x port-based operational direction configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pPort_direction    -   the pointer of Operation direction
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_PORT_ID                  -  Invalid port id
+ *      RT_ERR_NULL_POINTER          -  Input parameter is null pointer
+ * Note:
+ *      The operate controlled direction of 802.1x port-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */    
+extern rtk_api_ret_t rtk_dot1x_portBasedDirection_get(rtk_port_t port, rtk_dot1x_direction_t *pPort_direction);
+
+/* Function Name:
+ *      rtk_dot1x_macBasedEnable_set
+ * Description:
+ *      Set 802.1x mac-based port enable configuration
+ * Input:
+ *      port                  -   Port id
+ *      enable               -   The status of 802.1x mac-base funtion
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                         -  Success
+ *      RT_ERR_FAILED                    -  Failure
+ *      RT_ERR_PORT_ID                  -  Invalid port id
+ * Note:
+ *     If a port is 802.1x MAC based network access control "enabled", the incoming packets should 
+ *     be authenticated so packets from that port won't be dropped or trapped to CPU.
+ *     The status of 802.1x MAC-based network access control is as following:
+ *         - DISABLED
+ *         - ENABLED
+ */    
+extern rtk_api_ret_t rtk_dot1x_macBasedEnable_set(rtk_port_t port, rtk_enable_t enable);
+
+/* Function Name:
+ *      rtk_dot1x_macBasedEnable_get
+ * Description:
+ *      Get 802.1x mac-based port enable configuration
+ * Input:
+ *      port                  -   Port id
+ * Output:
+ *      pEnable             -   the pointer of the status of 802.1x mac-base funtion
+ * Return:
+ *      RT_ERR_OK               -  Success
+ *      RT_ERR_FAILED         -   Failure
+ * Note:
+ *     If a port is 802.1x MAC based network access control "enabled", the incoming packets should 
+ *     be authenticated so packets from that port won't be dropped or trapped to CPU.
+ *     The status of 802.1x MAC-based network access control is as following:
+ *         - DISABLED
+ *         - ENABLED
+ */    
+extern rtk_api_ret_t rtk_dot1x_macBasedEnable_get(rtk_port_t port, rtk_enable_t *pEnable);
+
+/* Function Name:
+ *      rtk_dot1x_macBasedDirection_set
+ * Description:
+ *      Set 802.1x mac-based operational direction configuration
+ * Input:
+ *      mac_direction    -   Operation direction
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                    -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_DOT1X_MACBASEDOPDIR      -  MAC-based opdir error
+ * Note:
+ *      The operate controlled direction of 802.1x mac-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */     
+extern rtk_api_ret_t rtk_dot1x_macBasedDirection_set(rtk_dot1x_direction_t mac_direction);
+
+/* Function Name:
+ *      rtk_dot1x_macBasedDirection_get
+ * Description:
+ *      Get 802.1x mac-based operational direction configuration
+ * Input:
+ *      none
+ * Output:
+ *      pMac_direction    -   the pointer of Operation direction
+ * Return:
+ *      RT_ERR_OK                                    -  Success
+ *      RT_ERR_FAILED                              -  Failure
+ *      RT_ERR_NULL_POINTER                    -  Input parameter is null pointer
+ * Note:
+ *      The operate controlled direction of 802.1x mac-based network access control is as following:
+ *          - BOTH
+ *          - IN
+ */  
+extern rtk_api_ret_t rtk_dot1x_macBasedDirection_get(rtk_dot1x_direction_t *pMac_direction);
+
+/* Function Name:
+ *      rtk_dot1x_macBasedAuthMac_add
+ * Description:
+ *      Add an authenticated MAC to ASIC
+ * Input:
+ *      port            -  Port id
+ *      pAuth_mac   - The authenticated MAC
+ *      fid              -  no use for RTL8306E   
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                       - Success
+ *      RT_ERR_FAILED                                 -  Failure
+ *      RT_ERR_L2_ENTRY_NOTFOUND             -  Specified entry not found
+ *      RT_ERR_DOT1X_MAC_PORT_MISMATCH  - Auth MAC and port mismatch eror 
+ * Note:
+ *     The API can add a 802.1x authenticated MAC address to port. If the MAC does not exist in LUT, 
+ *     user can't add this MAC to auth status.
+ */    
+extern rtk_api_ret_t rtk_dot1x_macBasedAuthMac_add(rtk_port_t port, rtk_mac_t *pAuth_mac, rtk_fid_t fid);
+
+/* Function Name:
+ *      rtk_dot1x_macBasedAuthMac_del
+ * Description:
+ *      Delete an authenticated MAC to ASIC
+ * Input:
+ *      port            -  Port id
+ *      pAuth_mac   - The authenticated MAC
+ *      fid              -  no use for RTL8306E   
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK                                       - Success
+ *      RT_ERR_FAILED                                 -  Failure
+ *      RT_ERR_L2_ENTRY_NOTFOUND             -  Specified entry not found
+ *      RT_ERR_DOT1X_MAC_PORT_MISMATCH  - Auth MAC and port mismatch eror 
+ * Note:
+ *     The API can delete a 802.1x authenticated MAC address to port. It only change the auth status of
+ *     the MAC and won't delete it from LUT.
+ */    
+extern rtk_api_ret_t rtk_dot1x_macBasedAuthMac_del(rtk_port_t port, rtk_mac_t *pAuth_mac, rtk_fid_t fid);
+
+
+/* Function Name:
+ *      rtk_svlan_init
+ * Description:
+ *      Initialize SVLAN Configuration
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ *      RT_ERR_INPUT
+ * Note:
+ *    Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 
+ *    0x9100 and 0x9200 for Q-in-Q SLAN design. User can set mathced ether 
+ *    type as service provider supported protocol. After call this API, all ports are 
+ *    set as CVLAN port. you can use rtk_svlan_servicePort_add to add SVLAN port. 
+ */
+extern rtk_api_ret_t rtk_svlan_init(void);
+
+/* Function Name:
+ *      rtk_svlan_servicePort_add
+ * Description:
+ *      Enable one service port in the specified device
+ * Input:
+ *      port     -  Port id
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ * Note:
+ *    This API is setting which port is connected to provider switch. All frames receiving from this port
+ *    will recognize Service Vlan Tag.
+ *    
+ */
+extern rtk_api_ret_t rtk_svlan_servicePort_add(rtk_port_t port);
+
+
+/* Function Name:
+ *      rtk_svlan_servicePort_del
+ * Description:
+ *      Disable one service port in the specified device
+ * Input:
+ *      none
+ * Output:
+ *      pSvlan_portmask  - svlan ports mask
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type
+ *      0x9100 and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+extern rtk_api_ret_t rtk_svlan_servicePort_del(rtk_port_t port);
+
+/* Function Name:
+ *      rtk_svlan_servicePort_get
+ * Description:
+ *      Disable one service port in the specified device
+ * Input:
+ *      none
+ * Output:
+ *      pSvlan_portmask  - svlan ports mask
+ * Return:
+ *      RT_ERR_OK                 - success
+ *      RT_ERR_FAILED            -  fail
+ *      RT_ERR_NULL_POINTER  -  null pointer
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 
+ *      and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+extern rtk_api_ret_t rtk_svlan_servicePort_get(rtk_portmask_t *pSvlan_portmask);
+
+/* Function Name:
+ *      rtk_svlan_tpidEntry_set
+ * Description:
+ *      Configure accepted S-VLAN ether type. The default ether type of S-VLAN is 0x88a8
+ * Input:
+ *      svlan_tag_id  - Ether type of S-tag frame parsing in uplink ports
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 
+ *      and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+extern rtk_api_ret_t rtk_svlan_tpidEntry_set(rtk_svlan_tpid_t svlan_tag_id);
+
+
+/* Function Name:
+ *      rtk_svlan_tpidEntry_get
+ * Description:
+ *      Get accepted S-VLAN ether type. The default ether type of S-VLAN is 0x88a8
+ * Input:
+ *      pSvlan_tag_id       - Ether type of S-tag frame parsing in uplink ports
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ * Note:
+ *      Ether type of S-tag in 802.1ad is 0x88a8 and there are existed ether type 0x9100 
+ *      and 0x9200 for Q-in-Q SLAN design. User can set mathced ether type as service 
+ *      provider supported protocol. 
+ */
+extern rtk_api_ret_t rtk_svlan_tpidEntry_get(rtk_svlan_tpid_t *pSvlan_tag_id);
+
+
+/* Function Name:
+ *      rtk_svlan_portPvid_set
+ * Description:
+ *      Set port to specified VLAN ID(PVID) for Service Provider Port
+ * Input:
+ *      port             - Port id
+ *      pvid             - Specified Service VLAN ID
+ *      priority         - 802.1p priority for the PVID
+ *      dei               - Service VLAN tag DEI bit
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_VLAN_VID
+ *      RT_ERR_SMI 
+ *      RT_ERR_VLAN_PRIORITY 
+ *      RT_ERR_VLAN_ENTRY_NOT_FOUND
+ * Note:
+ *    The API is used for Port-based VLAN. The untagged frame received from the
+ *    port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+extern rtk_api_ret_t rtk_svlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority, rtk_dei_t dei);
+
+/* Function Name:
+ *      rtk_svlan_portPvid_get
+ * Description:
+ *      Get Service VLAN ID(PVID) on specified port
+ * Input:
+ *      port             - Port id
+ *      pPvid            - Specified VLAN ID
+ *      pPriority        - 802.1p priority for the PVID
+ *      pDei             - DEI bit
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_SMI
+ *      RT_ERR_PORT_ID
+ *      RT_ERR_NULL_POINTER 
+ * Note:
+ *    The API is used for Port-based VLAN. The untagged frame received from the
+ *    port will be classified to the specified VLAN and assigned to the specified priority.
+ */
+extern rtk_api_ret_t rtk_svlan_portPvid_get(rtk_port_t port, rtk_vlan_t *pPvid, rtk_pri_t* pPriority, rtk_dei_t *pDei);
+
+/* Function Name:
+ *      rtk_filter_igrAcl_init
+ * Description:
+ *       Initialize ACL 
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ * Note:
+ *      The API init ACL module.
+ */
+extern rtk_api_ret_t rtk_filter_igrAcl_init(void);
+
+/* Function Name:
+ *      rtk_filter_igrAcl_rule_add
+ * Description:
+ *      Add an acl rule into acl table
+ * Input:
+ *      pRule    -  the pointer of rule structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_TBL_FULL
+ *      RT_ERR_NULL_POINTER
+ * Note:
+ *      The API add an  ACL rule. <nl>
+ *      phyport could be  0~5: port number,  RTL8306_ACL_ANYPORT: any port;<nl>
+ *      protocol could be RTL8306_ACL_ETHER(ether type), RTL8306_ACL_TCP(TCP), RTL8306_ACL_UDP(UDP), RTL8306_ACL_TCPUDP(TCP or UDP);<nl>
+ *      prority could be RTL8306_PRIO0~RTL8306_PRIO3;<nl>
+ *      action could be RTL8306_ACT_DROP/RTL8306_ACT_PERMIT/RTL8306_ACT_TRAPCPU/RTL8306_ACT_MIRROR;<nl>
+ */
+
+extern rtk_api_ret_t rtk_filter_igrAcl_rule_add(rtk_filter_rule_t *pRule);
+
+/* Function Name:
+ *      rtk_filter_igrAcl_rule_get
+ * Description:
+ *      Get ACL rule priority and action 
+ * Input:
+ *      pRule    -  the pointer of rule structure
+ * Output:
+ *      pRule    -  the pointer of rule structure
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ * Note:
+ *      The API add an  ACL rule. <nl>
+ *      phyport could be  0~5: port number,  RTL8306_ACL_ANYPORT: any port;<nl>
+ *      protocol could be RTL8306_ACL_ETHER(ether type), RTL8306_ACL_TCP(TCP), RTL8306_ACL_UDP(UDP), RTL8306_ACL_TCPUDP(TCP or UDP);<nl>
+ *      prority could be RTL8306_PRIO0~RTL8306_PRIO3;<nl>
+ *      action could be RTL8306_ACT_DROP/RTL8306_ACT_PERMIT/RTL8306_ACT_TRAPCPU/RTL8306_ACT_MIRROR;<nl>
+ */
+extern rtk_api_ret_t rtk_filter_igrAcl_rule_get(rtk_filter_rule_t *pRule);
+
+
+
+/* Function Name:
+ *      rtk_filter_igrAcl_rule_del
+ * Description:
+ *      Delete an acl rule into acl table
+ * Input:
+ *      pRule    -  the pointer of rule structure
+ * Output:
+ *      none
+ * Return:
+ *      RT_ERR_OK
+ *      RT_ERR_FAILED
+ *      RT_ERR_INPUT
+ *      RT_ERR_NULL_POINTER
+ * Note:
+ *      The API delete an  ACL rule. <nl>
+ *      only phyport/protocol/data field in pRule needs to be specified.
+ */
+extern rtk_api_ret_t rtk_filter_igrAcl_rule_del(rtk_filter_rule_t *pRule);
+
+/*add at 2012-2-13*/
+extern rtk_api_ret_t rtk_mib_get(rtk_port_t port, rtk_mib_counter_t counter, rtk_mib_cntValue_t *pValue);
+extern rtk_api_ret_t rtk_mib_cntType_set(rtk_port_t port, rtk_mib_counter_t counter,rtk_mib_cntType_t type);
+extern rtk_api_ret_t rtk_mib_cntType_get(rtk_port_t port, rtk_mib_counter_t counter,rtk_mib_cntType_t *pType);
+extern rtk_api_ret_t rtk_mib_reset(rtk_port_t port);
+
+#endif   /*__RTK_API_EXT_H__*/
+
+
+
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_error.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_error.h
new file mode 100644
index 0000000..ebbb5ea
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtk_error.h
@@ -0,0 +1,231 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 10083 $ 
+* $Date: 2010-06-07 11:18:41 +0800 (星期一, 2010-06-07) $
+*
+* Purpose : Definition the error number in the SDK
+*
+* Feature :  This file consists of following modules:
+*                
+*
+*/
+
+#ifndef __RTL_ERROR_H__
+#define __RTL_ERROR_H__
+
+/*
+ * Data Type Declaration
+ */
+typedef enum rt_error_code_e
+{
+    RT_ERR_FAILED = -1,                             /* General Error                                                                    */
+
+    /* 0x00xx for common error code */
+    RT_ERR_OK = 0,                                    /* 0x0000, OK                                                                   */
+    RT_ERR_INPUT,                                     /* 0x0001, invalid input parameter                                              */
+    RT_ERR_UNIT_ID,                                  /* 0x0002, invalid unit id                                                      */
+    RT_ERR_PORT_ID,                                 /* 0x0003, invalid port id                                                      */
+    RT_ERR_PORT_MASK,                            /* 0x0004, invalid port mask                                                    */
+    RT_ERR_PORT_LINKDOWN,                    /* 0x0005, link down port status                                                */
+    RT_ERR_ENTRY_INDEX,                         /* 0x0006, invalid entry index                                                  */
+    RT_ERR_NULL_POINTER,                       /* 0x0007, input parameter is null pointer                                      */
+    RT_ERR_QUEUE_ID,                             /* 0x0008, invalid queue id                                                     */
+    RT_ERR_QUEUE_NUM,                               /* 0x0009, invalid queue number                                                 */
+    RT_ERR_BUSYWAIT_TIMEOUT,                        /* 0x000a, busy watting time out                                                */
+    RT_ERR_MAC,                                     /* 0x000b, invalid mac address                                                  */
+    RT_ERR_OUT_OF_RANGE,                            /* 0x000c, input parameter out of range                                         */
+    RT_ERR_CHIP_NOT_SUPPORTED,                      /* 0x000d, functions not supported by this chip model                           */
+    RT_ERR_SMI,                                     /* 0x000e, SMI error                                                            */
+    RT_ERR_NOT_INIT,                                /* 0x000f, The module is not initial                                            */
+    RT_ERR_CHIP_NOT_FOUND,                          /* 0x0010, The chip can not found                                               */
+    RT_ERR_NOT_ALLOWED,                             /* 0x0011, actions not allowed by the function                                  */
+    RT_ERR_DRIVER_NOT_FOUND,                        /* 0x0012, The driver can not found                                             */
+    RT_ERR_SEM_LOCK_FAILED,                         /* 0x0013, Failed to lock semaphore                                             */
+    RT_ERR_SEM_UNLOCK_FAILED,                       /* 0x0014, Failed to unlock semaphore                                           */
+    RT_ERR_ENABLE,                                  /* 0x0015, invalid enable parameter                                             */
+    RT_ERR_TBL_FULL,                                /* 0x0016, input table full                                                     */
+
+    /* 0x01xx for vlan */
+    RT_ERR_VLAN_VID = 0x0100,                       /* 0x0100, invalid vid                                                          */
+    RT_ERR_VLAN_PRIORITY,                           /* 0x0101, invalid 1p priority                                                  */
+    RT_ERR_VLAN_EMPTY_ENTRY,                        /* 0x0102, emtpy entry of vlan table                                            */
+    RT_ERR_VLAN_ACCEPT_FRAME_TYPE,                  /* 0x0103, invalid accept frame type                                            */
+    RT_ERR_VLAN_EXIST,                              /* 0x0104, vlan is exist                                                        */
+    RT_ERR_VLAN_ENTRY_NOT_FOUND,                    /* 0x0105, specified vlan entry not found                                       */
+    RT_ERR_VLAN_PORT_MBR_EXIST,                     /* 0x0106, member port exist in the specified vlan                              */
+    RT_ERR_VLAN_PROTO_AND_PORT,                     /* 0x0108, invalid protocol and port based vlan                              */
+
+    /* 0x02xx for svlan */
+    RT_ERR_SVLAN_ENTRY_INDEX = 0x0200,              /* 0x0200, invalid svid entry no                                                */
+    RT_ERR_SVLAN_ETHER_TYPE,                        /* 0x0201, invalid SVLAN ether type                                             */
+    RT_ERR_SVLAN_TABLE_FULL,                        /* 0x0202, no empty entry in SVLAN table                                        */
+    RT_ERR_SVLAN_ENTRY_NOT_FOUND,                   /* 0x0203, specified svlan entry not found                                      */
+    RT_ERR_SVLAN_EXIST,                             /* 0x0204, SVLAN entry is exist                                                 */
+    RT_ERR_SVLAN_VID,                               /* 0x0205, invalid svid                                                         */
+
+    /* 0x03xx for MSTP */
+    RT_ERR_MSTI = 0x0300,                           /* 0x0300, invalid msti                                                         */
+    RT_ERR_MSTP_STATE,                              /* 0x0301, invalid spanning tree status                                         */
+    RT_ERR_MSTI_EXIST,                              /* 0x0302, MSTI exist                                                           */
+    RT_ERR_MSTI_NOT_EXIST,                          /* 0x0303, MSTI not exist                                                       */
+
+    /* 0x04xx for BUCKET */
+    RT_ERR_TIMESLOT = 0x0400,                       /* 0x0400, invalid time slot                                                    */
+    RT_ERR_TOKEN,                                   /* 0x0401, invalid token amount                                                 */
+    RT_ERR_RATE,                                    /* 0x0402, invalid rate                                                         */
+    RT_ERR_TICK,                                    /* 0x0403, invalid tick                                                 */
+
+    /* 0x05xx for RMA */
+    RT_ERR_RMA_ADDR = 0x0500,                       /* 0x0500, invalid rma mac address                                              */
+    RT_ERR_RMA_ACTION,                              /* 0x0501, invalid rma action                                                   */
+
+    /* 0x06xx for L2 */
+    RT_ERR_L2_HASH_KEY = 0x0600,                    /* 0x0600, invalid L2 Hash key                                                  */
+    RT_ERR_L2_HASH_INDEX,                           /* 0x0601, invalid L2 Hash index                                                */
+    RT_ERR_L2_CAM_INDEX,                            /* 0x0602, invalid L2 CAM index                                                 */
+    RT_ERR_L2_ENRTYSEL,                             /* 0x0603, invalid EntrySel                                                     */
+    RT_ERR_L2_INDEXTABLE_INDEX,                     /* 0x0604, invalid L2 index table(=portMask table) index                        */
+    RT_ERR_LIMITED_L2ENTRY_NUM,                     /* 0x0605, invalid limited L2 entry number                                      */
+    RT_ERR_L2_AGGREG_PORT,                          /* 0x0606, this aggregated port is not the lowest physical
+                                                               port of its aggregation group                                        */
+    RT_ERR_L2_FID,                                  /* 0x0607, invalid fid                                                          */
+    RT_ERR_L2_RVID,                                 /* 0x0608, invalid cvid                                                         */
+    RT_ERR_L2_NO_EMPTY_ENTRY,                       /* 0x0609, no empty entry in L2 table                                           */
+    RT_ERR_L2_ENTRY_NOTFOUND,                       /* 0x060a, specified entry not found                                            */
+    RT_ERR_L2_INDEXTBL_FULL,                        /* 0x060b, the L2 index table is full                                           */
+    RT_ERR_L2_INVALID_FLOWTYPE,                     /* 0x060c, invalid L2 flow type                                                 */
+    RT_ERR_L2_L2UNI_PARAM,                          /* 0x060d, invalid L2 unicast parameter                                         */
+    RT_ERR_L2_L2MULTI_PARAM,                        /* 0x060e, invalid L2 multicast parameter                                       */
+    RT_ERR_L2_IPMULTI_PARAM,                        /* 0x060f, invalid L2 ip multicast parameter                                    */
+    RT_ERR_L2_PARTIAL_HASH_KEY,                     /* 0x0610, invalid L2 partial Hash key                                          */
+    RT_ERR_L2_EMPTY_ENTRY,                          /* 0x0611, the entry is empty(invalid)                                          */
+    RT_ERR_L2_FLUSH_TYPE,                           /* 0x0612, the flush type is invalid                                            */
+    RT_ERR_L2_NO_CPU_PORT,                          /* 0x0613, CPU port not exist                                                   */
+
+    /* 0x07xx for FILTER (PIE) */
+    RT_ERR_FILTER_BLOCKNUM = 0x0700,                /* 0x0700, invalid block number                                                 */
+    RT_ERR_FILTER_ENTRYIDX,                         /* 0x0701, invalid entry index                                                  */
+    RT_ERR_FILTER_CUTLINE,                          /* 0x0702, invalid cutline value                                                */
+    RT_ERR_FILTER_FLOWTBLBLOCK,                     /* 0x0703, block belongs to flow table                                          */
+    RT_ERR_FILTER_INACLBLOCK,                       /* 0x0704, block belongs to ingress ACL                                         */
+    RT_ERR_FILTER_ACTION,                           /* 0x0705, action doesn't consist to entry type                                 */
+    RT_ERR_FILTER_INACL_RULENUM,                    /* 0x0706, invalid ACL rulenum                                                  */
+    RT_ERR_FILTER_INACL_TYPE,                       /* 0x0707, entry type isn't an ingress ACL rule                                 */
+    RT_ERR_FILTER_INACL_EXIST,                      /* 0x0708, ACL entry is already exit                                            */
+    RT_ERR_FILTER_INACL_EMPTY,                      /* 0x0709, ACL entry is empty                                                   */
+    RT_ERR_FILTER_FLOWTBL_TYPE,                     /* 0x070a, entry type isn't an flow table rule                                  */
+    RT_ERR_FILTER_FLOWTBL_RULENUM,                  /* 0x070b, invalid flow table rulenum                                           */
+    RT_ERR_FILTER_FLOWTBL_EMPTY,                    /* 0x070c, flow table entry is empty                                            */
+    RT_ERR_FILTER_FLOWTBL_EXIST,                    /* 0x070d, flow table entry is already exist                                    */
+    RT_ERR_FILTER_METER_ID,                         /* 0x070e, invalid metering id                                                  */
+    RT_ERR_FILTER_LOG_ID,                           /* 0x070f, invalid log id                                                       */
+    RT_ERR_FILTER_INACL_ACT_NOT_SUPPORT,            /* 0x0710, rule not support                                                     */        
+    RT_ERR_FILTER_INACL_RULE_NOT_SUPPORT,           /* 0x0710, action not support                                                   */    
+
+    /* 0x08xx for ACL Rate Limit */
+    RT_ERR_ACLRL_HTHR = 0x0800,                     /* 0x0800, invalid high threshold                                               */
+    RT_ERR_ACLRL_TIMESLOT,                          /* 0x0801, invalid time slot                                                    */
+    RT_ERR_ACLRL_TOKEN,                             /* 0x0802, invalid token amount                                                 */
+    RT_ERR_ACLRL_RATE,                              /* 0x0803, invalid rate                                                         */
+
+    /* 0x09xx for Link aggregation */
+    RT_ERR_LA_CPUPORT = 0x0900,                     /* 0x0900, CPU port can not be aggregated port                                  */
+    RT_ERR_LA_TRUNK_ID,                             /* 0x0901, invalid trunk id                                                     */
+    RT_ERR_LA_PORTMASK,                             /* 0x0902, invalid port mask                                                    */
+    RT_ERR_LA_HASHMASK,                             /* 0x0903, invalid hash mask                                                    */
+    RT_ERR_LA_DUMB,                                 /* 0x0904, this API should be used in 802.1ad dumb mode                         */
+    RT_ERR_LA_PORTNUM_DUMB,                         /* 0x0905, it can only aggregate at most four ports when 802.1ad dumb mode      */
+    RT_ERR_LA_PORTNUM_NORMAL,                       /* 0x0906, it can only aggregate at most eight ports when 802.1ad normal mode   */
+    RT_ERR_LA_MEMBER_OVERLAP,                       /* 0x0907, the specified port mask is overlapped with other group               */
+    RT_ERR_LA_NOT_MEMBER_PORT,                      /* 0x0908, the port is not a member port of the trunk                           */
+    RT_ERR_LA_TRUNK_NOT_EXIST,                      /* 0x0909, the trunk doesn't exist                                              */
+
+
+    /* 0x0axx for storm filter */
+    RT_ERR_SFC_TICK_PERIOD = 0x0a00,                /* 0x0a00, invalid SFC tick period                                              */
+    RT_ERR_SFC_UNKNOWN_GROUP,                       /* 0x0a01, Unknown Storm filter group                                           */
+
+    /* 0x0bxx for pattern match */
+    RT_ERR_PM_MASK = 0x0b00,                        /* 0x0b00, invalid pattern length. Pattern length should be 8                   */
+    RT_ERR_PM_LENGTH,                               /* 0x0b01, invalid pattern match mask, first byte must care                     */
+    RT_ERR_PM_MODE,                                 /* 0x0b02, invalid pattern match mode                                           */
+
+    /* 0x0cxx for input bandwidth control */
+    RT_ERR_INBW_TICK_PERIOD = 0x0c00,               /* 0x0c00, invalid tick period for input bandwidth control                      */
+    RT_ERR_INBW_TOKEN_AMOUNT,                       /* 0x0c01, invalid amount of token for input bandwidth control                  */
+    RT_ERR_INBW_FCON_VALUE,                         /* 0x0c02, invalid flow control ON threshold value for input bandwidth control  */
+    RT_ERR_INBW_FCOFF_VALUE,                        /* 0x0c03, invalid flow control OFF threshold value for input bandwidth control */
+    RT_ERR_INBW_FC_ALLOWANCE,                       /* 0x0c04, invalid allowance of incomming packet for input bandwidth control    */
+    RT_ERR_INBW_RATE,                               /* 0x0c05, invalid input bandwidth                                              */
+
+    /* 0x0dxx for QoS */
+    RT_ERR_QOS_1P_PRIORITY = 0x0d00,                /* 0x0d00, invalid 802.1P priority                                              */
+    RT_ERR_QOS_DSCP_VALUE,                          /* 0x0d01, invalid DSCP value                                                   */
+    RT_ERR_QOS_INT_PRIORITY,                        /* 0x0d02, invalid internal priority                                            */
+    RT_ERR_QOS_SEL_DSCP_PRI,                        /* 0x0d03, invalid DSCP selection priority                                      */
+    RT_ERR_QOS_SEL_PORT_PRI,                        /* 0x0d04, invalid port selection priority                                      */
+    RT_ERR_QOS_SEL_IN_ACL_PRI,                      /* 0x0d05, invalid ingress ACL selection priority                               */
+    RT_ERR_QOS_SEL_CLASS_PRI,                       /* 0x0d06, invalid classifier selection priority                                */
+    RT_ERR_QOS_EBW_RATE,                            /* 0x0d07, invalid egress bandwidth rate                                        */
+    RT_ERR_QOS_SCHE_TYPE,                           /* 0x0d08, invalid QoS scheduling type                                          */
+    RT_ERR_QOS_QUEUE_WEIGHT,                        /* 0x0d09, invalid Queue weight                                                 */
+    RT_ERR_QOS_SEL_PRI_SOURCE,                      /* 0x0d0a, invalid selection of priority source                                                 */
+    
+    /* 0x0exx for port ability */
+    RT_ERR_PHY_PAGE_ID = 0x0e00,                    /* 0x0e00, invalid PHY page id                                                  */
+    RT_ERR_PHY_REG_ID,                              /* 0x0e01, invalid PHY reg id                                                   */
+    RT_ERR_PHY_DATAMASK,                            /* 0x0e02, invalid PHY data mask                                                */
+    RT_ERR_PHY_AUTO_NEGO_MODE,                      /* 0x0e03, invalid PHY auto-negotiation mode*/
+    RT_ERR_PHY_SPEED,                               /* 0x0e04, invalid PHY speed setting                                            */
+    RT_ERR_PHY_DUPLEX,                              /* 0x0e05, invalid PHY duplex setting                                           */
+    RT_ERR_PHY_FORCE_ABILITY,                       /* 0x0e06, invalid PHY force mode ability parameter                             */
+    RT_ERR_PHY_FORCE_1000,                          /* 0x0e07, invalid PHY force mode 1G speed setting                              */
+    RT_ERR_PHY_TXRX,                                /* 0x0e08, invalid PHY tx/rx                                                    */
+
+    /* 0x0fxx for mirror */
+    RT_ERR_MIRROR_DIRECTION = 0x0f00,               /* 0x0f00, invalid error mirror direction                                       */
+    RT_ERR_MIRROR_SESSION_FULL,                     /* 0x0f01, mirroring session is full                                            */
+    RT_ERR_MIRROR_SESSION_NOEXIST,                  /* 0x0f02, mirroring session not exist                                          */
+    RT_ERR_MIRROR_PORT_EXIST,                       /* 0x0f03, mirroring port already exists                                        */
+    RT_ERR_MIRROR_PORT_NOT_EXIST,                   /* 0x0f04, mirroring port does not exists                                       */
+    RT_ERR_MIRROR_PORT_FULL,                        /* 0x0f05, Exceeds maximum number of supported mirroring port                   */
+
+    /* 0x10xx for stat */
+    RT_ERR_STAT_INVALID_GLOBAL_CNTR = 0x1000,       /* 0x1000, Invalid Global Counter                                               */
+    RT_ERR_STAT_INVALID_PORT_CNTR,                  /* 0x1001, Invalid Port Counter                                                 */
+    RT_ERR_STAT_GLOBAL_CNTR_FAIL,                   /* 0x1002, Could not retrieve/reset Global Counter                              */
+    RT_ERR_STAT_PORT_CNTR_FAIL,                     /* 0x1003, Could not retrieve/reset Port Counter                                */
+
+    /* 0x1100 for dot1x */
+    RT_ERR_DOT1X_INVALID_DIRECTION = 0x1100,        /* 0x1100, Invalid Authentication Direction                                     */
+    RT_ERR_DOT1X_PORTBASEDPNEN,                     /* 0x1101, Port-based enable port error                                         */
+    RT_ERR_DOT1X_PORTBASEDAUTH,                     /* 0x1102, Port-based auth port error                                           */
+    RT_ERR_DOT1X_PORTBASEDOPDIR,                    /* 0x1103, Port-based opdir error                                               */
+    RT_ERR_DOT1X_MACBASEDPNEN,                      /* 0x1104, MAC-based enable port error                                          */
+    RT_ERR_DOT1X_MACBASEDOPDIR,                     /* 0x1105, MAC-based opdir error                                                */
+    RT_ERR_DOT1X_PROC,                              /* 0x1106, unauthorized behavior error                                          */
+    RT_ERR_DOT1X_GVLANIDX,                          /* 0x1107, guest vlan index error                                               */
+    RT_ERR_DOT1X_GVLANTALK,                         /* 0x1108, guest vlan OPDIR error                                               */
+    RT_ERR_DOT1X_MAC_PORT_MISMATCH,                 /* 0x1109, Auth MAC and port mismatch eror                                      */
+
+    /* 0x1200 for jumbo */
+    RT_ERR_JUMBO_FRAME_SIZE = 0x1200,               /* Jumbo frame size not supported */
+    
+    RT_ERR_END                                       /* The symbol is the latest symbol                                                  */
+} rt_error_code_t;    
+
+
+#endif /*__RTL_ERROR_H__*/
+
+
+
+
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asicdrv.c b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asicdrv.c
new file mode 100644
index 0000000..f5f32e0
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asicdrv.c
@@ -0,0 +1,8839 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 26889 $ 
+* $Date: 2012-02-28 21:08:47 +0800 (星期二, 2012-02-28) $
+*
+* Purpose : asic-level driver implementation for RTL8306E switch
+*
+*  Feature :  This file consists of following modules:
+*                1) 
+*
+*/
+#include <linux/spinlock.h> 
+#include <linux/delay.h>
+#include <mach/iomap.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>  
+#include <linux/slab.h>  
+#include <linux/mii.h> 
+#include "rtl8306e_types.h"
+#include "rtl8306e_asicdrv.h"
+#include "rtk_api.h"
+//#ifndef RTK_X86_ASICDRV
+//#include "mdcmdio.h"
+//#endif
+//rtk_mode_ext_e rtk_mode_ext_t;
+//rtk_mode_ext_t *Mode;
+//rtk_port_mac_ability_t portAbility;
+extern rtk_api_ret_t rtk_cpu_enable_set(rtk_enable_t enable);
+extern rtk_api_ret_t rtk_cpu_tagPort_set(rtk_port_t port, rtk_cpu_insert_t mode);
+extern rtk_api_ret_t rtk_port_isolation_set(rtk_port_t port, rtk_portmask_t portmask);
+extern rtk_api_ret_t rtk_port_phyReg_get(rtk_port_t phy, rtk_port_phy_reg_t reg, rtk_port_phy_data_t *pData); 
+extern rtk_api_ret_t rtk_port_macForceLinkExt0_set(rtk_mode_ext_t mode, rtk_port_mac_ability_t *pPortability);
+extern rtk_api_ret_t rtk_vlan_get(rtk_vlan_t vid, rtk_portmask_t *pMbrmsk, rtk_portmask_t *pUntagmsk, rtk_fid_t *pFid);
+extern rtk_api_ret_t rtk_vlan_portPvid_get(rtk_port_t port, rtk_vlan_t *pPvid, rtk_pri_t *pPriority);
+extern rtk_api_ret_t rtk_vlan_init(void);
+extern rtk_api_ret_t rtk_vlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority);
+extern rtk_api_ret_t rtk_vlan_set(rtk_vlan_t vid, rtk_portmask_t mbrmsk, rtk_portmask_t untagmsk, rtk_fid_t fid);
+extern rtk_api_ret_t rtk_vlan_portAcceptFrameType_set(rtk_port_t port, rtk_vlan_acceptFrameType_t accept_frame_type);
+extern rtk_api_ret_t rtk_vlan_destroy(rtk_vlan_t vid);
+
+extern int smiRead(int phyad, int regad,int * data);
+extern int smiWrite(int phyad, int regad, int data);
+extern struct net_device* 	gmac_net_dev;
+volatile unsigned long virt, phys;//用于存放虚拟地址和物理地址
+#ifdef RTL8306_LUT_CACHE
+RTL8306_LUT rtl8306_LutCache[RTL8306_MAX_LUT_NUM];
+#endif
+#ifdef RTL8306_TBLBAK        
+rtl8306_ConfigBakPara_t rtl8306_TblBak; 
+#endif 
+
+int switch_ioctl (struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg);
+int switch_open(struct inode *inode, struct file *file);
+static int switch_probe(struct platform_device *dev);
+int switch_remove(struct platform_device *dev);
+static int switch_drv_init(void);
+static int switch_drv_exit(void);
+static unsigned int switch_major; 
+static struct cdev *switch_cdev = NULL; 
+static struct class *switch_class = NULL;	 
+	 
+	 /* Function Name:
+ *      rtl8306e_reg_set
+ * Description:
+ *      Write Asic Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      npage   - Specify page number (0 ~3)
+ *      value    - Value to be write into the register
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could write all configurable registers of RTL8306, 
+ *      it is realized by calling functions smiRead and smiWrite which are switch
+ *      MDC/MDIO interface access functions. Those two functions use two GPIO 
+ *      pins to simulate MDC/MDIO timing,  and they are based on rtl8651b platform,
+ *      to modify them,  you can port all asic API to other platform.
+ */
+
+int32 rtl8306e_reg_set(uint32 phyad, uint32 regad, uint32 npage, uint32 value) 
+{
+    uint32 rdata; 
+
+    if ((phyad >= RTL8306_PHY_NUMBER) || (npage >= RTL8306_PAGE_NUMBER))
+        return FAILED;
+    
+    /* Select PHY Register Page through configuring PHY 0 Register 16 [bit1 bit15] */
+    value = value & 0xFFFF;
+    smiRead(0, 16, &rdata); 
+    switch (npage) 
+    {
+        case RTL8306_REGPAGE0:
+            smiWrite(0, 16, (rdata & 0x7FFF) | 0x0002);
+            break;
+        case RTL8306_REGPAGE1:
+            smiWrite(0, 16, rdata | 0x8002 );
+            break;
+        case RTL8306_REGPAGE2:
+            smiWrite(0, 16, rdata & 0x7FFD);
+            break;
+        case RTL8306_REGPAGE3:
+            smiWrite(0, 16, (rdata & 0xFFFD) | 0x8000);
+            break;
+        case RTL8306_REGPAGE4:
+            smiRead(5, 16, &rdata);
+            rdata |= 0x2;
+            smiWrite(5, 16, rdata);
+            break;                        
+        default:
+            return FAILED;
+    }
+
+    smiWrite(phyad, regad, value);
+    
+    if(RTL8306_REGPAGE4 == npage)
+    {
+        /*exit page 4*/
+        smiRead(5, 16, &rdata);
+        rdata &= ~0x2;
+        smiWrite(5, 16, rdata);        
+    }
+    
+    return SUCCESS;
+    
+
+}
+
+
+/* Function Name:
+ *      rtl8306e_reg_get
+ * Description:
+ *      Read Asic Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      npage   - Specify page number (0 ~3)
+ * Output:
+ *      pvalue    - The pointer of value read back from register
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could write all configurable registers of RTL8306, 
+ *      it is realized by calling functions smiRead and smiWrite which are switch
+ *      MDC/MDIO interface access functions. Those two functions use two GPIO 
+ *      pins to simulate MDC/MDIO timing,  and they are based on rtl8651b platform,
+ *      to modify them,  you can port all asic API to other platform.
+ */
+ 
+int32  rtl8306e_reg_get(uint32 phyad, uint32 regad, uint32 npage, uint32 *pvalue)
+{
+
+    uint32 rdata;
+
+    if ((phyad >= RTL8306_PHY_NUMBER) || (npage >= RTL8306_PAGE_NUMBER))
+        return FAILED;
+
+    /* Select PHY Register Page through configuring PHY 0 Register 16 [bit1 bit15] */
+    smiRead(0, 16, &rdata); 
+    switch (npage) 
+    {
+        case RTL8306_REGPAGE0:
+            smiWrite(0, 16, (rdata & 0x7FFF) | 0x0002);
+            break;
+        case RTL8306_REGPAGE1:
+            smiWrite(0, 16, rdata | 0x8002 );
+            break;
+        case RTL8306_REGPAGE2:
+            smiWrite(0, 16, rdata & 0x7FFD);
+            break;
+        case RTL8306_REGPAGE3:
+            smiWrite(0, 16, (rdata & 0xFFFD) | 0x8000);
+            break;
+        case RTL8306_REGPAGE4:
+            smiRead(5, 16, &rdata);
+            rdata |= 0x2;
+            smiWrite(5, 16, rdata);            
+            break;
+        default:
+            return FAILED;
+    }
+
+    smiRead(phyad, regad, pvalue);
+
+    *pvalue = *pvalue & 0xFFFF;
+    if(RTL8306_REGPAGE4 == npage)
+    {
+        /*exit page 4*/
+        smiRead(5, 16, &rdata);
+        rdata &= ~0x2;
+        smiWrite(5, 16, rdata);        
+    }
+        
+    return SUCCESS;
+
+}
+
+
+/* Function Name:
+ *      rtl8306e_regbit_set
+ * Description:
+ *      Write one bit of Asic Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      bit        - Specify bit position(0 ~ 15)
+ *      npage   - Specify page number (0 ~3)
+ *      value    - Value to be write(0, 1)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function  you could write each bit of  all configurable registers of RTL8306.
+ */
+
+int32 rtl8306e_regbit_set(uint32 phyad, uint32 regad, uint32 bit, uint32 npage,  uint32 value) 
+{
+    uint32 rdata;
+    
+    if ((phyad >= RTL8306_PHY_NUMBER) || (npage >= RTL8306_PAGE_NUMBER) ||
+        (bit > 15) || (value > 1))
+        return FAILED;
+    
+    rtl8306e_reg_get(phyad, regad,  npage, &rdata);
+    if (value) 
+        rtl8306e_reg_set(phyad, regad, npage, rdata | (1 << bit));
+    else
+        rtl8306e_reg_set(phyad, regad, npage, rdata & (~(1 << bit)));
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_regbit_get
+ * Description:
+ *      Read one bit of Asic  PHY Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      bit        - Specify bit position(0 ~ 15)
+ *      npage   - Specify page number (0 ~3)
+ * Output:
+ *      pvalue  - The pointer of value read back
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could read each bit of  all configurable registers of RTL8306
+ */
+
+int32 rtl8306e_regbit_get(uint32 phyad, uint32 regad, uint32 bit, uint32 npage,  uint32 * pvalue) 
+{
+    uint32 rdata;
+
+    if ((phyad >= RTL8306_PHY_NUMBER) || (npage >= RTL8306_PAGE_NUMBER) || 
+        (bit > 15) || (pvalue == NULL))
+        return FAILED;
+    
+    rtl8306e_reg_get(phyad, regad, npage, &rdata);
+    if (rdata & (1 << bit))
+        *pvalue =1;
+    else 
+        *pvalue =0;
+
+    return SUCCESS;
+}
+
+int32 rtl8306e_phyReg_set(uint32 phyad, uint32 regad, uint32 npage, uint32 value) 
+{
+
+
+    uint32 rdata;
+    uint32 regval; 
+
+    if ((phyad >= RTL8306_PHY_NUMBER) || (npage > 0x5))
+        return FAILED;
+
+    /*read/write pcs register*/
+    smiRead(5, 16, &rdata); 
+    smiWrite(5, 16, rdata|0x0001);
+
+    /*Select PHY Register Page*/
+    smiRead(phyad, 31, &regval);
+    regval &= ~0xFF;
+    regval |= npage;
+    smiWrite(phyad, 31, regval);
+
+    smiWrite(phyad, regad, value);
+
+    smiWrite(5, 16, rdata & (~0x0001));
+    
+    return SUCCESS;
+}
+
+int32 rtl8306e_phyReg_get(uint32 phyad, uint32 regad, uint32 npage, uint32 *pvalue)
+{
+
+    uint32 rdata;
+    uint32 regval; 
+
+    if ((phyad >= RTL8306_PHY_NUMBER) || (npage > 0x5))
+        return FAILED;
+
+    /*read/write pcs register*/
+    smiRead(5, 16, &rdata);
+    smiWrite(5, 16, rdata|0x0001);
+
+    /*Select PHY Register Page*/
+    smiRead(phyad, 31, &regval);
+    regval &= ~0xFF;
+    regval |= npage;
+    smiWrite(phyad, 31, regval);
+    													
+    smiRead(phyad, regad, pvalue);
+
+    *pvalue = *pvalue & 0xFFFF;
+
+    smiWrite(5, 16, rdata & (~0x0001));
+    
+    return SUCCESS;
+    
+
+}
+
+int32 rtl8306e_asic_init(void)
+{
+    uint32 regval;
+    uint32 regval2;
+    uint32 regval3;
+    uint32 phy;
+    
+    /*by default: enable xor lut hash algorithm*/
+    rtl8306e_regbit_set(1, 23, 12, 0, 1);
+
+#ifdef RTL8306_LUT_CACHE
+    memset(rtl8306_LutCache, 0, sizeof(rtl8306_LutCache));
+#endif
+
+    rtl8306e_regbit_set(0, 16, 11, 0, 1);
+    rtl8306e_regbit_set(4, 23, 5, 0, 1); 
+    rtl8306e_reg_get(4, 30, 0, &regval);
+    rtl8306e_reg_get(4, 26, 0, &regval2);
+    rtl8306e_regbit_set(0, 16, 11, 0, 0);
+    rtl8306e_regbit_set(4, 23, 5, 0, 0); 
+    if (0x6167 == regval)
+    {
+        if ((((regval2 & (0x7<<13)) >> 13) == 1) || (((regval2 & (0x7<<13)) >> 13) == 2))
+        {
+            for (phy = 0; phy <= 4; phy++)
+            {
+                rtl8306e_phyReg_get(phy, 22, 0, &regval3);
+                regval3 &= ~(0x1 << 14);
+                rtl8306e_phyReg_set(phy, 22, 0, regval3);        
+            }
+        }
+        if (((regval2 & (0x7<<13)) >> 13) == 1)
+        {
+            rtl8306e_regbit_set(0, 19, 2, 0, 0);
+            rtl8306e_regbit_set(4, 23, 8, 0, 1);
+            rtl8306e_reg_get(0, 31, 3, &regval3);
+            regval3 &= ~0x3;
+            regval3 |= 0x2;
+            rtl8306e_reg_set(0, 31, 3, regval3);
+            rtl8306e_reg_get(1, 31, 3, &regval3);
+            regval3 &= ~0x3;
+            regval3 |= 0x2;
+            rtl8306e_reg_set(1, 31, 3, regval3);
+            rtl8306e_reg_get(2, 31, 3, &regval3);
+            regval3 &= ~0x3;
+            regval3 |= 0x2;
+            rtl8306e_reg_set(2, 31, 3, regval3);
+            rtl8306e_reg_get(3, 31, 3, &regval3);
+            regval3 &= ~0x3;
+            regval3 |= 0x2;
+            rtl8306e_reg_set(3, 31, 3, regval3);
+            rtl8306e_reg_get(5, 31, 3, &regval3);
+            regval3 &= ~0x3;
+            regval3 |= 0x2;
+            rtl8306e_reg_set(5, 31, 3, regval3);
+            rtl8306e_regbit_set(4, 23, 8, 0, 0);
+
+            rtl8306e_phyReg_get(0, 25, 4, &regval3);
+            regval3 &= ~(0x7 << 4);
+            regval3 |= (0x6 << 4);
+            rtl8306e_phyReg_set(0, 25, 4, regval3);
+
+            rtl8306e_phyReg_get(0, 28, 4, &regval3);
+            regval3 &= ~(0x1 << 8);
+            regval3 |= (0x1 << 8);
+            rtl8306e_phyReg_set(0, 28, 4, regval3);
+
+            rtl8306e_phyReg_set(0, 29, 4, 0x5000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x6000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x7000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x8700);
+            rtl8306e_phyReg_set(0, 29, 4, 0xD36C);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFFF);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCA6C);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFFD);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5060);
+            rtl8306e_phyReg_set(0, 29, 4, 0x61C5);
+            rtl8306e_phyReg_set(0, 29, 4, 0x7010);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4001);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5061);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4001);
+            rtl8306e_phyReg_set(0, 29, 4, 0x87F1);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCE60);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0026);
+            rtl8306e_phyReg_set(0, 29, 4, 0x8E03);
+            rtl8306e_phyReg_set(0, 29, 4, 0xA021);
+            rtl8306e_phyReg_set(0, 29, 4, 0x300F);
+            rtl8306e_phyReg_set(0, 29, 4, 0x58A0);
+            rtl8306e_phyReg_set(0, 29, 4, 0x629C);
+            rtl8306e_phyReg_set(0, 29, 4, 0x7010);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4002);
+            rtl8306e_phyReg_set(0, 29, 4, 0x58A1);
+            rtl8306e_phyReg_set(0, 29, 4, 0x87E6);
+            rtl8306e_phyReg_set(0, 29, 4, 0xAE25);
+            rtl8306e_phyReg_set(0, 29, 4, 0xA018);
+            rtl8306e_phyReg_set(0, 29, 4, 0x301A);
+            rtl8306e_phyReg_set(0, 29, 4, 0x6E94);
+            rtl8306e_phyReg_set(0, 29, 4, 0x6694);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5123);
+            rtl8306e_phyReg_set(0, 29, 4, 0x63C2);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5127);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4003);
+            rtl8306e_phyReg_set(0, 29, 4, 0x87DC);
+            rtl8306e_phyReg_set(0, 29, 4, 0x8EF3);
+            rtl8306e_phyReg_set(0, 29, 4, 0xA10E);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCC40);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0007);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCA40);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFDF);
+            rtl8306e_phyReg_set(0, 29, 4, 0xA202);
+            rtl8306e_phyReg_set(0, 29, 4, 0x3024);
+            rtl8306e_phyReg_set(0, 29, 4, 0x7018);
+            rtl8306e_phyReg_set(0, 29, 4, 0x3024);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCC44);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFF4);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCC44);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFF2);
+            rtl8306e_phyReg_set(0, 29, 4, 0x3000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5220);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4004);
+            rtl8306e_phyReg_set(0, 29, 4, 0x3000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x64A0);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5429);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4005);
+            rtl8306e_phyReg_set(0, 29, 4, 0x87C6);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCE18);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFC4);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCE64);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFCF);
+            rtl8306e_phyReg_set(0, 29, 4, 0x303A);
+            rtl8306e_phyReg_set(0, 29, 4, 0x65C0);
+            rtl8306e_phyReg_set(0, 29, 4, 0x50A9);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4006);
+            rtl8306e_phyReg_set(0, 29, 4, 0xA3DB);
+            rtl8306e_phyReg_set(0, 29, 4, 0x3043);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x60F3);
+            rtl8306e_phyReg_set(0, 29, 4, 0x5008);
+            rtl8306e_phyReg_set(0, 29, 4, 0x7010);
+            rtl8306e_phyReg_set(0, 29, 4, 0x4000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x87B6);
+            rtl8306e_phyReg_set(0, 29, 4, 0xA3B5);
+            rtl8306e_phyReg_set(0, 29, 4, 0xD36C);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFFD);
+            rtl8306e_phyReg_set(0, 29, 4, 0xCA68);
+            rtl8306e_phyReg_set(0, 29, 4, 0xFFBA);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+            rtl8306e_phyReg_set(0, 29, 4, 0x0000);
+
+            rtl8306e_phyReg_get(0, 28, 4, &regval3);
+            regval3 &= ~(0x1 << 8);
+            rtl8306e_phyReg_set(0, 28, 4, regval3);
+
+            rtl8306e_phyReg_get(0, 25, 4, &regval3);
+            regval3 &= ~(0x7 << 4);
+            regval3 |= (0x3 << 4);
+            rtl8306e_phyReg_set(0, 25, 4, regval3);
+
+            for (phy = 0; phy <= 4; phy++)
+            {
+                rtl8306e_phyReg_get(phy, 24, 4, &regval3);
+                regval3 &= ~(0xFF);
+                regval3 |= 0xF3;
+                rtl8306e_phyReg_set(phy, 24, 4, regval3);
+            }
+            
+            /*RTCT*/
+            for (phy = 0; phy <= 4; phy++)
+            {
+                rtl8306e_phyReg_get(phy, 16, 2, &regval3);
+                regval3 &= ~(0x3FF);
+                regval3 |= 0xFA;
+                rtl8306e_phyReg_set(phy, 16, 2, regval3);
+                rtl8306e_phyReg_get(phy, 22, 2, &regval3);
+                regval3 &= ~(0x7FF);
+                regval3 |= 0x12C;
+                rtl8306e_phyReg_set(phy, 22, 2, regval3);
+                rtl8306e_phyReg_get(phy, 23, 2, &regval3);
+                regval3 &= ~(0x3FF);
+                regval3 |= 0xC8;
+                rtl8306e_phyReg_set(phy, 23, 2, regval3);
+                rtl8306e_phyReg_get(phy, 24, 2, &regval3);
+                regval3 &= ~(0x1FF);
+                regval3 |= 0x32;
+                rtl8306e_phyReg_set(phy, 24, 2, regval3);
+                rtl8306e_phyReg_get(phy, 19, 2, &regval3);
+                regval3 &= ~(0xF << 12);
+                regval3 |= (0x4 << 12);
+                rtl8306e_phyReg_set(phy, 19, 2, regval3);
+                rtl8306e_phyReg_get(phy, 18, 2, &regval3);
+                regval3 &= ~(0x1F << 10);
+                regval3 |= (0x5 << 10);
+                rtl8306e_phyReg_set(phy, 18, 2, regval3);
+                rtl8306e_phyReg_get(phy, 25, 2, &regval3);
+                regval3 &= ~(0xFF << 8);
+                regval3 |= (0x4 << 8);
+                rtl8306e_phyReg_set(phy, 25, 2, regval3);
+                rtl8306e_phyReg_get(phy, 25, 2, &regval3);
+                regval3 &= ~0xFF;
+                regval3 |= 0x40;
+                rtl8306e_phyReg_set(phy, 25, 2, regval3);
+                
+            }
+        }    
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_phy_reset
+ * Description:
+ *      Reset the phy
+ * Input:
+ *      phy   - Specify Phy address (0 ~4)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+int32 rtl8306e_phy_reset(uint32 phy)
+{
+    uint32 regval, regval2;
+    uint32 nway, pause, dupSpd;
+    if (phy > 4)
+        return FAILED;
+    
+    rtl8306e_regbit_set(0, 16, 11, 0, 1);
+    rtl8306e_regbit_set(4, 23, 5, 0, 1); 
+    rtl8306e_reg_get(4, 30, 0, &regval);
+    rtl8306e_reg_get(4, 26, 0, &regval2);
+    rtl8306e_regbit_set(0, 16, 11, 0, 0);
+    rtl8306e_regbit_set(4, 23, 5, 0, 0); 
+    if ((0x6167 == regval) && ((regval2 & (0x7<<13)) >> 13 == 1))
+    {
+        rtl8306e_regbit_get(phy, 22, 6, 0, &nway);
+        rtl8306e_regbit_get(phy, 22, 3, 0, &pause);
+        rtl8306e_reg_get(phy, 22, 0, &dupSpd);
+          
+        rtl8306e_regbit_set(phy, 0, 15, 0, 1);
+        if (nway)
+        {
+            switch((dupSpd & (0x3 << 4)) >> 4)
+            {
+                case 0x3:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 1);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 1);
+                    break;
+                case 0x2:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 1);
+                    break;
+                case 0x1:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 1);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 1);
+                    break;
+                case 0x0:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 1);
+                    break;
+                default:
+                   break;
+            } 
+            rtl8306e_regbit_set(phy, 0, 12, 0, 1);
+            rtl8306e_regbit_set(phy, 0, 9, 0, 1);
+        }
+        else
+        {
+            rtl8306e_regbit_set(phy, 0, 12, 0, 0);
+            switch((dupSpd & (0x3 << 4)) >> 4)
+            {
+                case 0x3:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 1);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 0);
+                    break;
+                case 0x2:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 0);
+                    break;
+                case 0x1:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 1);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 1);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 0);
+                    break;
+                case 0x0:
+                    rtl8306e_regbit_set(phy, 0, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 0, 13, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 8, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 7, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 6, 0, 0);
+                    rtl8306e_regbit_set(phy, 4, 5, 0, 1);
+                    break;
+                default:
+                   break;
+            }  
+        }
+        
+        rtl8306e_regbit_set(phy, 4, 10, 0, pause);
+        
+    }
+    else
+        rtl8306e_regbit_set(phy, 0, 15, 0, 1);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_switch_maxPktLen_set
+ * Description:
+ *      set Max packet length which could be forwarded by
+ * Input:
+ *      maxLen         -  max packet length
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      maxLen could be set : 
+ *      RTL8306_MAX_PKT_LEN_1518 -1518 bytes without any tag; 1522 bytes: 
+ *              with VLAN tag or CPU tag, 1526 bytes with CPU and VLAN tag;
+ *      RTL8306_MAX_PKT_LEN_1536 - 1536 bytes (all tags counted);
+ *      RTL8306_MAX_PKT_LEN_1552 - 1552 bytes (all tags counted); 
+ *      RTL8306_MAX_PKT_LEN_2000 - 2000 bytes (all tags counted) 
+ *              
+ */ 
+
+int32 rtl8306e_switch_maxPktLen_set(uint32 maxLen)
+{
+    switch(maxLen)
+    {
+        case RTL8306_MAX_PKT_LEN_1518:
+            rtl8306e_regbit_set(2, 23, 1, 3, 1);
+            rtl8306e_regbit_set(0, 29, 15, 3, 0);
+            break;
+
+        case RTL8306_MAX_PKT_LEN_1536:
+            rtl8306e_regbit_set(2, 23, 1, 3, 0);
+            rtl8306e_regbit_set(0, 18, 14, 0, 1);
+            rtl8306e_regbit_set(0, 29, 15, 3, 0);            
+            break;
+
+        case RTL8306_MAX_PKT_LEN_1552:
+            rtl8306e_regbit_set(2, 23, 1, 3, 0);
+            rtl8306e_regbit_set(0, 18, 14, 0, 0);
+            rtl8306e_regbit_set(0, 29, 15, 3, 0);            
+            break;
+
+        case RTL8306_MAX_PKT_LEN_2000:
+            rtl8306e_regbit_set(0, 29, 15, 3, 1);
+            break;
+            
+        default:
+            return FAILED;
+
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_switch_maxPktLen_get
+ * Description:
+ *      set Max packet length which could be forwarded by
+ * Input:
+ *      none
+ * Output:
+ *      maxLen         -  max packet length
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      maxLen could be set : 
+ *      RTL8306_MAX_PKT_LEN_1518 -1518 bytes without any tag; 1522 bytes: 
+ *              with VLAN tag or CPU tag, 1526 bytes with CPU and VLAN tag;
+ *      RTL8306_MAX_PKT_LEN_1536 - 1536 bytes (all tags counted);
+ *      RTL8306_MAX_PKT_LEN_1552 - 1552 bytes (all tags counted); 
+ *      RTL8306_MAX_PKT_LEN_2000 - 2000 bytes (all tags counted) 
+ *              
+ */ 
+int32 rtl8306e_switch_maxPktLen_get(uint32 *pMaxLen)
+{
+    uint32 regval;
+
+    if (pMaxLen == NULL)
+        return FAILED;
+    
+    rtl8306e_regbit_get(0, 29, 15, 3, &regval);
+    if(regval)
+    {
+        *pMaxLen = RTL8306_MAX_PKT_LEN_2000;
+    }
+    else
+    {
+        rtl8306e_regbit_get(2, 23, 1, 3, &regval);
+        if (regval)
+        {
+            *pMaxLen = RTL8306_MAX_PKT_LEN_1518;
+        }
+        else 
+        {
+            rtl8306e_regbit_get(0, 18, 14, 0, &regval);
+            if (regval)
+            {
+                *pMaxLen = RTL8306_MAX_PKT_LEN_1536;            
+            }
+            else
+            {
+                *pMaxLen = RTL8306_MAX_PKT_LEN_1552;                        
+            }
+        }
+    }
+    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_port_etherPhy_set
+ * Description:
+ *      Configure PHY setting
+ * Input:
+ *      phy                    - Specify the phy to configure
+ *      autoNegotiation    - Specify whether enable auto-negotiation
+ *      advCapability       - When auto-negotiation is enabled, specify the advertised capability
+ *      speed                 - When auto-negotiation is disabled, specify the force mode speed
+ *      fullDuplex            - When auto-negotiatoin is disabled, specify the force mode duplex mode
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      When auto-negotiation is enabled, the advertisement capability is used to handshaking with link partner.
+ *      When auto-negotiation is disabled, the phy is configured into force mode and the speed and duplex mode 
+ *      setting is based on speed and fullDuplex setting.Port number should be smaller than RTL8306_PHY_NUMBER.
+ *      AdverCapability should be ranged between RTL8306_ETHER_AUTO_100FULL and RTL8306_ETHER_AUTO_10HALF.
+ *      Speed should be either RTL8306_ETHER_SPEED_100 or RTL8306_ETHER_SPEED_10.
+ */
+int32 rtl8306e_port_etherPhy_set(uint32 phy, uint32 autoNegotiation, uint32 advCapability, uint32 speed, uint32 fullDuplex) 
+{
+    uint32 ctrlReg;
+
+    if(phy >= RTL8306_PHY_NUMBER || 
+       advCapability < RTL8306_ETHER_AUTO_100FULL ||
+       advCapability > RTL8306_ETHER_AUTO_10HALF ||
+       (speed != 100 && speed != 10))
+           return FAILED;
+
+    if(RTL8306_ETHER_AUTO_100FULL == advCapability)
+        rtl8306e_reg_set(phy, 4, 0, RTL8306_CAPABLE_PAUSE | RTL8306_CAPABLE_100BASE_TX_FD 
+                                  | RTL8306_CAPABLE_100BASE_TX_HD | RTL8306_CAPABLE_10BASE_TX_FD 
+                                  | RTL8306_CAPABLE_10BASE_TX_HD | 0x1);
+    else if(RTL8306_ETHER_AUTO_100HALF == advCapability)
+        rtl8306e_reg_set(phy, 4, 0, RTL8306_CAPABLE_PAUSE | RTL8306_CAPABLE_100BASE_TX_HD
+                                  | RTL8306_CAPABLE_10BASE_TX_FD | RTL8306_CAPABLE_10BASE_TX_HD | 0x1);
+    else if( RTL8306_ETHER_AUTO_10FULL == advCapability)
+        rtl8306e_reg_set(phy, 4, 0, RTL8306_CAPABLE_PAUSE | RTL8306_CAPABLE_10BASE_TX_FD 
+                                  | RTL8306_CAPABLE_10BASE_TX_HD | 0x1);
+    else if(RTL8306_ETHER_AUTO_10HALF == advCapability)
+        rtl8306e_reg_set(phy, 4, 0, RTL8306_CAPABLE_PAUSE | RTL8306_CAPABLE_10BASE_TX_HD | 0x1);
+
+    /*Each time the link ability of the RTL8306 is reconfigured, 
+     *the auto-negotiation process should be executed to allow
+     *the configuration to take effect. 
+     */
+    if(TRUE == autoNegotiation) 
+        ctrlReg = RTL8306_ENABLE_AUTONEGO | RTL8306_RESTART_AUTONEGO; 
+    else
+        ctrlReg = 0;
+    if(100 == speed) 
+        ctrlReg |= RTL8306_SPEED_SELECT_100M;
+    if(TRUE == fullDuplex)
+        ctrlReg |= RTL8306_SELECT_FULL_DUPLEX;
+    rtl8306e_reg_set(phy, 0, RTL8306_REGPAGE0, ctrlReg);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_port_etherPhy_get
+ * Description:
+ *       Get PHY setting
+ * Input:
+ *      phy                    - Specify the phy to configure
+ * Output:
+ *      pAutoNegotiation    - Get whether auto-negotiation is enabled
+ *      pAdvCapability       - When auto-negotiation is enabled, Get the advertised capability
+ *      pSpeed                 - When auto-negotiation is disabled, Get the force mode speed
+ *      pFullDuplex            - When auto-negotiatoin is disabled, Get the force mode duplex mode
+
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      When auto-negotiation is enabled, the advertisement capability is used to handshaking with link partner.
+ *      When auto-negotiation is disabled, the phy is configured into force mode and the speed and duplex mode 
+ *      setting is based on speed and fullDuplex setting.Port number should be smaller than RTL8306_PHY_NUMBER.
+ *      AdverCapability should be ranged between RTL8306_ETHER_AUTO_100FULL and RTL8306_ETHER_AUTO_10HALF.
+ *      Speed should be either RTL8306_ETHER_SPEED_100 or RTL8306_ETHER_SPEED_10.
+ */
+
+int32 rtl8306e_port_etherPhy_get(uint32 phy, uint32 *pAutoNegotiation, uint32 *pAdvCapability, uint32 *pSpeed, uint32 *pFullDuplex)
+{
+    uint32 regData;
+
+    if((phy >= RTL8306_PHY_NUMBER) || (NULL == pAutoNegotiation) || (NULL == pAdvCapability)
+        || (NULL ==  pSpeed) || (NULL == pFullDuplex))
+        return FAILED;
+
+    rtl8306e_reg_get(phy, 0, RTL8306_REGPAGE0, &regData);
+    *pAutoNegotiation = (regData & RTL8306_ENABLE_AUTONEGO) ? TRUE: FALSE;
+    *pSpeed = (regData & RTL8306_SPEED_SELECT_100M) ? 100: 10;
+    *pFullDuplex = (regData & RTL8306_SELECT_FULL_DUPLEX) ? TRUE: FALSE;
+
+    rtl8306e_reg_get(phy, 4, RTL8306_REGPAGE0, &regData);
+    if(regData & RTL8306_CAPABLE_100BASE_TX_FD)
+        *pAdvCapability = RTL8306_ETHER_AUTO_100FULL;
+    else if(regData & RTL8306_CAPABLE_100BASE_TX_HD)
+        *pAdvCapability = RTL8306_ETHER_AUTO_100HALF;
+    else if(regData & RTL8306_CAPABLE_10BASE_TX_FD)
+        *pAdvCapability = RTL8306_ETHER_AUTO_10FULL;
+    else if(regData & RTL8306_CAPABLE_10BASE_TX_HD)
+        *pAdvCapability = RTL8306_ETHER_AUTO_10HALF;
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_port_port5LinkStatus_set
+ * Description:
+ *      Force port 5 link up or link down
+ * Input:
+ *      enabled   - true or false
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Port 5 should be manully enable / disable
+ */
+int32 rtl8306e_port_port5LinkStatus_set(uint32 enabled) 
+{
+    uint32 duplex, speed, nway;
+
+    /*save phy 6 reg 0.13, 0.12, 0.8*/
+    rtl8306e_regbit_get(6, 0, 13, 0, &speed);
+    rtl8306e_regbit_get(6, 0, 12, 0, &nway);
+    rtl8306e_regbit_get(6, 0, 8, 0, &duplex);
+      
+    rtl8306e_regbit_set(6, 22, 15, 0, enabled ? 1:0);
+    
+    /*restore phy 6 reg 0.13, 0.12, 0.8*/
+    rtl8306e_regbit_set(6, 0, 13, 0, speed);
+    rtl8306e_regbit_set(6, 0, 12, 0, nway);
+    rtl8306e_regbit_set(6, 0, 8, 0, duplex);
+
+    return SUCCESS;       
+}
+
+/* Function Name:
+ *      rtl8306e_port_port5LinkStatus_get
+ * Description:
+ *      get port 5 link status
+ * Input:
+ *      none
+ * Output:
+*      enabled   - true or false
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Port 5 should be manully enable / disable
+ */
+
+int32 rtl8306e_port_port5LinkStatus_get(uint32 *pEnabled)
+{
+    uint32 bitValue;
+
+    if (NULL == pEnabled) 
+        return FAILED;
+    
+    rtl8306e_regbit_get(6, 22, 15, 0, &bitValue);
+    *pEnabled = (bitValue ? TRUE : FALSE);
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_port_phyLinkStatus_get
+ * Description:
+ *      Get PHY Link Status
+ * Input:
+*      phy        - Specify the phy 
+ * Output:
+*      plinkUp   - Describe whether link status is up or not
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       Read the link status of PHY register 1
+ */
+
+int32 rtl8306e_port_phyLinkStatus_get(uint32 phy, uint32 *plinkUp) 
+{
+    uint32 bitValue;
+
+    if (NULL == plinkUp)
+        return FAILED;
+    
+    rtl8306e_regbit_get(phy, 1, 2, RTL8306_REGPAGE0, &bitValue);
+    rtl8306e_regbit_get(phy, 1, 2, RTL8306_REGPAGE0, &bitValue);    
+    *plinkUp = (bitValue ? TRUE: FALSE);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_port_phyAutoNegotiationDone_get
+ * Description:
+ *      Get PHY auto-negotiation result status
+ * Input:
+ *      phy      - Specify the phy to get status
+ * Output:
+*      pDone   -  Describe whether auto-negotiation is done or not
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Read the auto-negotiation complete of PHY register 1.
+ */
+
+int32 rtl8306e_port_phyAutoNegotiationDone_get(uint32 phy, uint32 *pDone) 
+{
+    uint32 bitValue;
+
+    if (NULL == pDone)
+        return FAILED;
+    
+    rtl8306e_regbit_get(phy, 1, 5, 0, &bitValue);
+    *pDone = (bitValue ? TRUE: FALSE);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_port_phyLoopback_set
+ * Description:
+ *       Set PHY loopback
+ * Input:
+ *      phy         - Specify the phy to configure
+ *      enabled   - Enable phy loopback
+ * Output:
+ *      none      
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Only phy 0~4 could be configured the phy loopback
+ */
+
+int32 rtl8306e_port_phyLoopback_set(uint32 phy, uint32 enabled) 
+{
+    if(phy > 4)
+        return FAILED;
+    rtl8306e_regbit_set(phy, 0, 14, 0, enabled ? 1 : 0);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_port_phyLoopback_get
+ * Description:
+ *      Get PHY loopback setting
+ * Input:
+ *      phy         - Specify the phy to get status
+ * Output:
+ *      pEnabled  -  phy loopback setting
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+
+int32 rtl8306e_port_phyLoopback_get(uint32 phy, uint32 *pEnabled) 
+{
+    uint32 bitValue;
+
+    if (NULL == pEnabled)
+        return FAILED;
+    
+    rtl8306e_regbit_get(phy, 0, 14, 0, &bitValue);
+    *pEnabled = (bitValue ? TRUE: FALSE);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_portLearningAbility_set
+ * Description:
+ *      Enable/disable physical port learning ability
+ * Input:
+ *      port        - Specify port number (0 ~ 5)
+ * Output:
+ *      enabled -  TRUE or FALSE
+ * Return:
+ *      SUCCESS
+ * Note:
+ *
+ */
+int32 rtl8306e_portLearningAbility_set(uint32 port, uint32 enabled)
+{
+    if (port > RTL8306_PORT5)
+        return FAILED;
+    if (RTL8306_PORT5 == port)
+        port++;
+
+    rtl8306e_regbit_set(port, 24, 9, 0, enabled ? 1 : 0);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_port_isolation_set
+ * Description:
+ *      set port isolation 
+ * Input:
+ *      isomsk    - port isolation port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each bit of isomsk determine two port's isolation,
+ *      1 means two port could not forward packet between
+ *      each other.
+ *      bit 0  - Port0 & Port1 
+ *      bit 1  - Port0 & Port2 
+ *      bit 2  - Port0 & Port3
+ *      bit 3  - Port0 & Port4
+ *      bit 4  - Port0 & Port5
+ *      bit 5  - Port1 & Port2
+ *      bit 6  - Port1 & Port3
+ *      bit 7  - Port1 & Port4
+ *      bit 8  - Port1 & Port5
+ *      bit 9  - Port2 & Port3
+ *      bit 10 - Port2 & Port4
+ *      bit 11 - Port2 & Port5
+ *      bit 12 - Port3 & Port4
+ *      bit 13 - Port3 & Port5
+ *      bit 14 - Port4 & Port5
+ */
+
+int32 rtl8306e_port_isolation_set(uint32 isomsk)
+{
+    uint32 regval;
+
+    rtl8306e_reg_get(0, 29, 3, &regval);
+    regval &= ~0x7FFF;
+    regval |= isomsk & 0x7FFF;
+    rtl8306e_reg_set(0, 29, 3, regval);
+    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_port_isolation_set
+ * Description:
+ *      set port isolation 
+ * Input:
+ *      none
+ * Output:
+ *      pIsomsk    -  the pointer of port isolation port mask
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each bit of isomsk determine two port's isolation,
+ *      1 means two port could not forward packet between
+ *      each other.
+ *      bit 0  - Port0 & Port1 
+ *      bit 1  - Port0 & Port2 
+ *      bit 2  - Port0 & Port3
+ *      bit 3  - Port0 & Port4
+ *      bit 4  - Port0 & Port5
+ *      bit 5  - Port1 & Port2
+ *      bit 6  - Port1 & Port3
+ *      bit 7  - Port1 & Port4
+ *      bit 8  - Port1 & Port5
+ *      bit 9  - Port2 & Port3
+ *      bit 10 - Port2 & Port4
+ *      bit 11 - Port2 & Port5
+ *      bit 12 - Port3 & Port4
+ *      bit 13 - Port3 & Port5
+ *      bit 14 - Port4 & Port5
+ */
+
+int32 rtl8306e_port_isolation_get(uint32 *pIsomsk)
+{
+    uint32 regval;
+
+    if (NULL == pIsomsk)
+        return FAILED;
+    rtl8306e_reg_get(0, 29, 3, &regval);
+    *pIsomsk = regval & 0x7FFF;
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_tagAware_set
+ * Description:
+ *      Configure switch to be VLAN tag awared
+ * Input:
+ *      enabled  - Configure RTL8306 VLAN tag awared
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If switch is unawared VLAN tag, packet with vlan tag is treated as untagged pkt
+ *      and assigned PVID as VID.
+ */
+int32 rtl8306e_vlan_tagAware_set(uint32 enabled) 
+{
+    rtl8306e_regbit_set(0, 16, 10, 0, enabled ? 0: 1);        
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanConfig.enTagAware = (uint8) enabled;
+#endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_tagAware_set
+ * Description:
+ *      Get switch to be VLAN tag awared  or not
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled  - the pointer of RTL8306 VLAN tag awared status
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If switch is unawared VLAN tag, packet with vlan tag is treated as untagged pkt
+ *      and assigned PVID as VID.
+ */
+ 
+int32 rtl8306e_vlan_tagAware_get(uint32 * pEnabled) 
+{
+    uint32 bitValue;
+
+    if (NULL == pEnabled)
+        return FAILED;
+    
+    rtl8306e_regbit_get(0, 16, 10, 0, &bitValue);
+    *pEnabled = (bitValue ? FALSE: TRUE);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_IgrFilterEnable_set
+ * Description:
+ *      Configure VLAN ingress filter
+ * Input:
+ *      enabled  - enable or disable
+ * Output:
+ *      none 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+int32 rtl8306e_vlan_IgrFilterEnable_set(uint32 enabled) 
+{
+
+    rtl8306e_regbit_set(0, 16, 9, 0, enabled ? 0 : 1);    
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanConfig.enIngress = (uint8) enabled;
+#endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_IgrFilterEnable_get
+ * Description:
+ *      Get VLAN ingress filter enabled or disabled
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled  - enable or disable
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+int32 rtl8306e_vlan_IgrFilterEnable_get(uint32 *pEnabled) 
+{
+    uint32 bitValue;
+
+    if (NULL == pEnabled)
+        return FAILED;
+    
+    rtl8306e_regbit_get(0, 16, 9, 0, &bitValue);
+    *pEnabled = (bitValue ? 0: 1);
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_leaky_set
+ * Description:
+ *      Configure switch to forward frames to other VLANs ignoring the egress rule.
+ * Input:
+ *      type   -  vlan leaky type
+ *      enabled  - enable or disable
+ * Output:
+ *      none 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_VALN_LEAKY_UNICAST - Vlan leaky for unicast pkt
+ *          RTL8306_VALN_LEAKY_MULTICAST - Vlan leaky for multicast pkt
+ *          RTL8306_VALN_LEAKY_ARP - Vlan leaky for ARP brodcast pkt 
+ *          RTL8306_VALN_LEAKY_MIRROR - Vlan leaky for mirror function
+
+ *    1.When the Vlan leaky for unicast pkt is enabled, it enables the inter-VLANs unicast packet forwarding. 
+ *    That is, if the L2 look up MAC table search hit, then the unicast packet will be forwarded
+ *    to the egress port ignoring the egress rule.
+ *    2.When Vlan leaky for multicast pkt is enabled, multicast packet may be flood to all multicast address
+ *    group member set, ignoring the VLAN member set domain limitation.
+ *    3.When Vlan leaky for ARP pkt is enabled, the ARP broadcast packets will be forward to all the other
+ *    ports ignoring the egress rule.
+ *    4.When Vlan leaky for mirror function is enabled, it enables the inter-VLANs mirror function, 
+ *    ignoring the VLAN member set domain limitation.
+ */
+int32 rtl8306e_vlan_leaky_set(uint32 type, uint32 enabled)
+{
+    switch(type) 
+    {
+        case RTL8306_VALN_LEAKY_UNICAST:
+            rtl8306e_regbit_set(0, 18, 11, 0, enabled ? 0 : 1);
+#ifdef RTL8306_TBLBAK
+            rtl8306_TblBak.vlanConfig.enLeakVlan = (uint8) enabled;
+#endif
+            break;
+        case RTL8306_VALN_LEAKY_MULTICAST:
+            rtl8306e_regbit_set(2, 23, 7, 3, enabled ? 0 : 1);
+#ifdef RTL8306_TBLBAK
+            rtl8306_TblBak.vlanConfig.enIPMleaky = (uint8) enabled;
+#endif
+            break;
+        case RTL8306_VALN_LEAKY_ARP:
+            rtl8306e_regbit_set(0, 18, 10, 0, enabled ? 0 : 1);
+#ifdef RTL8306_TBLBAK
+            rtl8306_TblBak.vlanConfig.enArpVlan = (uint8) enabled;
+#endif
+            break;
+        case RTL8306_VALN_LEAKY_MIRROR:
+            rtl8306e_regbit_set(2, 23, 6, 3, enabled ? 0 : 1);
+#ifdef RTL8306_TBLBAK
+            rtl8306_TblBak.vlanConfig.enMirLeaky = (uint8) enabled;
+#endif
+            break;
+        default:
+            return FAILED;
+    }    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_leaky_get
+ * Description:
+ *      Get switch whether forwards unicast frames to other VLANs
+ * Input:
+ *      type   -  vlan leaky type
+ * Output:
+ *      pEnabled  - the pointer of Vlan Leaky status(Dsiabled or Enabled) 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *   type coulde be:
+ *          RTL8306_VALN_LEAKY_UNICAST - Vlan leaky for unicast pkt
+ *          RTL8306_VALN_LEAKY_MULTICAST - Vlan leaky for multicast pkt
+ *          RTL8306_VALN_LEAKY_ARP - Vlan leaky for ARP brodcast pkt 
+ *    1.When the Vlan leaky for unicast pkt is enabled, it enables the inter-VLANs unicast packet forwarding. 
+ *    That is, if the L2 look up MAC table search hit, then the unicast packet will be forwarded
+ *    to the egress port ignoring the egress rule.
+ *    2.When Vlan leaky for multicast pkt is enabled, multicast packet may be flood to all multicast address
+ *    group member set, ignoring the VLAN member set domain limitation.
+ *    3.When Vlan leaky for ARP pkt is enabled, the ARP broadcast packets will be forward to all the other
+ *    ports ignoring the egress rule.
+ *    4.When Vlan leaky for mirror function is enabled, it enables the inter-VLANs mirror function, 
+ *    ignoring the VLAN member set domain limitation.
+ */
+
+int32 rtl8306e_vlan_leaky_get(uint32 type, uint32 *pEnabled)
+{
+    uint32 bitValue;
+
+    if(NULL == pEnabled)
+        return FAILED;
+
+    switch(type) 
+    {
+        case RTL8306_VALN_LEAKY_UNICAST:
+            rtl8306e_regbit_get(0, 18, 11, 0, &bitValue);
+            break;
+        case RTL8306_VALN_LEAKY_MULTICAST:
+            rtl8306e_regbit_get(2, 23, 7, 3, &bitValue);
+            break;
+        case RTL8306_VALN_LEAKY_ARP:
+            rtl8306e_regbit_get(0, 18, 10, 0, &bitValue);
+            break;
+        case RTL8306_VALN_LEAKY_MIRROR:
+            rtl8306e_regbit_get(2, 23, 6, 3, &bitValue);
+            break;
+        default:
+            return FAILED;
+    }
+    *pEnabled = (bitValue ?  FALSE : TRUE);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_nullVidReplace_set
+ * Description:
+ *      Configure switch to replace Null VID tagged frame by PVID if it is tag aware
+ * Input:
+ *      port   -  port number
+ *      enabled  - enable or disable
+ * Output:
+ *      none 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.When Null VID replacement is enabled, 8306E only captures tagged packet with VID=0,
+ *      then replace VID with input port's PVID. If switch received a packet that is not tagged, 
+ *      it will not insert a tag with PVID to this packet.
+ *      2. When Null VID replacement is disabled, switch will drop or deal the null VID tagged 
+ *      frame depends on the configuration.
+ */
+int32 rtl8306e_vlan_nullVidReplace_set(uint32 port, uint32 enabled)
+{
+    uint32 speed, duplex, nway;
+
+    if (port > RTL8306_PORT5)
+        return FAILED;
+    
+    speed = 0; 
+    duplex = 0;
+    nway = 0;
+    
+    /*save mac 4 or port status when operate reg.22*/    
+    if (4 == port) 
+    {
+        rtl8306e_regbit_get(5, 0, 13, 0, &speed);
+        rtl8306e_regbit_get(5, 0, 12, 0, &nway);
+        rtl8306e_regbit_get(5, 0, 8, 0, &duplex);            
+    } 
+    else if (5 == port) 
+    {
+        rtl8306e_regbit_get(6, 0, 13, 0, &speed);
+        rtl8306e_regbit_get(6, 0, 12, 0, &nway);
+        rtl8306e_regbit_get(6, 0, 8, 0, &duplex);            
+    }
+
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ; 
+    
+    rtl8306e_regbit_set(port, 22, 12, 0, enabled ? 1 : 0);
+    
+    /*restore mac 4 or port status when operate reg.22*/    
+    if (4 == port) 
+    {
+        rtl8306e_regbit_set(5, 0, 13, 0, speed);
+        rtl8306e_regbit_set(5, 0, 12, 0, nway);
+        rtl8306e_regbit_set(5, 0, 8, 0, duplex);            
+    }
+    else if (6 == port) 
+    { 
+        /*for port++ when port 5*/
+        rtl8306e_regbit_set(6, 0, 13, 0, speed);
+        rtl8306e_regbit_set(6, 0, 12, 0, nway);
+        rtl8306e_regbit_set(6, 0, 8, 0, duplex);
+    }           
+    
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanConfig_perport[port].enNulPvidRep = (uint8) enabled;
+#endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_nullVidReplace_get
+ * Description:
+ *      Configure switch to forward frames to other VLANs ignoring the egress rule.
+ * Input:
+ *      port   -  port number
+ * Output:
+ *      pEnabled  - the pointer of Null VID replacement ability(Dsiabled or Enabled) 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.When Null VID replacement is enabled, 8306E only captures tagged packet with VID=0,
+ *      then replace VID with input port's PVID. If switch received a packet that is not tagged, 
+ *      it will not insert a tag with PVID to this packet.
+ *      2. When Null VID replacement is disabled, switch will drop or deal the null VID tagged 
+ *      frame depends on the configuration.
+ */
+int32 rtl8306e_vlan_nullVidReplace_get(uint32 port, uint32 *pEnabled)
+{
+    uint32 bitValue;
+    
+    if ( (port > RTL8306_PORT5) || (NULL == pEnabled ))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/    
+    if (RTL8306_PORT5 == port)  
+        port ++ ; 
+    
+    rtl8306e_regbit_get(port, 22, 12, 0, &bitValue);
+    *pEnabled = (bitValue ? TRUE : FALSE);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_portPvidIndex_set
+ * Description:
+ *      Configure switch port PVID index 
+ * Input:
+ *      port           -   Specify the port(port 0 ~ port 5) to configure VLAN index
+ *      vlanIndex    -   Specify the VLAN index
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 16 vlan entry, VID of vlan entry pointed by PVID index  is the PVID 
+ */
+int32 rtl8306e_vlan_portPvidIndex_set(uint32 port, uint32 vlanIndex)
+{
+    uint32 regValue;
+
+    if(port > RTL8306_PORT5 || vlanIndex > (RTL8306_VLAN_ENTRYS -1))
+        return FAILED;
+    
+    if (port < RTL8306_PORT5) 
+    {
+        rtl8306e_reg_get(port, 24, 0, &regValue);
+        regValue = (regValue & 0xFFF) | (vlanIndex << 12);
+        rtl8306e_reg_set(port, 24, 0, regValue);
+    } else 
+    {
+        rtl8306e_reg_get(0, 26, 1, &regValue);
+        regValue = (regValue & 0xFFF) | (vlanIndex << 12);
+        rtl8306e_reg_set(0, 26, 1, regValue);
+    }
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanPvidIdx[port]= (uint8) vlanIndex;
+#endif
+       
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_portPvidIndex_get
+ * Description:
+ *      Get switch port PVID index 
+ * Input:
+ *      port            -   Specify the port(port 0 ~ port 5) to configure VLAN index
+ * Output:
+ *      pVlanIndex   -   pointer of VLAN index number
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 16 vlan entry, VID of vlan entry pointed by PVID index  is the PVID 
+ */
+ 
+int32 rtl8306e_vlan_portPvidIndex_get(uint32 port, uint32 *pVlanIndex) 
+{
+    if((port > RTL8306_PORT5) || pVlanIndex == NULL)
+        return FAILED;
+    
+    if (port < RTL8306_PORT5) 
+        rtl8306e_reg_get(port, 24, 0, pVlanIndex);
+    else 
+        rtl8306e_reg_get(0, 26, 1, pVlanIndex);
+    *pVlanIndex = (*pVlanIndex >> 12) & 0xF;
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_portAcceptFrameType_set
+ * Description:
+ *      Set VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ *      accept_frame_type             - accept frame type
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *    The API is used for checking 802.1Q tagged frames.
+ *    The accept frame type as following:
+ *    RTL8306E_ACCEPT_ALL
+ *    RTL8306E_ACCEPT_TAG_ONLY
+ *    RTL8306E_ACCEPT_UNTAG_ONLY
+ */
+int32 rtl8306e_vlan_portAcceptFrameType_set(uint32 port, rtl8306e_acceptFrameType_t accept_frame_type)
+{
+    uint32 regval;
+    
+    if(port > RTL8306_PORT5)
+        return FAILED;
+    
+    if(RTL8306_PORT0 == port)
+    {
+        rtl8306e_reg_get(0, 31, 0, &regval);
+        regval &= ~(0x3 << 7);
+        regval |= (accept_frame_type << 7);
+        rtl8306e_reg_set(0, 31, 0, regval);
+    }
+    else if (RTL8306_PORT5 == port)
+    {
+        rtl8306e_reg_get(6, 30, 1, &regval);
+        regval &= ~(0x3 << 6);
+        regval |= (accept_frame_type << 6);
+        rtl8306e_reg_set(6, 30, 1, regval);        
+    }
+    else
+    {
+        rtl8306e_reg_get(port, 21, 2, &regval);
+        regval &= ~(0x3 << 11);
+        regval |= (accept_frame_type << 11);
+        rtl8306e_reg_set(port, 21, 2, regval);        
+    }
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanConfig.enVlanTagOnly = (accept_frame_type == RTL8306E_ACCEPT_TAG_ONLY ? TRUE : FALSE);
+#endif
+    return SUCCESS;
+}
+
+
+
+/* Function Name:
+ *      rtl8306e_vlan_portAcceptFrameType_get
+ * Description:
+ *      Get VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ * Output:
+ *      pAccept_frame_type             - accept frame type pointer
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *    The API is used for checking 802.1Q tagged frames.
+ *    The accept frame type as following:
+ *    RTL8306E_ACCEPT_ALL
+ *    RTL8306E_ACCEPT_TAG_ONLY
+ *    RTL8306E_ACCEPT_UNTAG_ONLY
+ */
+int32 rtl8306e_vlan_portAcceptFrameType_get(uint32 port, rtl8306e_acceptFrameType_t *pAccept_frame_type)
+{
+    uint32 regval;
+    
+    if((port > RTL8306_PORT5) || (pAccept_frame_type == NULL))
+        return FAILED;
+
+    if(RTL8306_PORT0 == port)
+    {
+        rtl8306e_reg_get(0, 31, 0, &regval);
+        regval &= (0x3 << 7);
+        *pAccept_frame_type = (rtl8306e_acceptFrameType_t)(regval >> 7);
+    }
+    else if (RTL8306_PORT5 == port)
+    {
+        rtl8306e_reg_get(6, 30, 1, &regval);
+        regval &= (0x3 << 6);
+        *pAccept_frame_type = (rtl8306e_acceptFrameType_t)(regval >> 6);
+    }
+    else
+    {
+        rtl8306e_reg_get(port, 21, 2, &regval);
+        regval &= (0x3 << 11);
+        *pAccept_frame_type = (rtl8306e_acceptFrameType_t)(regval >> 11);        
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsert_set
+ * Description:
+ *      Insert VLAN tag by ingress port
+ * Input:
+ *      egPort               - egress port number 0~5
+ *      igPortMsk           - ingress port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      egPort is packet egress port, if the packet is untagged and its igress port
+ *      is in the igPortMsk, it will be inserted with an VLAN tag.
+ */
+int32 rtl8306e_vlan_tagInsert_set(uint32 egPort, uint32 igPortMsk)
+{
+    uint32 regval;
+    
+    if((egPort > RTL8306_PORT5) || (igPortMsk > 0x3F))
+        return FAILED;
+    
+    /*enable EN_INSERT_TAG*/
+    rtl8306e_regbit_set(0, 28, 0, 3, 1);
+
+    if(RTL8306_PORT0 == egPort)
+    {
+        rtl8306e_reg_get(0, 28, 3, &regval);
+        regval &= ~(0x3F << 1);
+        regval |= (igPortMsk << 1);
+        rtl8306e_reg_set(0, 28, 3, regval);        
+    }
+    else if(RTL8306_PORT5 == egPort)
+    {
+        rtl8306e_reg_get(6, 30, 1, &regval);
+        regval &= ~0x3F;
+        regval |= igPortMsk;
+        rtl8306e_reg_set(6, 30, 1, regval);
+    }
+    else
+    {
+        rtl8306e_reg_get(egPort, 30, 1, &regval);
+        regval &= ~(0x3F << 9);
+        regval |= (igPortMsk << 9);
+        rtl8306e_reg_set(egPort, 30, 1, regval);
+    }
+                
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsert_get
+ * Description:
+ *      get  ingress port mask of VLAN tag insertion for untagged packet
+ * Input:
+ *      egPort               - egress port number 0~5
+ *      igPortMsk           - ingress port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      egPort is packet egress port, if the packet is untagged and its igress port
+ *      is in the igPortMsk, it will be inserted with an VLAN tag.
+ */
+int32 rtl8306e_vlan_tagInsert_get(uint32 egPort, uint32 * pIgPortMsk)
+{
+    uint32 regval ;
+    
+    if ((egPort > RTL8306_PORT5) || (NULL == pIgPortMsk))
+        return FAILED;
+
+    /*EN_INSERT_TAG = 0, insert tag operation is disable*/
+    rtl8306e_regbit_get(0, 28, 0, 3, &regval);
+    if(!regval)
+        *pIgPortMsk = 0;
+    
+    if(RTL8306_PORT0 == egPort)
+    {
+        rtl8306e_reg_get(0, 28, 3, &regval);
+        regval &= (0x3F << 1);
+        *pIgPortMsk = regval >> 1;
+    }
+    else if(RTL8306_PORT5 == egPort)
+    {
+        rtl8306e_reg_get(6, 30, 1, &regval);
+        regval &= 0x3F;
+        *pIgPortMsk = regval;
+    }
+    else 
+    {
+        rtl8306e_reg_get(egPort, 30, 1, &regval);
+        regval &= (0x3F << 9);
+        *pIgPortMsk = regval >> 9;
+    }
+    
+    return SUCCESS;
+}
+
+/*added by Fan Kaixi, 2012-01-18*/
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsertRemove_set
+ * Description:
+ *      set per port vlan tag action
+ * Input:
+ *      Port               - egress port number 0~5
+ *      option              - action options, insert/remove/replace/untouch
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      port is egress port number from 0 to 5. option is the action the egress
+ *      port will take on packets tx from itself.
+ *      option have values as follows:
+ *          RTL8306_VLAN_IRTAG = 0  ---  insert tag for untagged packets, remove tag from tagged packets and add new tag to it
+ *          RTL8306_VLAN_RTAG,      ---  remove tag from tagged packets, don't touch untagged packets                 
+ *          RTL8306_VLAN_ITAG,      ---  insert tag for untagged packets, don't touch tagged packets       
+ *          RTL8306_VLAN_UNDOTAG    ---  don't touch tag for packets 
+ *      when egress port decide to insert tag for untagged packets, the tag vid is derived from packets'
+ *      ingress port pvid.
+*/
+int32 rtl8306e_vlan_tagInsertRemove_set(uint32 port, uint32 option)
+{
+	uint32 regValue;
+	 uint32 speed, duplex, nway;
+     
+	if ( (port > RTL8306_PORT5) || (option > 0x3) ) 
+		return FAILED;
+
+       /*save mac 4 or port status when operate reg.22*/
+       if (port == 4) {
+            rtl8306e_regbit_get(5, 0, 13, 0, &speed);
+            rtl8306e_regbit_get(5, 0, 12, 0, &nway);
+            rtl8306e_regbit_get(5, 0, 8, 0, &duplex);            
+       } else if (port == 5) {
+            rtl8306e_regbit_get(6, 0, 13, 0, &speed);
+            rtl8306e_regbit_get(6, 0, 12, 0, &nway);
+            rtl8306e_regbit_get(6, 0, 8, 0, &duplex);            
+       }
+    
+	/*Port 5 corresponding PHY6*/	
+	if (port == RTL8306_PORT5 )  
+		port ++ ;  
+    rtl8306e_reg_get(port, 22, 0, &regValue);
+    regValue &= ~0x3;
+    regValue |= option;
+    rtl8306e_reg_set(port, 22, 0, regValue);
+
+       /*restore mac 4 or port status when operate reg.22*/
+      if (port == 4) {
+            rtl8306e_regbit_set(5, 0, 13, 0, speed);
+            rtl8306e_regbit_set(5, 0, 12, 0, nway);
+            rtl8306e_regbit_set(5, 0, 8, 0, duplex);        
+      } else if (port == 6)  {  /*for port++ when port 5*/
+           rtl8306e_regbit_set(6, 0, 13, 0, speed);
+           rtl8306e_regbit_set(6, 0, 12, 0, nway);
+           rtl8306e_regbit_set(6, 0, 8, 0, duplex);
+      }      
+
+	return SUCCESS;    
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsertRemove_get
+ * Description:
+ *      get per port vlan tag action
+ * Input:
+ *      Port               - egress port number 0~5
+ * Output:
+ *      pOption              - action options, insert/remove/replace/untouch
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      port is egress port number from 0 to 5. option is the action the egress
+ *      port will take on packets tx from itself.
+ *      option have values as follows:
+ *          RTL8306_VLAN_IRTAG = 0  ---  insert tag for untagged packets, remove tag from tagged packets and add new tag to it
+ *          RTL8306_VLAN_RTAG,      ---  remove tag from tagged packets, don't touch untagged packets                 
+ *          RTL8306_VLAN_ITAG,      ---  insert tag for untagged packets, don't touch tagged packets       
+ *          RTL8306_VLAN_UNDOTAG    ---  don't touch tag for packets 
+ *      when egress port decide to insert tag for untagged packets, the tag vid is derived from packets'
+ *      ingress port pvid.
+*/
+int32 rtl8306e_vlan_tagInsertRemove_get(uint32 port, uint32 *pOption)
+{
+ 	uint32 regValue;
+	
+	if (port > RTL8306_PORT5 || (pOption == NULL))
+		return FAILED;
+	/*Port 5 corresponding PHY6*/	
+	if (port == RTL8306_PORT5 )  
+		port ++ ;  
+	rtl8306e_reg_get(port, 22, 0, &regValue);	
+	*pOption = regValue & 0x3;
+
+	return SUCCESS;   
+}
+
+/* Function Name:
+ *      rtk_vlan_set
+ * Description:
+ *      Set a VLAN entry
+ * Input:
+ *      vlanIndex  - VLAN entry index
+ *      vid           - VLAN ID to configure
+ *      mbrmsk     - VLAN member set portmask
+ *      untagmsk  - VLAN untag set portmask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ */
+int32 rtl8306e_vlan_entry_set(uint32 vlanIndex, uint32 vid, uint32 mbrmsk, uint32 untagmsk )
+{
+    uint32 regValue;
+
+    if ((vid > RTL8306_VIDMAX) || (mbrmsk > 0x3F) || (untagmsk > 0x3F))
+        return FAILED;
+    
+    /*enable EN_UNTAG_SET*/
+    rtl8306e_regbit_set(0, 29, 12, 0, 1);
+    
+    /*set vlan entry*/
+    switch(vlanIndex) 
+    {
+        case 0: /* VLAN[A] */
+            rtl8306e_reg_get(0, 25, 0, &regValue);
+            regValue = (regValue & 0xF000) | vid ;
+            rtl8306e_reg_set(0, 25, 0, regValue);
+            rtl8306e_reg_get(0, 24, 0, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(0, 24, 0, regValue);
+            rtl8306e_reg_get(0, 29, 0, &regValue);
+            regValue &= ~0x3F;
+            regValue |= untagmsk;
+            rtl8306e_reg_set(0, 29, 0, regValue);            
+            break;
+
+        case 1: /* VLAN[B] */
+            rtl8306e_reg_get(1, 25, 0, &regValue);
+            regValue = (regValue & 0xF000) | vid ;
+            rtl8306e_reg_set(1, 25, 0, regValue);
+            rtl8306e_reg_get(1, 24, 0, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(1, 24, 0, regValue);
+            rtl8306e_reg_get(1, 30, 1, &regValue);
+            regValue &= ~0x3F;
+            regValue |= untagmsk;
+            rtl8306e_reg_set(1, 30, 1, regValue);            
+            break;
+
+        case 2: /* VLAN[C] */
+            rtl8306e_reg_get(2, 25, 0, &regValue);
+            regValue = (regValue & 0xF000) | vid ;
+            rtl8306e_reg_set(2, 25, 0, regValue);
+            rtl8306e_reg_get(2, 24, 0, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(2, 24, 0, regValue);
+            rtl8306e_reg_get(2, 30, 1, &regValue);
+            regValue &= ~0x3F;
+            regValue |= untagmsk;
+            rtl8306e_reg_set(2, 30, 1, regValue);                
+            break;
+
+        case 3: /* VLAN[D] */
+            rtl8306e_reg_get(3, 25, 0, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(3, 25, 0, regValue);
+            rtl8306e_reg_get(3, 24, 0, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(3, 24, 0, regValue);
+            rtl8306e_reg_get(3, 30, 1, &regValue);
+            regValue &= ~0x3F;
+            regValue |= untagmsk;
+            rtl8306e_reg_set(3, 30, 1, regValue);                
+            break;
+
+        case 4: /* VLAN[E] */
+            rtl8306e_reg_get(4, 25, 0, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(4, 25, 0, regValue);
+            rtl8306e_reg_get(4, 24, 0, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(4, 24, 0, regValue);
+            rtl8306e_reg_get(4, 30, 1, &regValue);
+            regValue &= ~0x3F;
+            regValue |= untagmsk;
+            rtl8306e_reg_set(4, 30, 1, regValue);                            
+            break;
+
+        case 5: /* VLAN[F] */
+            rtl8306e_reg_get(0, 27, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(0, 27, 1, regValue);
+            rtl8306e_reg_get(0, 26, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(0, 26, 1, regValue);
+            rtl8306e_reg_get(0, 26, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(0, 26, 1, regValue);            
+            break;
+        
+        case 6: /* VLAN[G] */
+            rtl8306e_reg_get(1, 27, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(1, 27, 1, regValue);
+            rtl8306e_reg_get(1, 26, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(1, 26, 1, regValue);
+            rtl8306e_reg_get(1, 26, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(1, 26, 1, regValue);                        
+            break;
+
+        case 7: /* VLAN[H] */
+            rtl8306e_reg_get(2, 27, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(2, 27, 1, regValue);
+            rtl8306e_reg_get(2, 26, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(2, 26, 1, regValue);
+            rtl8306e_reg_get(2, 26, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(2, 26, 1, regValue);                                    
+            break;
+
+        case 8: /* VLAN[I] */
+            rtl8306e_reg_get(3, 27, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(3, 27, 1, regValue);
+            rtl8306e_reg_get(3, 26, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(3, 26, 1, regValue);
+            rtl8306e_reg_get(3, 26, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(3, 26, 1, regValue);                        
+            
+            break;
+
+        case 9: /* VLAN[J] */
+            rtl8306e_reg_get(4, 27, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(4, 27, 1, regValue);
+            rtl8306e_reg_get(4, 26, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(4, 26, 1, regValue);
+            rtl8306e_reg_get(4, 26, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(4, 26, 1, regValue);                                    
+            break;
+
+        case 10: /* VLAN[K] */
+            rtl8306e_reg_get(0, 29, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(0, 29, 1, regValue);
+            rtl8306e_reg_get(0, 28, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(0, 28, 1, regValue);
+            rtl8306e_reg_get(0, 28, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(0, 28, 1, regValue);                                    
+            break;
+
+        case 11: /* VLAN[L] */
+            rtl8306e_reg_get(1, 29, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(1, 29, 1, regValue);
+            rtl8306e_reg_get(1, 28, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(1, 28, 1, regValue);
+            rtl8306e_reg_get(1, 28, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(1, 28, 1, regValue);                                                
+            break;
+
+        case 12: /* VLAN[M] */
+            rtl8306e_reg_get(2, 29, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(2, 29, 1, regValue);
+            rtl8306e_reg_get(2, 28, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(2, 28, 1, regValue);
+            rtl8306e_reg_get(2, 28, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(2, 28, 1, regValue);                                                
+            break;
+
+        case 13: /* VLAN[N] */
+            rtl8306e_reg_get(3, 29, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(3, 29, 1, regValue);
+            rtl8306e_reg_get(3, 28, 1, &regValue);
+            regValue = (regValue & 0xFFC0) |mbrmsk;
+            rtl8306e_reg_set(3, 28, 1, regValue);
+            rtl8306e_reg_get(3, 28, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(3, 28, 1, regValue);                                                
+            break;
+
+        case 14: /* VLAN[O] */
+            rtl8306e_reg_get(4, 29, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(4, 29, 1, regValue);
+            rtl8306e_reg_get(4, 28, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(4, 28, 1, regValue);
+            rtl8306e_reg_get(4, 28, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(4, 28, 1, regValue);                                                
+            break;
+
+        case 15: /* VLAN[P] */
+            rtl8306e_reg_get(0, 31, 1, &regValue);
+            regValue = (regValue & 0xF000) | vid;
+            rtl8306e_reg_set(0, 31, 1, regValue);
+            rtl8306e_reg_get(0, 30, 1, &regValue);
+            regValue = (regValue & 0xFFC0) | mbrmsk;
+            rtl8306e_reg_set(0, 30, 1, regValue);
+            rtl8306e_reg_get(0, 30, 1, &regValue);
+            regValue &= ~(0x3F << 6);
+            regValue |= (untagmsk << 6);
+            rtl8306e_reg_set(0, 30, 1, regValue);                                                
+            break;
+        default:
+            return FAILED;
+
+    }    
+
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanTable[vlanIndex].vid = (uint16)vid;
+    rtl8306_TblBak.vlanTable[vlanIndex].memberPortMask = (uint8)mbrmsk;
+#endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_entry_get
+ * Description:
+ *      Get a VLAN entry
+ * Input:
+ *      vlanIndex  - VLAN entry index
+ * Output:
+ *      pVid           -  the pointer of VLAN ID 
+ *      pMbrmsk     -  the pointer of VLAN member set portmask
+ *      pUntagmsk  -  the pointer of VLAN untag set portmask
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ */
+int32 rtl8306e_vlan_entry_get(uint32 vlanIndex, uint32 *pVid, uint32 *pMbrmsk, uint32 *pUntagmsk)
+{
+
+    if(  (NULL == pVid) ||  (NULL == pMbrmsk))
+        return FAILED;
+    
+    switch(vlanIndex)
+    {
+        case 0: /*VLAN[A]*/
+            rtl8306e_reg_get(0, 25, 0, pVid);
+            rtl8306e_reg_get(0, 24, 0, pMbrmsk);
+            rtl8306e_reg_get(0, 29, 0, pUntagmsk);            
+            break;        
+            
+        case 1: /*VLAN[B]*/
+            rtl8306e_reg_get(1, 25, 0, pVid);
+            rtl8306e_reg_get(1, 24, 0, pMbrmsk);
+            rtl8306e_reg_get(1, 30, 1, pUntagmsk);                        
+            break;
+            
+        case 2: /*VLAN[C]*/
+            rtl8306e_reg_get(2, 25, 0, pVid);
+            rtl8306e_reg_get(2, 24, 0, pMbrmsk);
+            rtl8306e_reg_get(2, 30, 1, pUntagmsk);                                    
+            break;
+            
+        case 3: /*VLAN[D]*/
+            rtl8306e_reg_get(3, 25, 0, pVid);
+            rtl8306e_reg_get(3, 24, 0, pMbrmsk);
+            rtl8306e_reg_get(3, 30, 1, pUntagmsk);                                    
+            break;
+            
+        case 4: /*VLAN[E]*/
+            rtl8306e_reg_get(4, 25, 0, pVid);
+            rtl8306e_reg_get(4, 24, 0, pMbrmsk);
+            rtl8306e_reg_get(4, 30, 1, pUntagmsk);                                    
+            break;
+            
+        case 5: /*VLAN[F]*/
+            rtl8306e_reg_get(0, 27, 1, pVid);
+            rtl8306e_reg_get(0, 26, 1, pMbrmsk);
+            rtl8306e_reg_get(0, 26, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 6: /*VLAN[G]*/
+            rtl8306e_reg_get(1, 27, 1, pVid);
+            rtl8306e_reg_get(1, 26, 1, pMbrmsk);
+            rtl8306e_reg_get(1, 26, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 7: /*VLAN[H]*/
+            rtl8306e_reg_get(2, 27, 1, pVid);
+            rtl8306e_reg_get(2, 26, 1, pMbrmsk);
+            rtl8306e_reg_get(2, 26, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 8: /*VLAN[I]*/        
+            rtl8306e_reg_get(3, 27, 1, pVid);
+            rtl8306e_reg_get(3, 26, 1, pMbrmsk);
+            rtl8306e_reg_get(3, 26, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 9: /*VLAN[J]*/
+            rtl8306e_reg_get(4, 27, 1, pVid);
+            rtl8306e_reg_get(4, 26, 1, pMbrmsk);
+            rtl8306e_reg_get(4, 26, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 10: /*VLAN[K]*/
+            rtl8306e_reg_get(0, 29, 1, pVid);
+            rtl8306e_reg_get(0, 28, 1, pMbrmsk);
+            rtl8306e_reg_get(0, 28, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 11: /*VLAN[L]*/
+            rtl8306e_reg_get(1, 29, 1, pVid);
+            rtl8306e_reg_get(1, 28, 1, pMbrmsk);
+            rtl8306e_reg_get(1, 28, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 12: /*VLAN[M]*/
+            rtl8306e_reg_get(2, 29, 1, pVid);
+            rtl8306e_reg_get(2, 28, 1, pMbrmsk);
+            rtl8306e_reg_get(2, 28, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 13: /*VLAN[N]*/
+            rtl8306e_reg_get(3, 29, 1, pVid);
+            rtl8306e_reg_get(3, 28, 1, pMbrmsk);
+            rtl8306e_reg_get(3, 28, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 14: /*VLAN[O]*/
+            rtl8306e_reg_get(4, 29, 1, pVid);
+            rtl8306e_reg_get(4, 28, 1, pMbrmsk);
+            rtl8306e_reg_get(4, 28, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        case 15: /*VLAN[P]*/
+            rtl8306e_reg_get(0, 31, 1, pVid);
+            rtl8306e_reg_get(0, 30, 1, pMbrmsk);
+            rtl8306e_reg_get(0, 30, 1, pUntagmsk);   
+            *pUntagmsk >>= 6;
+            break;
+            
+        default:
+            return  FAILED;
+    }
+    
+    *pVid  &= 0xFFF;
+    *pMbrmsk  &= 0x3F;
+    *pUntagmsk &= 0x3F;
+    
+    return  SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_vlanBasedPriority_set
+ * Description:
+ *       Set VID based priority
+ * Input:
+ *      vlanIndex   -   Specify VLAN entry index
+ *      pri            -   the specified VLAN priority  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each VLAN could be assigned an priority. if vlanIndex > 15, it means the VID
+ *      is not in VLAN entries, unmatched VID could also be assigned an priority.
+ *       
+ */
+int32 rtl8306e_vlan_vlanBasedPriority_set(uint32 vlanIndex, uint32 pri)
+{
+    uint32 regval;
+    
+    if (pri > 3)
+        return FAILED;
+
+    switch(vlanIndex)
+    {
+        case 0: /*VLAN[A]*/
+            rtl8306e_regbit_set(0, 29, 8, 0, 1);
+            rtl8306e_reg_get(0, 29, 0, &regval);
+            regval &= ~(0x3 << 6);
+            regval |= (pri << 6);
+            rtl8306e_reg_set(0, 29, 0, regval);            
+            break;        
+            
+        case 1: /*VLAN[B]*/
+            rtl8306e_regbit_set(1, 30, 8, 1, 1);
+            rtl8306e_reg_get(1, 30, 1, &regval);
+            regval &= ~(0x3 << 6);
+            regval |= (pri << 6);
+            rtl8306e_reg_set(1, 30, 1, regval);                                   
+            break;
+            
+        case 2: /*VLAN[C]*/
+            rtl8306e_regbit_set(2, 30, 8, 1, 1);
+            rtl8306e_reg_get(2, 30, 1, &regval);
+            regval &= ~(0x3 << 6);
+            regval |= (pri << 6);
+            rtl8306e_reg_set(2, 30, 1, regval);                                   
+            break;
+            
+        case 3: /*VLAN[D]*/
+            rtl8306e_regbit_set(3, 30, 8, 1, 1);
+            rtl8306e_reg_get(3, 30, 1, &regval);
+            regval &= ~(0x3 << 6);
+            regval |= (pri << 6);
+            rtl8306e_reg_set(3, 30, 1, regval);                                               
+            break;
+            
+        case 4: /*VLAN[E]*/
+            rtl8306e_regbit_set(4, 30, 8, 1, 1);
+            rtl8306e_reg_get(4, 30, 1, &regval);
+            regval &= ~(0x3 << 6);
+            regval |= (pri << 6);
+            rtl8306e_reg_set(4, 30, 1, regval);                                               
+            break;
+            
+        case 5: /*VLAN[F]*/
+            rtl8306e_regbit_set(0, 27, 14, 1, 0);
+            rtl8306e_reg_get(0, 27, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(0, 27, 1, regval);                                               
+            break;
+            
+        case 6: /*VLAN[G]*/
+            rtl8306e_regbit_set(1, 26, 14, 1, 0);
+            rtl8306e_reg_get(1, 26, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(1, 26, 1, regval);                                                           
+            break;
+            
+        case 7: /*VLAN[H]*/
+            rtl8306e_regbit_set(2, 26, 14, 1, 0);
+            rtl8306e_reg_get(2, 26, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(2, 26, 1, regval);                                                                       
+            break;
+            
+        case 8: /*VLAN[I]*/        
+            rtl8306e_regbit_set(3, 26, 14, 1, 1);
+            rtl8306e_reg_get(3, 26, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(3, 26, 1, regval);                                                                                   
+            break;
+            
+        case 9: /*VLAN[J]*/
+            rtl8306e_regbit_set(4, 26, 14, 1, 1);
+            rtl8306e_reg_get(4, 26, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(4, 26, 1, regval);                                                                                               
+            break;
+            
+        case 10: /*VLAN[K]*/
+            rtl8306e_regbit_set(0, 28, 14, 1, 1);
+            rtl8306e_reg_get(0, 28, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(0, 28, 1, regval);                                                                                                           
+            break;
+            
+        case 11: /*VLAN[L]*/
+            rtl8306e_regbit_set(1, 28, 14, 1, 1);
+            rtl8306e_reg_get(1, 28, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(1, 28, 1, regval);                                                                                                                       
+            break;
+            
+        case 12: /*VLAN[M]*/
+            rtl8306e_regbit_set(2, 28, 14, 1, 0);
+            rtl8306e_reg_get(2, 28, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(2, 28, 1, regval);                                                                                                                                   
+            break;
+            
+        case 13: /*VLAN[N]*/
+            rtl8306e_regbit_set(3, 28, 14, 1, 0);
+            rtl8306e_reg_get(3, 28, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(3, 28, 1, regval);                                                                                                                                               
+            break;
+            
+        case 14: /*VLAN[O]*/
+            rtl8306e_regbit_set(4, 28, 14, 1, 0);
+            rtl8306e_reg_get(4, 28, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(4, 28, 1, regval);                                                                                                                                                           
+            break;
+            
+        case 15: /*VLAN[P]*/
+            rtl8306e_regbit_set(0, 30, 14, 1, 0);
+            rtl8306e_reg_get(0, 30, 1, &regval);
+            regval &= ~(0x3 << 12);
+            regval |= (pri << 12);
+            rtl8306e_reg_set(0, 30, 1, regval);                                                                                                                                                                       
+            break;
+            
+        default: /*unmatched vlan entry*/
+            rtl8306e_regbit_set(0, 29, 11, 0, 1);
+            rtl8306e_reg_get(0, 29, 0, &regval);
+            regval &= ~(0x3 << 9);
+            regval |= (pri << 9);
+            rtl8306e_reg_set(0, 29, 0, regval);                                                                                                                                                                                                          
+            return  FAILED;
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_vlanBasedPriority_get
+ * Description:
+ *       Get VID based priority
+ * Input:
+ *      vlanIndex   -   Specify VLAN entry index
+ * Output:
+ *      pPri           -   the pointer of specified VLAN priority  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each VLAN could be assigned an priority. if vlanIndex > 15, it means the VID
+ *      is not in VLAN entries, unmatched VID could also be assigned an priority.
+ *       
+ */
+int32 rtl8306e_vlan_vlanBasedPriority_get(uint32 vlanIndex, uint32 *pPri)
+{
+    uint32 regval;
+    
+    if (NULL == pPri)
+        return FAILED;
+
+    switch(vlanIndex)
+    {
+        case 0: /*VLAN[A]*/
+            rtl8306e_reg_get(0, 29, 0, &regval);
+            regval &= (0x3 << 6);
+            *pPri = regval >> 6;
+            break;        
+            
+        case 1: /*VLAN[B]*/
+            rtl8306e_reg_get(1, 30, 1, &regval);
+            regval &= (0x3 << 6);
+            *pPri = regval >> 6;
+            break;
+            
+        case 2: /*VLAN[C]*/
+            rtl8306e_reg_get(2, 30, 1, &regval);
+            regval &= (0x3 << 6);
+            *pPri = regval >> 6;
+            break;
+            
+        case 3: /*VLAN[D]*/
+            rtl8306e_reg_get(3, 30, 1, &regval);
+            regval &= (0x3 << 6);
+            *pPri = regval >> 6;
+            break;
+            
+        case 4: /*VLAN[E]*/
+            rtl8306e_reg_get(4, 30, 1, &regval);
+            regval &= (0x3 << 6);
+            *pPri = regval >> 6;
+            break;
+            
+        case 5: /*VLAN[F]*/
+            rtl8306e_reg_get(0, 27, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 6: /*VLAN[G]*/
+            rtl8306e_reg_get(1, 26, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 7: /*VLAN[H]*/
+            rtl8306e_reg_get(2, 26, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 8: /*VLAN[I]*/        
+            rtl8306e_reg_get(3, 26, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 9: /*VLAN[J]*/
+            rtl8306e_reg_get(4, 26, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 10: /*VLAN[K]*/
+            rtl8306e_reg_get(0, 28, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 11: /*VLAN[L]*/
+            rtl8306e_reg_get(1, 28, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 12: /*VLAN[M]*/
+            rtl8306e_reg_get(2, 28, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 13: /*VLAN[N]*/
+            rtl8306e_reg_get(3, 28, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 14: /*VLAN[O]*/
+            rtl8306e_reg_get(4, 28, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        case 15: /*VLAN[P]*/
+            rtl8306e_reg_get(0, 30, 1, &regval);
+            regval &= (0x3 << 12);
+            *pPri = regval >> 12;
+            break;
+            
+        default: /*unmatched vlan entry*/
+            rtl8306e_reg_get(0, 29, 0, &regval);
+            regval &= (0x3 << 9);
+            *pPri = regval >> 9;
+            return  FAILED;
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_transEnable_set
+ * Description:
+ *      Enable VLAN translation 
+ * Input:
+ *      enable       -   enable or disable VLAN translation
+ *      portmask    -   NNI port is set 1 and UNI port is set 0
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Only the traffic between NNI port and UNI port will be change with VID,
+ *      the VLAN tranlation function and Q-in-Q(SVLAN) could not be enabled  
+ *      at the same time, user should choose one of them. 
+ */
+int32 rtl8306e_vlan_transEnable_set(uint32 enable, uint32 portmask)
+{
+    uint32 regval;
+
+    rtl8306e_reg_get(6, 30, 3, &regval);
+
+    if(enable)
+    {
+        regval &= ~0xff;
+        regval |= (1 << 6) | (portmask & 0x3F);
+        rtl8306e_reg_set(6, 30, 3, regval);
+    }
+    else
+    {
+        regval &= ~0xff;
+        rtl8306e_reg_set(6, 30, 3, regval);
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_vlan_transEnable_get
+ * Description:
+ *      Get VLAN translation setting
+ * Input:
+ *      none
+ * Output:
+ *      pEnable       -   the pointer of enable or disable VLAN translation
+ *      pPortMask    -   the pointer of VLAN translation port mask
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Only the traffic between NNI port and UNI port will be change with VID,
+ *      the VLAN tranlation function and Q-in-Q(SVLAN) could not be enabled  
+ *      at the same time, user should choose one of them. 
+ */
+int32 rtl8306e_vlan_transEnable_get(uint32 *pEnable, uint32 *pPortMask)
+{
+    uint32 regval;
+
+    if((NULL == pEnable) || (NULL == pPortMask))
+        return FAILED;
+    
+    rtl8306e_reg_get(6, 30, 3, &regval);
+    if((regval & (0x3 << 6)) == (0x1 << 6))
+    {
+        *pEnable = 1;
+        *pPortMask = regval & 0x3F;
+    }
+    else
+    {
+        *pEnable = 0;
+        *pPortMask = 0;
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_transparentEnable_set
+ * Description:
+ *      Enable VLAN transparent 
+ * Input:
+ *      enable       -   enable or disable VLAN transparent
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+int32 rtl8306e_vlan_transparentEnable_set(uint32 enable)
+{
+    uint32 port;
+
+    if (enable)
+    {
+        /*set vlan disabled*/
+        rtl8306e_regbit_set(0, 18, 8, 0, 1);
+        
+        /*disable tag aware*/
+        rtl8306e_vlan_tagAware_set(FALSE); 
+
+        /*disable EN_UNTAG_SET*/
+        rtl8306e_regbit_set(0, 29, 12, 0, 0);
+        
+        /*set vlan translation disabled*/
+        rtl8306e_regbit_set(6, 30, 6, 3, 0);
+        
+        /*set port0~5 untag unawre and disable Non-PVID discard*/
+        for (port = 0; port < 5; port ++)
+        {
+            rtl8306e_regbit_set(port, 22, 15, 0, 1);
+            rtl8306e_regbit_set(port, 22, 11, 0, 0);
+        } 
+        rtl8306e_regbit_set(6, 24, 1, 0, 1);
+        rtl8306e_regbit_set(6, 22, 11, 0, 0);
+         
+        /*disable EN_INSERT_TAG*/
+        rtl8306e_regbit_set(0, 28, 0, 3, 0);
+    }
+    else
+    {
+        /*set vlan enabled*/
+        rtl8306e_regbit_set(0, 18, 8, 0, 0);
+        
+        /*enable tag aware*/
+        rtl8306e_vlan_tagAware_set(TRUE); 
+    }
+
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_transVid_set
+ * Description:
+ *      Set the translated VID
+ * Input:
+ *      vlanIndex   -   the VLAN entry index
+ *      transVid     -   the new VID
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      The VID in the entry indexed by vlanIndex will be replaced with
+ *      new VID.
+ */ 
+int32 rtl8306e_vlan_transVid_set(uint32 vlanIndex, uint32 transVid)    
+{
+   uint32 regval;
+   
+   if((vlanIndex > 15) || (transVid > 0xFFF))
+        return FAILED;
+
+   if(vlanIndex < 15)     
+   {
+        rtl8306e_reg_get(6, 17 + vlanIndex, 4, &regval);
+        regval &= ~0xfff;
+        regval |= transVid;
+        rtl8306e_reg_set(6, 17 + vlanIndex, 4, regval);
+   }
+   else
+   {
+        rtl8306e_reg_get(6, 18, 1, &regval);
+        regval &= ~0xfff;
+        regval |= transVid;
+        rtl8306e_reg_set(6, 18, 1, regval);
+   }
+       
+   return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_vlan_transVid_get
+ * Description:
+ *      Get the translated VID
+ * Input:
+ *      vlanIndex   -   the VLAN entry index
+ * Output:
+ *      pTransVid   -   the pointer of the new VID
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      The VID in the entry indexed by vlanIndex will be replaced with
+ *      new VID.
+ */ 
+int32 rtl8306e_vlan_transVid_get(uint32 vlanIndex, uint32 *pTransVid)
+{
+    uint32 regval;
+
+    if((vlanIndex > 15) || (NULL == pTransVid))
+        return FAILED;
+
+    if(vlanIndex < 15)
+    {
+       rtl8306e_reg_get(6, 17 + vlanIndex, 4, &regval);
+       *pTransVid = (regval & 0xfff);
+    }
+    else
+    {
+       rtl8306e_reg_get(6, 18, 1, &regval);
+       *pTransVid = (regval & 0xfff);
+    }
+        
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_svlan_tagAdmit_set
+ * Description:
+ *      Set Q-in-Q tag admit control
+ * Input:
+ *      port          -   port id
+ *      enable       -   enable tag admit control 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       
+ */
+int32 rtl8306e_svlan_tagAdmit_set(uint32 port, uint32 enable)
+{
+    if (port > 5)
+        return FAILED;
+
+    if(5 == port)
+    {
+        rtl8306e_regbit_set(6, 23, 0, 0, enable ? 1:0);
+    }
+    else
+    {
+        rtl8306e_regbit_set(6, 17 + port, 0, 0, enable ? 1:0);
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_svlan_tagAdmit_get
+ * Description:
+ *      Get Q-in-Q tag admit control
+ * Input:
+ *      port          -   port id
+ * Output:
+ *      pEnable     -   the pointer of enable tag admit control 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       
+ */
+int32 rtl8306e_svlan_tagAdmit_get(uint32 port, uint32 *pEnable)
+{
+    uint32 regval;
+    
+    if(port > 5)
+        return FAILED;
+    
+    if(5 == port)
+    {
+        rtl8306e_reg_get(6, 23, 0, &regval);
+        *pEnable = regval ? 1:0;
+    }
+    else 
+    {
+        rtl8306e_reg_get(6, 17 + port, 0, &regval);
+        *pEnable = regval ? 1:0;        
+    }
+        
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_svlan_otagSrc_set
+ * Description:
+ *      Set how to decide outer tag vid and priority 
+ * Input:
+ *      port          -   port id
+ *      ovidSrc      -   ovid comes from
+ *      opriSrc      -    opri comes from 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       ovidSrc RTL8306E_VIDSRC_POVID : ovid is port-based ovid,    RTL8306E_VIDSRC_NVID:ovid is new vid(translated vid)
+ *       opriSrc  RTL8306E_PRISRC_PPRI   : opri is port-based priority, RTL8306E_PRISRC_1PRMK: opri is 1p remarking value
+ */
+int32 rtl8306e_svlan_otagSrc_set(uint32 port, uint32 ovidSrc, uint32 opriSrc)
+{
+    uint32 regval;
+    
+    if(port > 5)
+        return FAILED;
+
+    if(5 == port)
+    {
+        rtl8306e_reg_get(6, 23, 0, &regval);
+        regval &= ~0xC;
+        regval |= ovidSrc ? (1 << 3):0;
+        regval |= opriSrc ? (1 << 2) :0;
+        rtl8306e_reg_set(6, 23, 0, regval);
+    }
+    else
+    {
+        rtl8306e_reg_get(6, 17 + port, 0, &regval);
+        regval &= ~0xC;
+        regval |= ovidSrc ? (1 << 3):0;
+        regval |= opriSrc ? (1 << 2) :0;
+        rtl8306e_reg_set(6, 17 + port, 0, regval);        
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_svlan_otagSrc_get
+ * Description:
+ *      Get how to decide outer tag vid and priority 
+ * Input:
+ *      port            -   port id
+ * Output:
+ *      pOvidsrc      -   the pointer of ovid comes from
+ *      pOpriSrc      -   the pointer of opri comes from 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       ovidSrc RTL8306E_VIDSRC_POVID : ovid is port-based ovid,    RTL8306E_VIDSRC_NVID:ovid is new vid(translated vid)
+ *       opriSrc  RTL8306E_PRISRC_PPRI   : opri is port-based priority, RTL8306E_PRISRC_1PRMK: opri is 1p remarking value
+ */
+
+int32 rtl8306e_svlan_otagSrc_get(uint32 port, uint32 *pOvidsrc, uint32 *pOpriSrc)
+{
+    uint32 regval;
+
+    if(port > 5)
+        return FAILED;
+
+    if(5 == port)
+    {
+        rtl8306e_reg_get(6, 23, 0, &regval);
+        *pOvidsrc = (regval & (1 << 3)) ? 1:0;
+        *pOpriSrc = (regval & (1 << 2)) ? 1:0;
+    }
+    else
+    {
+        rtl8306e_reg_get(6, 17 + port, 0, &regval);
+        *pOvidsrc = (regval & (1 << 3)) ? 1:0;
+        *pOpriSrc = (regval & (1 << 2)) ? 1:0;
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_cpu_set
+ * Description:
+ *       Specify Asic CPU port 
+ * Input:
+ *      port       -   Specify the port
+ *      enTag    -    CPU tag insert or not
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If the port is specified RTL8306_NOCPUPORT, it means
+ *      that no port is assigned as cpu port
+ */
+int32 rtl8306e_cpu_set(uint32 port, uint32 enTag) 
+{
+    uint32 regValue;
+
+    if (port > RTL8306_NOCPUPORT)
+        return FAILED;
+
+    if (port < RTL8306_PORT_NUMBER) 
+    {
+        /*enable CPU port Function */
+        rtl8306e_regbit_set(2, 21, 15, 3, 0);        
+        
+        /*whether inserting CPU tag*/
+        rtl8306e_regbit_set(2, 21, 12, 3, enTag ? 1 : 0);
+        
+        /*enable the ability to check cpu tag*/
+        rtl8306e_regbit_set(4, 21, 7, 0, 1);
+        
+        /*enable removing CPU tag*/
+        rtl8306e_regbit_set(2, 21, 11, 3, 1);
+        rtl8306e_reg_get(4, 21, 0, &regValue);
+        regValue = (regValue & 0xFFF8) | port;
+        rtl8306e_reg_set(4, 21, 0, regValue);
+
+        /*enable asic recaculate crc for pkt with cpu tag*/
+        rtl8306e_regbit_set(4, 21, 3, 0, 0);
+        
+        /*disable IEEE802.1x function of CPU Port*/
+        if (port < RTL8306_PORT5) 
+        {
+            rtl8306e_regbit_set(port, 17, 9, 2, 0);
+            rtl8306e_regbit_set(port, 17, 8, 2, 0);
+        }
+        else 
+        {
+            rtl8306e_regbit_set(6, 17, 9, 2, 0);
+            rtl8306e_regbit_set(6, 17, 8, 2, 0);
+        }
+        
+        /*Port 5 should be enabled especially*/
+        if (RTL8306_PORT5 == port)
+        {
+            rtl8306e_regbit_set(6, 22, 15, 0, TRUE);
+        }
+    }   
+    else 
+    {
+        /*disable CPU port Function */
+        rtl8306e_regbit_set(2, 21, 15, 3, 1);
+        rtl8306e_regbit_set(2, 21, 12, 3, 0);        
+        rtl8306e_reg_get(4, 21, 0, &regValue);
+        regValue = (regValue & 0xFFF8) | port;
+        rtl8306e_reg_set(4, 21, 0, regValue);
+    }   
+
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_cpu_set
+ * Description:
+ *       Get Asic CPU port number
+ * Input:
+ *      none
+ * Output:
+ *      pPort     - the pointer of CPU port number
+ *      pEnTag  - the pointer of CPU tag insert or not
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If the port is specified RTL8306_NOCPUPORT, it means
+ *      that no port is assigned as cpu port
+ */
+int32 rtl8306e_cpu_get(uint32 *pPort, uint32 *pEnTag) 
+{
+    uint32 regValue;
+    uint32 bitValue, bitVal, cpufun;
+
+    if ((NULL == pPort ) || (NULL == pEnTag))
+        return FAILED;
+    
+    rtl8306e_regbit_get(2, 21, 12, 3, &bitValue);
+    rtl8306e_regbit_get(2, 21, 15, 3, &cpufun);
+    rtl8306e_regbit_get(4, 21, 7, 0, &bitVal);
+    
+    rtl8306e_reg_get(4, 21, 0, &regValue);
+    *pPort = regValue & 0x7;
+
+    if ((!cpufun) && bitValue && bitVal)
+        *pEnTag = TRUE;
+    else 
+        *pEnTag = FALSE;
+    
+    if(cpufun)
+        *pPort = RTL8306_NOCPUPORT;
+    
+    return SUCCESS;
+}
+
+/*added by Fan Kaixi*/
+
+/* Function Name:
+ *      rtl8306e_cpu_doubleTagInsert_set
+ * Description:
+ *      Enable synchronously insertting cpu tag and vlan tag ability
+ * Input:
+ *      enabled     -   enable or disable
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      This API can be called to enable synchronously insertting cpu tag and vlan tag ability.
+*/
+int32 rtl8306e_cpu_doubleTagInsert_set(uint32 enabled)
+{
+    if (enabled > 0x1)
+        return FAILED;
+    
+    rtl8306e_regbit_set(4, 21, 10, 0, enabled ?1:0);
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_cpu_doubleTagInsert_get
+ * Description:
+ *      Get Enabled status of synchronously insertting cpu tag and vlan tag ability
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled    -   enable or disable
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      This API can be called to enable synchronously insertting cpu tag and vlan tag ability.
+*/
+int32 rtl8306e_cpu_doubleTagInsert_get(uint32 *pEnabled)
+{
+    
+    if (pEnabled == NULL)
+        return FAILED;
+    
+    rtl8306e_regbit_get(4, 21, 10, 0, pEnabled);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_softReset_set
+ * Description:
+ *      Software reset the asic
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      reset packet buffer.
+ */
+ 
+int32 rtl8306e_qos_softReset_set(void) 
+{    
+    /*software reset*/
+    rtl8306e_regbit_set(0, 16, 12, 0, 1);    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_queueNum_set
+ * Description:
+ *      Set egress port queue number (1 ~4)
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Queue number is global configuration for switch.
+ */
+
+int32 rtl8306e_qos_queueNum_set(uint32 num) 
+{
+    uint32 regValue;
+    
+    if ((num == 0) ||(num > 4))
+        return FAILED;
+    
+    rtl8306e_reg_get(2, 22, 3, &regValue);
+    rtl8306e_reg_set(2, 22, 3, (regValue & 0xFFF3) | ((num-1) << 2));
+    
+    /*A soft-reset is required after configuring queue num*/
+     rtl8306e_qos_softReset_set( );
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_queueNum_set
+ * Description:
+ *      Set egress port queue number (1 ~4)
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Queue number is global configuration for switch.
+ */
+int32 rtl8306e_qos_queueNum_get(uint32 *pNum) 
+{
+    uint32 regValue;
+
+    if (NULL == pNum) 
+        return FAILED;
+    
+    rtl8306e_reg_get(2, 22, 3, &regValue);
+    *pNum =    ((regValue & 0xC) >> 2) + 1;
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_priToQueMap_set
+ * Description:
+ *     Set priority to Queue ID mapping
+ * Input:
+ *      priority   -  priority value (0 ~ 3)
+ *      qid        -  Queue id (0~3)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Packets could be classified into specified queue through their priority. 
+ *      we can use this function to set pkt priority with queue id mapping
+ */
+int32 rtl8306e_qos_priToQueMap_set(uint32 priority, uint32 qid) 
+{
+    uint32 regValue;
+
+    if ((qid > 3) || (priority > 3)) 
+        return FAILED;
+    
+    rtl8306e_reg_get(1, 22, 3, &regValue);
+    switch(priority) 
+    {
+        case 0:
+            regValue = (regValue & 0xFFFC) | qid;
+            break;
+        case 1:
+            regValue = (regValue & 0xFFF3) | (qid << 2);
+            break;
+        case 2:
+            regValue = (regValue & 0xFFCF) | (qid << 4);
+            break;
+        case 3:
+            regValue = (regValue & 0xFF3F) | (qid << 6);
+            break;
+        default:
+            return FAILED;
+    }
+    rtl8306e_reg_set(1, 22, 3, regValue);
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_priToQueMap_get
+ * Description:
+ *      Get priority to Queue ID mapping
+ * Input:
+ *      priority   -  priority value (0 ~ 3)
+ * Output:
+ *      pQid      -  pointer of Queue id (0~3)
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Packets could be classified into specified queue through their priority. 
+ *      we can use this function to set pkt priority with queue id mapping
+ */
+int32 rtl8306e_qos_priToQueMap_get(uint32 priority, uint32 *pQid) 
+{
+    uint32 regValue;
+
+    if ((priority > 3) || (NULL == pQid))
+        return FAILED;
+    
+    rtl8306e_reg_get(1, 22, 3, &regValue);
+    
+    switch(priority) 
+    {
+        case 0:
+            *pQid = regValue & 0x3;
+            break;
+        case 1:
+            *pQid = (regValue & 0xC) >> 2;
+            break;
+        case 2:
+            *pQid = (regValue & 0x30) >> 4;
+            break;
+        case 3:
+            *pQid = (regValue & 0xC0) >> 6;
+            break;
+        default:
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_portRate_set
+ * Description:
+ *      Set port bandwidth control
+ * Input:
+ *      port            -  port number (0~5)
+ *      n64Kbps       -  Port rate (0~1526), unit 64Kbps
+ *      direction      -  Ingress or Egress bandwidth control
+ *      enabled       -  enable bandwidth control
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      For each port, both input and output bandwidth could be configured, 
+ *      RTL8306_PORT_RX represents port input bandwidth control, 
+ *      RTL8306_PORT_TX represents port output bandwidth control.
+ *      port rate unit is 64Kbps. For output rate control, enable/disable 
+ *      is configured per port, but for input rate control, it is for all port.
+ */
+int32 rtl8306e_qos_portRate_set(uint32 port, uint32 n64Kbps, uint32 direction, uint32 enabled)
+{
+    uint32 regValue;
+    
+    if ((port > RTL8306_PORT5) || (n64Kbps > 0x5F6) || (direction > 1))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    
+    if (RTL8306_PORT_RX == direction) 
+    {  
+        /*configure port Rx rate*/
+        if (!enabled ) 
+        {
+            rtl8306e_regbit_set(0, 21, 15, 3, 1);
+        } 
+        else 
+        {
+            rtl8306e_regbit_set(0, 21, 15, 3, 0);
+            rtl8306e_reg_get(port, 21, 2, &regValue);
+            regValue = (regValue & 0xF800) | (n64Kbps & 0x7FF);
+            rtl8306e_reg_set(port, 21, 2, regValue);
+        }
+    } 
+    else 
+    {  
+        /*configure port Tx rate*/
+        if (!enabled) 
+        {
+            rtl8306e_regbit_set(port, 18, 15, 2, 0);
+        } 
+        else 
+        {
+            rtl8306e_regbit_set(port, 18, 15, 2, 1);
+            rtl8306e_reg_get(port, 18, 2, &regValue);
+            regValue = (regValue & 0xF800) | (n64Kbps & 0x7FF);
+            rtl8306e_reg_set(port, 18, 2, regValue);
+        }
+    }
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_portRate_get
+ * Description:
+ *      Get port bandwidth control rate
+ * Input:
+ *      port                 -  Port number (0~5)
+ * Output:
+ *      *pN64Kbps        -  Port rate (0~1526), unit 64Kbps
+ *      direction           -  Input or output bandwidth control
+ *      *enabled           -  enabled or disabled bandwidth control
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      For each port, both input and output bandwidth could be configured, 
+ *      RTL8306_PORT_RX represents port input bandwidth control, 
+ *      RTL8306_PORT_TX represents port output bandwidth control.
+ *      port rate unit is 64Kbps. For output rate control, enable/disable 
+ *      is configured per port, but for input rate control, it is for all port.
+ */
+int32 rtl8306e_qos_portRate_get(uint32 port, uint32 *pN64Kbps, uint32 direction, uint32 *pEnabled) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) || (NULL == pN64Kbps) || (direction > RTL8306_PORT_TX) || (NULL == pEnabled))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+
+    if (RTL8306_PORT_RX == direction)
+    {
+        /*Get port Rx rate*/
+        rtl8306e_regbit_get(0, 21, 15, 3, &regValue);
+        *pEnabled = (regValue ? FALSE:TRUE);
+        rtl8306e_reg_get(port, 21, 2, &regValue);
+        *pN64Kbps = regValue & 0x7FF;
+    } 
+    else 
+    { 
+        /*Get port Tx rate*/
+        rtl8306e_regbit_get(port, 18, 15, 2, pEnabled);
+        rtl8306e_reg_get(port, 18, 2, &regValue);
+        *pN64Kbps = regValue & 0x7FF;
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_1pRemarkEnable_set
+ * Description:
+ *      Set 802.1P remarking ability
+ * Input:
+ *      port       -  port number (0~5)
+ *      enabled  -  TRUE or FALSE
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      
+ */
+int32 rtl8306e_qos_1pRemarkEnable_set(uint32 port, uint32 enabled)
+{
+
+    if (port > RTL8306_PORT5)
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;
+    /*enable new 1p remarking function*/
+    rtl8306e_regbit_set(0, 28, 13, 3, 1);
+    rtl8306e_regbit_set(port, 17, 0, 2, enabled ? 1:0);
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.vlanConfig_perport[port].en1PRemark= (uint8) enabled;
+#endif
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_1pRemarkEnable_set
+ * Description:
+ *      Get 802.1P remarking ability
+ * Input:
+ *      port        -  port number (0~5)
+ * Output:
+ *      pEnabled  -  pointer of the ability status
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      
+ */
+int32 rtl8306e_qos_1pRemarkEnable_get(uint32 port, uint32 *pEnabled) 
+{
+    uint32 bitValue;
+    
+    if (port > RTL8306_PORT5 || (NULL == pEnabled))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;
+    
+    rtl8306e_regbit_get(port, 17, 0, 2, &bitValue);
+    *pEnabled = (bitValue ? TRUE:FALSE);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_1pRemark_set
+ * Description:
+ *      Set 802.1P remarking priority
+ * Input:
+ *      priority       -  Packet priority(0~4)
+ *      priority1p    -  802.1P priority(0~7)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+int32 rtl8306e_qos_1pRemark_set(uint32 priority, uint32 priority1p)
+{
+    uint32 regValue;
+
+    if ( (priority > 3) || (priority1p > 0x7) ) 
+        return FAILED;
+    
+    rtl8306e_reg_get(0, 24, 3, &regValue);
+    switch(priority) 
+    {
+        case 0:
+            regValue = (regValue & 0xFFF8) | priority1p;
+            break;
+        case 1:
+            regValue = (regValue & 0xFFC7) | (priority1p << 3);
+            break;
+        case 2:
+            regValue = (regValue & 0xFE3F) | (priority1p <<6);
+            break;
+        case 3:
+            regValue = (regValue & 0xF1FF) | (priority1p <<9);
+            break;
+        default:
+            return FAILED;
+    }    
+    rtl8306e_reg_set(0, 24, 3, regValue);
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.dot1PremarkCtl[priority] = (uint8) priority1p;
+#endif
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306_getAsic1pRemarkingPriority
+ * Description:
+ *      Get 802.1P remarking priority
+ * Input:
+ *      priority       -  Packet priority(0~4)
+ * Output:
+ *      pPriority1p  -  the pointer of 802.1P priority(0~7)
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+int32 rtl8306e_qos_1pRemark_get(uint32 priority, uint32 *pPriority1p) 
+{
+    uint32 regValue;
+
+    if ( (priority > 3) || (NULL == pPriority1p) ) 
+        return FAILED;
+    
+    rtl8306e_reg_get(0, 24, 3, &regValue);
+    switch(priority)
+    {
+        case 0:
+            *pPriority1p = (regValue & 0x7);
+            break;
+        case 1:
+            *pPriority1p = (regValue & 0x0038) >> 3;
+            break;
+        case 2:
+            *pPriority1p = (regValue & 0x01C0) >> 6;
+            break;
+        case 3:
+            *pPriority1p = (regValue & 0x0E00) >> 9;
+            break;
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_portPri_set
+ * Description:
+ *      Set port-based priority
+ * Input:
+ *      port          -  port number (0~5)
+ *      priority      -  Packet port-based priority(0~3)
+ * Output:
+*       none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      packet will be assigned a port-based priority correspond to the ingress port.
+ */
+int32 rtl8306e_qos_portPri_set(uint32 port, uint32 priority)
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) ||(priority > 3))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    
+    rtl8306e_reg_get(port, 17, 2, &regValue);
+    regValue = (regValue & 0xE7FF) | (priority << 11);
+    rtl8306e_reg_set(port, 17, 2, regValue);
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_portPri_get
+ * Description:
+ *      Get port-based priority
+ * Input:
+ *      port          -  port number (0~5)
+ * Output:
+ *      pPriority    -   pointer of packet port-based priority(0~4)
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      packet will be assigned a port-based priority correspond to the ingress port.
+ */ 
+int32 rtl8306e_qos_portPri_get(uint32 port, uint32 *pPriority) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) ||(NULL == pPriority))
+        return FAILED;
+    
+    if (port < RTL8306_PORT5) 
+        rtl8306e_reg_get(port, 17, 2, &regValue);
+    else
+        rtl8306e_reg_get(6, 17, 2, &regValue);
+    
+    *pPriority = (regValue & 0x1800) >> 11;
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_1pPriRemap_set
+ * Description:
+ *      Set Asic 1Q-tag priority mapping to 2-bit priority
+ * Input:
+ *      tagprio  -  1Q-tag proirty (0~7, 3 bit value)
+ *      prio      -   internal use 2-bit priority
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch internal use 2-bit priority, so it should map 3-bit 1Q-tag priority
+ *      to 2-bit priority
+ */ 
+int32 rtl8306e_qos_1pPriRemap_set(uint32 tagprio, uint32 prio) 
+{
+    uint32 regValue;
+
+    if ((tagprio > RTL8306_1QTAG_PRIO7) || (prio > RTL8306_PRIO3 ))
+        return FAILED;
+    
+    rtl8306e_reg_get(2, 24, 3, &regValue);
+    switch(tagprio) 
+    {
+        case RTL8306_1QTAG_PRIO0:
+            regValue = (regValue & 0xFFFC) | prio;
+            break;
+        case RTL8306_1QTAG_PRIO1:
+            regValue = (regValue & 0xFFF3) |(prio << 2);
+            break;
+        case RTL8306_1QTAG_PRIO2:
+            regValue = (regValue & 0xFFCF) | (prio << 4);
+            break;
+        case RTL8306_1QTAG_PRIO3:
+            regValue = (regValue & 0xFF3F) | (prio << 6);
+            break;
+        case RTL8306_1QTAG_PRIO4:
+            regValue = (regValue & 0xFCFF) | (prio << 8);
+            break;
+        case RTL8306_1QTAG_PRIO5:
+            regValue = (regValue & 0xF3FF) | (prio << 10);
+            break;
+        case RTL8306_1QTAG_PRIO6:
+            regValue = (regValue & 0xCFFF) | (prio << 12);
+            break;
+        case RTL8306_1QTAG_PRIO7:
+            regValue = (regValue & 0x3FFF) | (prio << 14);
+            break;
+        default:
+            return FAILED;
+    }    
+
+    rtl8306e_reg_set(2, 24, 3, regValue);    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_1pPriRemap_get
+ * Description:
+ *      Get Asic 1Q-tag priority mapping to 2-bit priority
+ * Input:
+ *      tagprio  -  1Q-tag proirty (0~7, 3 bit value)
+ * Output:
+ *      pPrio     -  pointer of  internal use 2-bit priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch internal use 2-bit priority, so it should map 3-bit 1Q-tag priority
+ *      to 2-bit priority
+ */ 
+int32 rtl8306e_qos_1pPriRemap_get(uint32 tagprio, uint32 *pPrio) 
+{
+    uint32 regValue;
+    
+    if ((tagprio > RTL8306_1QTAG_PRIO7) || (NULL == pPrio))
+        return FAILED;
+    
+    rtl8306e_reg_get(2, 24, 3, &regValue);
+    switch(tagprio) 
+    {
+        case RTL8306_1QTAG_PRIO0:
+            *pPrio = regValue & 0x3;
+            break;
+        case RTL8306_1QTAG_PRIO1:
+            *pPrio = (regValue & 0xC) >> 2;
+            break;
+        case RTL8306_1QTAG_PRIO2:
+            *pPrio = (regValue & 0x30) >> 4;
+            break;
+        case RTL8306_1QTAG_PRIO3:
+            *pPrio = (regValue & 0xC0) >> 6;
+            break;
+        case RTL8306_1QTAG_PRIO4:
+            *pPrio = (regValue & 0x300) >> 8;
+            break;
+        case RTL8306_1QTAG_PRIO5:
+            *pPrio = (regValue & 0xC00) >> 10;
+            break;
+        case RTL8306_1QTAG_PRIO6:
+            *pPrio = (regValue & 0x3000) >> 12;
+            break;
+        case RTL8306_1QTAG_PRIO7:
+            *pPrio = (regValue & 0xC000) >> 14;
+            break;
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_dscpPriRemap_set
+ * Description:
+ *      Set DSCP-based priority
+ * Input:
+ *      code      -  dscp code
+ *      priority   -  dscp-based priority
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *     
+ */ 
+int32 rtl8306e_qos_dscpPriRemap_set(uint32 code, uint32 priority) 
+{
+    uint32 regValue1, regValue2;
+
+    if ((code > RTL8306_DSCP_BF) ||(priority > RTL8306_PRIO3))
+        return FAILED;
+
+    rtl8306e_reg_get(1, 23, 3, &regValue1);
+    rtl8306e_reg_get(1, 24, 3, &regValue2);
+    switch(code) 
+    {
+        case RTL8306_DSCP_EF:
+            regValue1 = (regValue1 & 0xFFFC) | priority;
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;            
+        case RTL8306_DSCP_AFL1:
+            regValue1 = (regValue1 & 0xFFF3) | (priority << 2);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFM1:
+            regValue1 = (regValue1 & 0xFFCF) | (priority << 4);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFH1:
+            regValue1 = (regValue1 & 0xFF3F) | (priority << 6);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFL2:
+            regValue1 = (regValue1 & 0xFCFF) | (priority << 8);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFM2:
+            regValue1 = (regValue1 & 0xF3FF) | (priority << 10);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFH2:
+            regValue1 = (regValue1 & 0xCFFF) |(priority << 12);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFL3:
+            regValue1 = (regValue1 & 0x3FFF) | (priority << 14);
+            rtl8306e_reg_set(1, 23, 3, regValue1);
+            break;
+        case RTL8306_DSCP_AFM3:
+            regValue2 = (regValue2 & 0xFFFC) | priority;
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_AFH3:
+            regValue2 = (regValue2 & 0xFFF3) | (priority <<2);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_AFL4:
+            regValue2 = (regValue2 & 0xFFCF) | (priority <<4);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_AFM4:
+            regValue2 = (regValue2 & 0xFF3F) | (priority << 6);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_AFH4:
+            regValue2 = (regValue2 & 0xFCFF) | (priority << 8);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_NC:
+            regValue2 = (regValue2 & 0xF3FF) | (priority << 10);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_REG_PRI:
+            regValue2 = (regValue2 & 0xCFFF) | (priority << 12);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        case RTL8306_DSCP_BF:
+            regValue2 = (regValue2 & 0x3FFF) | (priority << 14);
+            rtl8306e_reg_set(1, 24, 3, regValue2);
+            break;
+        default:
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_dscpPriRemap_set
+ * Description:
+ *      Get DSCP-based priority
+ * Input:
+ *      code      -  dscp code
+ * Output:
+ *      pPriority  -  the pointer of dscp-based priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *     
+ */ 
+int32 rtl8306e_qos_dscpPriRemap_get(uint32 code, uint32 *pPriority) 
+{
+    uint32  regValue1, regValue2;
+
+    if ((code > RTL8306_DSCP_BF) || (NULL == pPriority))
+        return FAILED;
+    
+    rtl8306e_reg_get(1, 23, 3, &regValue1);
+    rtl8306e_reg_get(1, 24, 3, &regValue2);
+    switch(code) 
+    {
+        case RTL8306_DSCP_EF:
+            *pPriority = regValue1 & 0x3;
+            break;
+        case RTL8306_DSCP_AFL1:
+            *pPriority = (regValue1 & 0xC)  >> 2;
+            break;
+        case RTL8306_DSCP_AFM1:
+            *pPriority = (regValue1 & 0x30) >> 4;
+            break;
+        case RTL8306_DSCP_AFH1:
+            *pPriority = (regValue1 & 0xC0) >> 6;
+            break;
+        case RTL8306_DSCP_AFL2:
+            *pPriority = (regValue1 & 0x300) >> 8;
+            break;
+        case RTL8306_DSCP_AFM2:
+            *pPriority = (regValue1 & 0xC00) >> 10;
+            break;
+        case RTL8306_DSCP_AFH2:
+            *pPriority = (regValue1 & 0x3000) >> 12;
+            break;
+        case RTL8306_DSCP_AFL3:
+            *pPriority = (regValue1 & 0xC000) >> 14;
+            break;
+        case RTL8306_DSCP_AFM3:
+            *pPriority = regValue2 & 0x3;
+            break;
+        case RTL8306_DSCP_AFH3:
+            *pPriority = (regValue2 & 0xC) >> 2;
+            break;
+        case RTL8306_DSCP_AFL4:
+            *pPriority = (regValue2 & 0x30) >> 4;
+            break;
+        case RTL8306_DSCP_AFM4:
+            *pPriority = (regValue2 & 0xC0) >> 6;
+            break;
+        case RTL8306_DSCP_AFH4:
+            *pPriority = (regValue2 & 0x300) >> 8;
+            break;
+        case RTL8306_DSCP_NC:
+            *pPriority = (regValue2 & 0xC00) >>10;
+            break;
+        case RTL8306_DSCP_REG_PRI:
+            *pPriority = (regValue2 & 0x3000) >> 12;
+            break;
+        case RTL8306_DSCP_BF:
+            *pPriority = (regValue2 & 0xC000) >> 14;
+            break;
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+} 
+
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcArbit_set
+ * Description:
+ *      Set priority source arbitration level
+ * Input:
+ *      priArbit  - The structure describe levels of 5 kinds of priority 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch could recognize 7 types of priority source at most, 
+ *      and a packet properly has all of them. among them, there 
+ *      are 5 type priorities could be set priority level, they are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority,
+ *      Port-based priority, VID- based priority.each one could be 
+ *      set level from 0 to 5, arbitration module will decide their sequece 
+ *      to take, the highest level priority will be adopted at first, 
+ *      then  priority type of the sencond highest level. priority with level 0
+ *      will not be recognized any more. 
+ */
+
+int32 rtl8306e_qos_priSrcArbit_set(rtl8306e_qosPriArbitPara_t priArbit) 
+{
+    uint32 regval;
+
+    if ((priArbit.acl_pri_lev > 5) || (priArbit.dscp_pri_lev > 5) ||
+        (priArbit.dot1q_pri_lev > 5)   || (priArbit.port_pri_lev > 5)  ||
+        (priArbit.vid_pri_lev > 5))
+        return FAILED;
+    
+    /*vid based priority selection*/
+    rtl8306e_reg_get(0, 28, 3, &regval);
+    regval &= ~(0x1F << 8);
+    if (priArbit.vid_pri_lev)
+        regval |= (1 << (priArbit.vid_pri_lev -1 + 8));
+    rtl8306e_reg_set(0, 28, 3, regval);
+
+    /*acl based priority*/
+    rtl8306e_reg_get(1, 21, 3, &regval);
+    regval &= ~(0xF << 12);
+    rtl8306e_reg_set(1, 21, 3, regval);    
+    rtl8306e_regbit_set(0, 28, 7, 3, 0);
+    if (5 == priArbit.acl_pri_lev)
+    {
+        rtl8306e_regbit_set(0, 28, 7, 3, 1);
+    }
+    else if (priArbit.acl_pri_lev > 0)
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval); 
+        regval |= (1 << (priArbit.acl_pri_lev -1 + 12));
+        rtl8306e_reg_set(1, 21, 3, regval);
+    }
+        
+    /*dscp based priority*/
+    rtl8306e_reg_get(1, 21, 3, &regval);
+    regval &= ~(0xF << 8);
+    rtl8306e_reg_set(1, 21, 3, regval);    
+    rtl8306e_regbit_set(0, 26, 15, 3, 0);
+    if (5 == priArbit.dscp_pri_lev)
+    {
+        rtl8306e_regbit_set(0, 26, 15, 3, 1);
+    }
+    else if (priArbit.dscp_pri_lev > 0)
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval);
+        regval |= (1 << (priArbit.dscp_pri_lev -1 + 8));
+        rtl8306e_reg_set(1, 21, 3, regval);
+    }
+    
+    /*1Q based priority*/
+    rtl8306e_reg_get(1, 21, 3, &regval);
+    regval &= ~(0xF << 4);
+    rtl8306e_reg_set(1, 21, 3, regval);
+    rtl8306e_regbit_set(0, 26, 14, 3, 0);
+    if (5 == priArbit.dot1q_pri_lev)
+    {
+        rtl8306e_regbit_set(0, 26, 14, 3, 1);                    
+    }
+    else if (priArbit.dot1q_pri_lev > 0)
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval);        
+        regval |= ( 1 << (priArbit.dot1q_pri_lev -1 + 4));
+        rtl8306e_reg_set(1, 21, 3, regval);
+    }
+
+    /*port based priority*/
+    rtl8306e_reg_get(1, 21, 3, &regval);
+    regval &= ~0xF;
+    rtl8306e_reg_set(1, 21, 3, regval);
+    rtl8306e_regbit_set(0, 26, 13, 3, 0);
+    if (5 == priArbit.port_pri_lev)
+    {
+        rtl8306e_regbit_set(0, 26, 13, 3, 1);        
+    }
+    else if (priArbit.port_pri_lev > 0)
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval); 
+        regval |= (1 << (priArbit.port_pri_lev -1));
+        rtl8306e_reg_set(1, 21, 3, regval);
+    }
+    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcArbit_get
+ * Description:
+ *      Get priority source arbitration level
+ * Input:
+ *      none 
+ * Output:
+ *      pPriArbit  - The structure describe levels of 5 kinds of priority 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch could recognize 7 types of priority source at most, 
+ *      and a packet properly has all of them. among them, there 
+ *      are 5 type priorities could be set priority level, they are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority,
+ *      Port-based priority, VID- based priority.each one could be 
+ *      set level from 0 to 5, arbitration module will decide their sequece 
+ *      to take, the highest level priority will be adopted at first, 
+ *      then  priority type of the sencond highest level. priority with level 0
+ *      will not be recognized any more. 
+ */
+int32 rtl8306e_qos_priSrcArbit_get(rtl8306e_qosPriArbitPara_t *pPriArbit)
+{
+    uint32 regval;
+    uint32 i ;
+        
+    if (NULL == pPriArbit)
+        return FAILED;
+
+    pPriArbit ->acl_pri_lev      = 0;
+    pPriArbit ->dot1q_pri_lev  = 0;
+    pPriArbit ->dscp_pri_lev   = 0;
+    pPriArbit ->port_pri_lev    = 0;
+    pPriArbit ->vid_pri_lev      = 0;
+
+    /*vid based priority selection*/
+    rtl8306e_reg_get(0, 28, 3, &regval);
+    regval &= (0x1F << 8);
+    regval >>= 8;
+    for (i = 5; i > 0; i --)
+    {
+        if(regval >> (i-1))
+        {
+            pPriArbit ->vid_pri_lev = i;
+            break;
+        }
+    }
+
+    /*acl based priority*/
+    rtl8306e_regbit_get(0, 28, 7, 3, &regval);
+    if(regval)
+    {
+        pPriArbit->acl_pri_lev = 5;
+    }
+    else
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval);
+        regval &= (0xF << 12);
+        regval >>= 12;
+        for (i = 4; i > 0; i --)
+        {
+            if(regval >> (i-1))
+            {
+                pPriArbit ->acl_pri_lev = i;
+                break;
+            }
+        }        
+    }
+
+    /*dscp based priority*/
+    rtl8306e_regbit_get(0, 26, 15, 3, &regval);
+    if (regval)
+    {
+        pPriArbit ->dscp_pri_lev = 5;
+    }
+    else
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval);
+        regval &= (0xF << 8);
+        regval >>= 8;
+        for (i = 4; i > 0; i --)
+        {
+            if(regval >> (i-1))
+            {
+                pPriArbit ->dscp_pri_lev =  i;
+                break;
+            }
+        }                
+    }
+
+    /*1Q based priority*/
+    rtl8306e_regbit_get(0, 26, 14, 3, &regval);
+    if (regval)
+    {
+        pPriArbit ->dot1q_pri_lev = 5;
+    }
+    else
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval);
+        regval &= (0xF << 4);
+        regval >>= 4;
+        for (i = 4; i > 0; i --)
+        {
+            if(regval >> (i-1))
+            {
+                pPriArbit ->dot1q_pri_lev = i;
+                break;
+            }
+        }                        
+    }
+
+    /*port based priority*/
+    rtl8306e_regbit_get(0, 26, 13, 3, &regval);
+    if (regval)
+    {
+        pPriArbit ->port_pri_lev = 5;
+    }
+    else 
+    {
+        rtl8306e_reg_get(1, 21, 3, &regval);
+        regval &= 0xF;
+
+        for (i = 4; i > 0; i --)
+        {
+            if(regval >> (i-1))
+            {
+                pPriArbit ->port_pri_lev = i;
+                break;
+            }
+        }                                
+    }
+        
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcEnable_set
+ * Description:
+ *      enable/disable Qos priority source for ingress port
+ * Input:
+ *      port      -  Specify port number (0 ~5)
+ *      priSrc    -  Specify priority source  
+ *      enabled -   TRUE of FALSE  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 kind of priority source for each port which could
+ *     be enabled ordisabled:
+ *          RTL8306_DSCP_PRIO     - DSCP-based priority
+ *          RTL8306_1QBP_PRIO     - 1Q-based priority
+ *          RTL8306_PBP_PRIO        - port-based priority
+ *          RTL8306_CPUTAG_PRIO  - cpu tag priority
+ */
+int32 rtl8306e_qos_priSrcEnable_set(uint32 port, uint32 priSrc, uint32 enabled) 
+{
+    uint32 duplex, speed, nway;
+      
+    if (port > RTL8306_PORT5)
+        return FAILED;
+
+    duplex = 0;
+    speed = 0;
+    nway = 0;
+    
+    /*save mac 4 or port status when operate reg.22*/    
+    if (4 == port) 
+    {
+        rtl8306e_regbit_get(5, 0, 13, 0, &speed);
+        rtl8306e_regbit_get(5, 0, 12, 0, &nway);
+        rtl8306e_regbit_get(5, 0, 8, 0, &duplex);            
+    } 
+    else if (5 == port) 
+    {
+        rtl8306e_regbit_get(6, 0, 13, 0, &speed);
+        rtl8306e_regbit_get(6, 0, 12, 0, &nway);
+        rtl8306e_regbit_get(6, 0, 8, 0, &duplex);            
+    }
+
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    
+    switch(priSrc) 
+    {
+        case RTL8306_DSCP_PRIO:
+            rtl8306e_regbit_set(port, 22, 9, 0, enabled ? 0:1);
+            break;
+        case RTL8306_1QBP_PRIO:
+            rtl8306e_regbit_set(port, 22, 10, 0, enabled ? 0:1);
+            break;
+        case RTL8306_PBP_PRIO:
+            rtl8306e_regbit_set(port, 22, 8, 0, enabled ? 0:1);
+            break;
+        case RTL8306_CPUTAG_PRIO:
+            rtl8306e_regbit_set(port, 17, 1, 2, enabled ? 1:0);
+            break;
+        default:
+            return FAILED;
+    }
+    
+    /*restore mac 4 or port status when operate reg.22*/    
+    if (4 == port) 
+    {
+        rtl8306e_regbit_set(5, 0, 13, 0, speed);
+        rtl8306e_regbit_set(5, 0, 12, 0, nway);
+        rtl8306e_regbit_set(5, 0, 8, 0, duplex);            
+    }
+    else if (6 == port) 
+    { 
+        /*for port++ when port 5*/
+        rtl8306e_regbit_set(6, 0, 13, 0, speed);
+        rtl8306e_regbit_set(6, 0, 12, 0, nway);
+        rtl8306e_regbit_set(6, 0, 8, 0, duplex);
+    }      
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcEnable_set
+ * Description:
+ *      enable/disable Qos priority source for  ingress port
+ * Input:
+ *      port       -  Specify port number (0 ~5)
+ *      priSrc     -  Specify priority source  
+ * Output:
+ *      pEnabled -  the pointer of priority source status  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 kind of priority source for each port which could
+ *     be enabled ordisabled:
+ *          RTL8306_DSCP_PRIO     - DSCP-based priority
+ *          RTL8306_1QBP_PRIO     - 1Q-based priority
+ *          RTL8306_PBP_PRIO        - port-based priority
+ *          RTL8306_CPUTAG_PRIO  - cpu tag priority
+ */
+int32 rtl8306e_qos_priSrcEnable_get(uint32 port, uint32 priSrc, uint32 *pEnabled) 
+{
+    uint32 bitValue;
+
+    if ((port > RTL8306_PORT5) || (NULL == pEnabled))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (port == RTL8306_PORT5 )  
+        port ++ ;  
+    
+    switch(priSrc)
+    {
+        case RTL8306_DSCP_PRIO:
+            rtl8306e_regbit_get(port, 22, 9, 0, &bitValue);
+            *pEnabled = (bitValue ? FALSE : TRUE);
+            break;
+        case RTL8306_1QBP_PRIO:
+            rtl8306e_regbit_get(port, 22, 10, 0, &bitValue);
+            *pEnabled = (bitValue ? FALSE : TRUE);
+            break;
+        case RTL8306_PBP_PRIO:
+            rtl8306e_regbit_get(port, 22, 8, 0, &bitValue);
+            *pEnabled = (bitValue ? FALSE : TRUE);
+            break;
+        case RTL8306_CPUTAG_PRIO:
+            rtl8306e_regbit_get(port, 17, 1, 2, &bitValue);
+            *pEnabled = (bitValue ? TRUE : FALSE);
+            break;
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddrPri_set
+ * Description:
+ *      Set IP address priority
+ * Input:
+ *      priority  -  internal use 2-bit priority value (0~3)  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+int32 rtl8306e_qos_ipAddrPri_set(uint32 priority) 
+{
+    uint32 regValue;
+
+    if (priority > 3)
+        return FAILED;
+    
+    rtl8306e_reg_get(2, 22, 3, &regValue);
+    rtl8306e_reg_set(2, 22, 3, (regValue & 0xFFFC) |priority);
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddrPri_get
+ * Description:
+ *      Get IP address priority
+ * Input:
+ *      priority  -  internal use 2-bit priority value (0~3)  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+int32 rtl8306e_qos_ipAddrPri_get(uint32 *priority)
+{
+    uint32 regValue;
+
+    if (priority == NULL)
+        return FAILED;
+    
+    rtl8306e_reg_get(2, 22, 3, &regValue);
+    *priority =  regValue & 0x3;
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddr_set
+ * Description:
+ *      Set IP address
+ * Input:
+ *      entry        -   specify entry
+         ip            -   ip address
+         mask        -  ip mask
+         enabled    -   enable the entry
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are two entries RTL8306_IPADD_A and RTL8306_IPADD_B
+ *      for user setting ip address, if ip address of packet matches
+ *      the entry, the packet will be assign the priority of ip address
+ *      priority which is configured by rtl8306e_qos_ipAddrPri_set.
+ */
+int32 rtl8306e_qos_ipAddr_set(uint32 entry, uint32 ip, uint32 mask, uint32 enabled) 
+{
+    uint32 regValue;
+
+    if (entry > 1) 
+        return FAILED;
+
+    switch(entry) 
+    {
+        case RTL8306_IPADD_A:        
+            if (enabled == TRUE) 
+            {
+                rtl8306e_regbit_set(0, 17, 14, 0, 1);
+                regValue = ip & 0xFFFF;
+                rtl8306e_reg_set(1, 17, 0, regValue);
+                regValue = (ip & 0xFFFF0000) >> 16;
+                rtl8306e_reg_set(1, 16, 0, regValue);
+                regValue = mask & 0xFFFF;
+                rtl8306e_reg_set(2, 17, 0, regValue);
+                regValue = (mask & 0xFFFF0000) >> 16;
+                rtl8306e_reg_set(2, 16, 0, regValue);
+            }    
+            else 
+                rtl8306e_regbit_set(0, 17, 14, 0, 0);
+            break;
+        case RTL8306_IPADD_B:        
+            if (enabled == TRUE)
+            {
+                rtl8306e_regbit_set(0, 17, 6, 0, 1);
+                regValue = ip & 0xFFFF;
+                rtl8306e_reg_set(1, 19, 0, regValue);
+                regValue = (ip & 0xFFFF0000) >> 16;
+                rtl8306e_reg_set(1, 18, 0, regValue);
+                regValue = mask & 0xFFFF;
+                rtl8306e_reg_set(2, 19, 0, regValue);
+                regValue = (mask & 0xFFFF0000) >> 16;
+                rtl8306e_reg_set(2, 18, 0, regValue);
+            }
+            else 
+                rtl8306e_regbit_set(0, 17, 6, 0, 0);        
+            break;
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddr_get
+ * Description:
+ *      Get IP address user seting
+ * Input:
+ *      entry       -   specify entry
+ * Output:
+ *      pIp            -   ip address
+         pMask        -   ip mask
+         pEnabled    -  enabled or disabled the entry for IP Priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+int32 rtl8306e_qos_ipAddr_get(uint32 entry, uint32 *pIp, uint32 *pMask , uint32 *pEnabled) 
+{
+    uint32 hi, lo;
+    uint32 bitValue;
+
+    if ((entry > 1) || (pIp == NULL) || (pMask == NULL) || (pEnabled == NULL))
+        return FAILED;
+    
+    switch (entry) 
+    {
+        case RTL8306_IPADD_A :
+            rtl8306e_reg_get(1, 17, 0, &lo);
+            rtl8306e_reg_get(1, 16, 0, &hi);
+            *pIp = lo + (hi << 16);
+            rtl8306e_reg_get(2, 17, 0, &lo);
+            rtl8306e_reg_get(2, 16, 0, &hi);
+            *pMask = lo + (hi << 16);
+            rtl8306e_regbit_get(0, 17, 14, 0, &bitValue);
+            *pEnabled = (bitValue == 1 ? TRUE : FALSE);
+            break;
+        case RTL8306_IPADD_B :
+            rtl8306e_reg_get(1, 19, 0, &lo);
+            rtl8306e_reg_get(1, 18, 0, &hi);
+            *pIp = lo + (hi << 16);
+            rtl8306e_reg_get(2, 19, 0, &lo);
+            rtl8306e_reg_get(2, 18, 0, &hi);
+            *pMask = lo + (hi << 16); 
+            rtl8306e_regbit_get(0, 17, 6, 0, &bitValue);
+            *pEnabled = (bitValue == 1 ? TRUE : FALSE);
+
+            break;
+        default :
+            return FAILED;
+    }
+
+    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_qos_schedulingPara_set
+ * Description:
+ *      Set qos scheduling parameter
+ * Input:
+ *      set          -  RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ *      sch_para  -  The structure describe schedule parameter
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch supports 4 queue per egress port, scheduling algorithm could be WRR(Weight Round Robin) or 
+ *      SP(Strict Priority). Only high queue Q3 and Q2 could be set as strict priority queue. There two set of 
+ *      scheduling parameter in whole system(RTL8306_QOS_SET0/RTL8306_QOS_SET1), each egress port select
+ *      one of them. The parameter defined by rtl8306e_qosSchPara_t, q0_wt and q1_wt should between 1~127,
+ *      that means Q0 and Q1 WRR weight, q2_wt and  q3_wt could be 0~127, 0 means strict priority. q2_n64Kbps 
+ *      and q3_n64Kbps means Q2/Q3 queue bandwidth control, unit is 64Kbps.
+ */
+int32 rtl8306e_qos_schedulingPara_set(uint32 set, rtl8306e_qosSchPara_t sch_para)
+{
+    uint32 regValue;
+    if ((sch_para.q0_wt > 127) || (sch_para.q1_wt > 127) || (sch_para.q2_wt > 127) ||
+         (sch_para.q3_wt > 127) || (0 == sch_para.q0_wt ) || (0 == sch_para.q1_wt)  ||
+         (sch_para.q2_n64Kbps > 0x7FF) || (sch_para.q3_n64Kbps > 0x7FF))
+         return FAILED;
+
+    switch(set)
+    {
+        case RTL8306_QOS_SET0:   
+            rtl8306e_reg_get(5, 20, 3, &regValue);
+            regValue &= ~0x7F;
+            regValue &= ~(0x7F << 8); 
+            regValue |= (sch_para.q0_wt | (sch_para.q1_wt << 8));
+            rtl8306e_reg_set(5, 20, 3, regValue);
+
+            regValue = 0;
+            regValue |=  (!sch_para.q3_wt) ? (1 << 15) :0;
+            regValue |= (sch_para.q3_wt << 8);
+            regValue |= (!sch_para.q2_wt) ? (1 << 7):0;
+            regValue |= sch_para.q2_wt;
+            rtl8306e_reg_set(5, 21, 3, regValue);
+            
+            rtl8306e_reg_get(5, 18, 3, &regValue);
+            regValue &= ~0x7FF;
+            regValue |= sch_para.q2_n64Kbps;
+            rtl8306e_reg_set(5, 18, 3, regValue);
+            
+            rtl8306e_reg_get(5, 19, 3, &regValue);
+            regValue &= ~0x7FF;
+            regValue |= sch_para.q3_n64Kbps;
+            rtl8306e_reg_set(5, 19, 3, regValue);                        
+            break;
+
+        case RTL8306_QOS_SET1:
+            rtl8306e_reg_get(5, 25, 3, &regValue);
+            regValue &= ~0x7F;
+            regValue &= ~(0x7F << 8); 
+            regValue |= (sch_para.q0_wt | (sch_para.q1_wt << 8));
+            rtl8306e_reg_set(5, 25, 3, regValue);
+
+            regValue = 0;
+            regValue |=  (!sch_para.q3_wt) ? (1 << 15) :0;
+            regValue |= (sch_para.q3_wt << 8);
+            regValue |= (!sch_para.q2_wt) ? (1 << 7):0;
+            regValue |= sch_para.q2_wt;
+            rtl8306e_reg_set(5, 26, 3, regValue);
+
+            rtl8306e_reg_get(5, 23, 3, &regValue);
+            regValue &= ~0x7FF;
+            regValue |= sch_para.q2_n64Kbps;
+            rtl8306e_reg_set(5, 23, 3, regValue);
+
+            rtl8306e_reg_get(5, 24, 3, &regValue);
+            regValue &= ~0x7FF;
+            regValue |= sch_para.q3_n64Kbps;
+            rtl8306e_reg_set(5, 24, 3, regValue);                                                                       
+            break;
+
+         default:
+            return FAILED;
+    }
+                    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_schedulingPara_get
+ * Description:
+ *      Set qos scheduling parameter
+ * Input:
+ *      set           -  RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ * Output:
+ *      pSch_para  - the pointer of schedule parameter
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch supports 4 queue per egress port, scheduling algorithm could be WRR(Weight Round Robin) or 
+ *      SP(Strict Priority). Only high queue Q3 and Q3 could be set as strict priority queue. There two set of 
+ *      scheduling parameter in whole system(RTL8306_QOS_SET0/RTL8306_QOS_SET1), each egress port select
+ *      one of them. The parameter defined by rtl8306e_qosSchPara_t, q0_wt and q1_wt should between 1~127,
+ *      that means Q0 and Q1 WRR weight, q2_wt and  q3_wt could be 0~127, 0 means strict priority. q2_n64Kbps 
+ *      and q3_n64Kbps means Q2/Q3 queue bandwidth control, unit is 64Kbps.
+ */
+int32 rtl8306e_qos_schedulingPara_get(uint32 set, rtl8306e_qosSchPara_t *pSch_para)
+{
+    uint32 regValue;
+    
+    if (NULL == pSch_para)
+        return FAILED;
+
+    switch(set)
+    {
+        case RTL8306_QOS_SET0:
+            rtl8306e_reg_get(5, 20, 3, &regValue);            
+            pSch_para->q0_wt = regValue & 0x7F;
+            pSch_para->q1_wt = (regValue & (0x7F << 8)) >> 8;
+
+            rtl8306e_reg_get(5, 21, 3, &regValue);
+            pSch_para->q2_wt = regValue & 0x7F;
+            pSch_para->q3_wt = (regValue & (0x7F << 8)) >> 8;
+            if (regValue & (1 << 7))
+            {
+                pSch_para->q2_wt = 0;
+            }
+            
+            if (regValue & (1 << 15))
+            {
+                pSch_para->q3_wt = 0;
+            }
+
+            rtl8306e_reg_get(5, 18, 3, &regValue);
+            pSch_para->q2_n64Kbps = regValue & 0x7FF;
+            rtl8306e_reg_get(5, 19, 3, &regValue);
+            pSch_para->q3_n64Kbps = regValue & 0x7FF;
+                        
+            break;
+            
+        case RTL8306_QOS_SET1:
+            rtl8306e_reg_get(5, 25, 3, &regValue);            
+            pSch_para->q0_wt = regValue & 0x7F;
+            pSch_para->q1_wt = (regValue & (0x7F << 8)) >> 8;
+            
+            rtl8306e_reg_get(5, 26, 3, &regValue);
+            pSch_para->q2_wt = regValue & 0x7F;
+            pSch_para->q3_wt = (regValue & (0x7F << 8)) >> 8;
+
+            if (regValue & (1 << 7))
+            {
+                pSch_para->q2_wt = 0;
+            }
+            
+            if (regValue & (1 << 15))
+            {
+                pSch_para->q3_wt = 0;
+            }
+            
+            rtl8306e_reg_get(5, 23, 3, &regValue);
+            pSch_para->q2_n64Kbps = regValue & 0x7FF;
+            rtl8306e_reg_get(5, 24, 3, &regValue);
+            pSch_para->q3_n64Kbps = regValue & 0x7FF;            
+            
+            break;
+        default:
+            return FAILED;
+    }
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_portSchedulingMode_set
+ * Description:
+ *      Select port schedule algorithm  from two sets.
+ * Input:
+ *      port    -   port number (0 ~ 5)
+ *      set     -   RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ *      lbmsk  -   Queue mask for enable queue leaky buckt
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are two sets configuration for schedule mode including strict priority 
+ *      enable/disable, queue weight and queue leaky bucket, every port could select
+ *      one of them. Queue leaky bucket of each port could be enable separately, so 
+ *      you can set queue mask to enable/disable them, because only queue 3 and queue 2
+ *      have leaky bucket, only bit 3 and bit 2 of quemask have effect, bit 3 represents
+ *      queue 3 and set 1 to enable it.
+ */
+int32 rtl8306e_qos_portSchedulingMode_set(uint32 port, uint32 set, uint32 lbmsk)
+{
+    uint32 regValue;
+    
+    if ((port > RTL8306_PORT5) ||(set > 1))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ; 
+    
+    lbmsk = ((lbmsk & 0x8) >> 3 ) | ((lbmsk & 0x4) >> 1);
+    rtl8306e_reg_get(port, 18, 2, &regValue);
+    regValue = (regValue & 0x97FF) | (lbmsk << 13) | (set & 0x1) << 11;
+    rtl8306e_reg_set(port, 18, 2, regValue);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_qos_portSchedulingMode_get
+ * Description:
+ *      Get which set of schedule algorithm  for the specified port 
+ * Input:
+ *      port    -   port number (0 ~ 5)
+ *      set     -   RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ *      lbmsk  -   Queue mask for enable queue leaky buckt
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are two sets configuration for schedule mode including strict priority 
+ *      enable/disable, queue weight and queue leaky bucket, every port could select
+ *      one of them. Queue leaky bucket of each port could be enable separately, so 
+ *      you can set queue mask to enable/disable them, because only queue 3 and queue 2
+ *      have leaky bucket, only bit 3 and bit 2 of quemask have effect, bit 3 represents
+ *      queue 3 and set 1 to enable it.
+ */
+int32 rtl8306e_qos_portSchedulingMode_get(uint32 port, uint32 *pSet, uint32 *pLbmsk) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) ||(NULL == pSet) || (NULL == pLbmsk))
+        return FAILED;
+
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+
+    rtl8306e_reg_get(port, 18, 2, &regValue );
+    *pSet = (regValue >> 11) & 0x1;
+    *pLbmsk = (regValue >> 13) & 0x3;
+    *pLbmsk = ((*pLbmsk & 0x1) << 3) | ((*pLbmsk & 0x2) << 1);
+    
+    return SUCCESS;
+}
+
+
+int32 rtl8306e_qos_queFlcThr_set(uint32 queue, uint32 type, uint32 onoff, uint32 set, uint32 value)
+{
+    uint32 regValue, mask;
+    uint32 selection;
+    uint32 reg, shift;
+
+    if ((queue > RTL8306_QUEUE3) || (type > RTL8306_FCO_QLEN) ||
+        (onoff > RTL8306_FCON) || (set > RTL8306_FCO_SET1) || (value > 127))
+        return FAILED;
+    
+    selection = (set << 2) | (onoff <<1) |type;
+    value &= 0x7f;
+    switch (selection) 
+    {
+        case 0 :  /*set 0, turn off, DSC*/
+            if (RTL8306_QUEUE0 == queue)
+            {
+                reg = 17;
+                mask = 0xFFF0;
+                shift = 0;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 17;
+                mask = 0xF0FF;
+                shift = 8;
+            } 
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                reg = 20;
+                mask = 0xFFF0;
+                shift = 0;
+            } 
+            else 
+            {
+                reg = 20;
+                mask = 0xF0FF;
+                shift = 8;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            regValue = (regValue & mask) | ((value & 0xf)  << shift);
+            rtl8306e_reg_set(5, reg, 2, regValue);
+        
+             /*flc bit[6:4]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);  
+                regValue &= 0xfff8;
+                regValue |= (value & 0x70) >> 4;
+                rtl8306e_reg_set(1, 26, 3, regValue);                
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);  
+                regValue &= 0xfe3f;
+                regValue |= ((value & 0x70) >> 4) << 6;
+                rtl8306e_reg_set(1, 26, 3, regValue);
+            }
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);  
+                regValue &= 0x8fff;
+                regValue |=   ((value & 0x70) >> 4) << 12;
+                rtl8306e_reg_set(1, 26, 3, regValue);                
+            } 
+            else  
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);  
+                regValue &= 0xffe3;
+                regValue |=   ((value & 0x70) >> 4) << 2;
+                rtl8306e_reg_set(1, 27, 3, regValue);
+            }             
+            break;
+        
+        case 1 :     /*set 0, turn off, QLEN*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                reg = 17;
+                mask = 0xFF0F;
+                shift = 4;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 17;
+                mask = 0x0FFF;
+                shift = 12;
+            } 
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                reg = 20;
+                mask = 0xFF0F;
+                shift = 4;
+            } 
+            else  
+            {
+                reg = 20;
+                mask = 0x0FFF;
+                shift = 12;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            regValue = (regValue & mask) | ((value & 0xf) << shift);
+            rtl8306e_reg_set(5, reg, 2, regValue);
+
+            /*bit[6:4]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);  
+                regValue &= 0xffc7;
+                regValue |= ((value & 0x70) >> 4) << 3;
+                rtl8306e_reg_set(1, 26, 3, regValue);                                   
+             } 
+             else if (RTL8306_QUEUE1 == queue) 
+             {
+                rtl8306e_reg_get(1, 26, 3, &regValue);  
+                regValue &= 0xf1ff;
+                regValue |= ((value & 0x70) >> 4) << 9;
+                rtl8306e_reg_set(1, 26, 3, regValue);                                                   
+             }
+             else if (RTL8306_QUEUE2 == queue) 
+             {
+                /*bit[4]*/
+                rtl8306e_reg_get(1, 26, 3, &regValue);                  
+                regValue &= 0x7fff;
+                regValue |= (((value & 0x10) >> 4) << 15);
+                rtl8306e_reg_set(1, 26, 3, regValue);   
+
+                /*bit[6:5]*/
+                rtl8306e_reg_get(1, 27, 3, &regValue);         
+                regValue &= 0xfffc;
+                regValue |= ((value & 0x60) >> 5) ;
+                rtl8306e_reg_set(1, 27, 3, regValue);
+             } 
+             else  
+             {
+                 rtl8306e_reg_get(1, 27, 3, &regValue);       
+                 regValue &= 0xff1f;
+                 regValue |= ((value & 0x70) >> 4) << 5;
+                 rtl8306e_reg_set(1, 27, 3, regValue);
+             }             
+                     
+             break;
+        case 2 :    /*set 0, turn on, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 18;
+            else if (RTL8306_QUEUE1 == queue) 
+                reg = 19;
+            else if (RTL8306_QUEUE2 == queue)
+                reg = 21;
+            else  
+                reg = 22;
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            regValue = (regValue & 0xFFC0) | (value & 0x3f);
+            rtl8306e_reg_set(5, reg, 2, regValue);
+
+             /*bit[6]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_set(5, 21, 7, 2, (value & 0x40) ? 1:0);            
+            }      
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_regbit_set(5, 21, 15, 2, (value & 0x40) ? 1:0);            
+            }
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_set(5, 24, 7, 2, (value & 0x40) ? 1:0);                        
+            }
+            else 
+            {
+                rtl8306e_regbit_set(5, 24, 15, 2, (value & 0x40) ? 1:0);                        
+            }            
+            break;
+            
+        case 3:   /*set 0, turn  on, QLEN*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 18;
+            else if (RTL8306_QUEUE1 == queue) 
+                reg = 19;
+            else if (RTL8306_QUEUE2 == queue) 
+                reg = 21;
+            else  
+                reg = 22;
+            if (queue != RTL8306_QUEUE3)  
+            {
+                rtl8306e_reg_get(5, reg, 2, &regValue);
+                regValue = (regValue & 0xC0FF) | ((value & 0x3f) << 8);
+                rtl8306e_reg_set(5, reg, 2, regValue);
+            }  
+            else 
+            {
+                rtl8306e_reg_get(5, reg, 2, &regValue);
+                regValue = (regValue & 0x3FF) | ((value & 0x3f) << 10);
+                rtl8306e_reg_set(5, reg, 2, regValue);
+            }
+        
+             /*bit[6]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_set(5, 21, 6, 2, (value & 0x40) ? 1:0);    
+            }      
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_regbit_set(5, 21, 14, 2, (value & 0x40) ? 1:0);                      
+            }
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_set(5, 24, 6, 2, (value & 0x40) ? 1:0);                        
+            }
+            else 
+            {
+                rtl8306e_regbit_set(5, 24, 14, 2, (value & 0x40) ? 1:0);                        
+            }                   
+            break;
+        
+        case 4:     /*set 1, turn off, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                reg = 23;
+                mask = 0xFFF0;
+                shift =0;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 23;
+                mask = 0xF0FF;
+                shift =8;
+            } 
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                reg = 26;
+                mask = 0xFFF0;
+                shift =0;
+            }
+            else 
+            {
+                reg = 26;
+                mask = 0xF0FF;
+                shift =8;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            regValue = (regValue & mask) | ((value & 0xf) << shift);
+            rtl8306e_reg_set(5, reg, 2, regValue);
+
+            /*flc bit[6:4]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);  
+                regValue &= 0xf8ff;
+                regValue |= ((value & 0x70) >> 4) << 8;
+                rtl8306e_reg_set(1, 27, 3, regValue);                
+             } 
+             else if (RTL8306_QUEUE1 == queue) 
+             {                
+                rtl8306e_reg_get(1, 27, 3, &regValue);  
+                regValue &= 0x3fff;
+                regValue |= ((value & 0x30) >> 4) << 14;
+                rtl8306e_reg_set(1, 27, 3, regValue);           
+                rtl8306e_regbit_set(1, 28, 0, 3, (value & 0x40) ? 1:0);
+                    
+             }
+             else if (RTL8306_QUEUE2 == queue) 
+             {
+                rtl8306e_reg_get(1, 28, 3, &regValue);
+                regValue &= 0xff8f;
+                regValue |= ((value & 0x70) >> 4) << 4;
+                rtl8306e_reg_set(1, 28, 3, regValue);
+             } 
+             else  
+             {
+                rtl8306e_reg_get(1, 28, 3, &regValue);
+                regValue &= 0xe3ff;
+                regValue |= ((value & 0x70) >> 4) << 10;
+                rtl8306e_reg_set(1, 28, 3, regValue);                
+             }                        
+            break;
+        
+        case 5:     /*set 1, turn off, QLEN*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                reg = 23;
+                mask = 0xFF0F;
+                shift = 4;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 23;
+                mask = 0x0FFF;
+                shift = 12;
+            } 
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                reg = 26;
+                mask = 0xFF0F;
+                shift = 4;
+            } 
+            else 
+            {
+                reg = 26;
+                mask = 0x0FFF;
+                shift = 12;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            regValue = (regValue & mask) | ((value & 0xf) << shift);
+            rtl8306e_reg_set(5, reg, 2, regValue);
+
+             /*bit[6:4]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);  
+                regValue &= 0xc7ff;
+                regValue |= ((value & 0x70) >> 4) << 11;
+                rtl8306e_reg_set(1, 27, 3, regValue);
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_reg_get(1, 28, 3, &regValue);  
+                regValue &= 0xfff1;
+                regValue |= ((value & 0x70) >> 4) << 1;
+                rtl8306e_reg_set(1, 28, 3, regValue);                                
+            }
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                rtl8306e_reg_get(1, 28, 3, &regValue);  
+                regValue &= 0xfc7f;
+                regValue |= ((value & 0x70) >> 4) << 7;
+                rtl8306e_reg_set(1, 28, 3, regValue);                                
+            } 
+            else  
+            {
+                rtl8306e_reg_get(1, 28, 3, &regValue);
+                regValue &= 0x1fff;
+                regValue |= ((value & 0x70) >> 4) << 13;
+                rtl8306e_reg_set(1, 28, 3, regValue);                                                
+            }                                 
+            break;
+        
+        case 6:    /*set 1, turn on, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 24;
+            else if  (RTL8306_QUEUE1 == queue) 
+                reg =25;
+            else if (RTL8306_QUEUE2 == queue) 
+                reg = 27;
+            else  
+                reg = 28;
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            regValue = (regValue & 0xFFC0) | (value & 0x3f);
+            rtl8306e_reg_set(5, reg, 2, regValue);
+
+             /*bit[6]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_set(5, 25, 7, 2, (value & 0x40) ? 1:0);            
+            }      
+            else if(RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_regbit_set(5, 25, 15, 2, (value & 0x40) ? 1:0);            
+            }
+            else if(RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_set(5, 27, 7, 2, (value & 0x40) ? 1:0);            
+            }
+            else 
+            {
+                rtl8306e_regbit_set(5, 27, 15, 2, (value & 0x40) ? 1:0);            
+            }              
+            break;
+        
+        case 7:     /*set 1, turn  on, QLEN*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 24;
+            else if (RTL8306_QUEUE1 == queue) 
+                reg =25;
+            else if (RTL8306_QUEUE2 == queue) 
+                reg = 27;
+            else  
+                reg = 28;
+            if (queue != RTL8306_QUEUE3)  
+            {
+                rtl8306e_reg_get(5, reg, 2, &regValue);
+                regValue = (regValue & 0xC0FF) | ((value & 0x3f) << 8);
+                rtl8306e_reg_set(5, reg, 2, regValue);
+            } 
+            else 
+            {
+                rtl8306e_reg_get(5, reg, 2, &regValue);
+                regValue = (regValue & 0x3FF) | ((value & 0x3f) << 10);
+                rtl8306e_reg_set(5, reg, 2, regValue);
+            }
+
+            /*bit[6]*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_set(5, 25, 6, 2, (value & 0x40) ? 1:0);            
+            }      
+            else if(RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_regbit_set(5, 25, 14, 2, (value & 0x40) ? 1:0);            
+            } 
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_set(5, 27, 6, 2, (value & 0x40) ? 1:0);                        
+            } 
+            else 
+            {
+                rtl8306e_regbit_set(5, 27, 14, 2, (value & 0x40) ? 1:0);                        
+            }              
+            break;
+            
+        default:
+            return FAILED;
+       }
+
+    return SUCCESS;
+}
+
+int32 rtl8306e_qos_queFlcThr_get(uint32 queue, uint32 type, uint32 onoff, uint32 set, uint32* pValue) 
+{
+    uint32 regValue, mask;
+    uint32 selection;
+    uint32 reg, shift = 0;
+    
+    if ((queue > RTL8306_QUEUE3) || (type > RTL8306_FCO_QLEN) || (onoff > RTL8306_FCON) ||
+        (set > RTL8306_FCO_SET1) || (NULL == pValue))
+        return FAILED;
+    
+    selection = (set << 2) | (onoff <<1) |type;
+    *pValue = 0;
+    switch (selection) 
+    {
+        case 0 :    /*set 0, turn off, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                reg = 17;
+                mask = 0xF;
+                shift = 0;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 17;
+                mask = 0x0F00;
+                shift = 8;
+            }
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                reg = 20;
+                mask = 0xF;
+                shift = 0;
+            } else 
+            {
+                reg = 20;
+                mask = 0x0F00;
+                shift = 8;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = (regValue & mask) >> shift;
+
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);
+                regValue &= 0x7;
+                *pValue |= (regValue << 4);                    
+             } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);
+                regValue &= 0x1c0;
+                regValue = regValue >> 6;
+                *pValue |= (regValue << 4);                     
+            } 
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);
+                regValue &= 0x7000;
+                regValue = regValue >> 12;
+                *pValue |= (regValue << 4);                                
+            } 
+            else  
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);
+                regValue &= 0x1c;
+                regValue = regValue >> 2;
+                *pValue |= (regValue << 4);                                                  
+            }                     
+            break;
+        
+        case 1 :    /*set 0, turn off, QLEN*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                reg = 17;
+                mask = 0x00F0;
+                shift = 4;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 17;
+                mask = 0xF000;
+                shift = 12;
+            } 
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                reg = 20;
+                mask = 0x00F0;
+                shift = 4;
+            }
+            else  
+            {
+                reg = 20;
+                mask = 0xF000;
+                shift = 12;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = (regValue & mask) >> shift;
+
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);
+                regValue &= 0x38;
+                regValue = regValue >> 3;
+                *pValue |= (regValue << 4);                                                                           
+             } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);
+                regValue &= 0xe00;
+                regValue = regValue >> 9;
+                *pValue |= (regValue << 4);                                                                                               
+            }
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_reg_get(1, 26, 3, &regValue);
+                regValue &= 0x8000;
+                regValue = regValue >> 15;
+                *pValue |= (regValue << 4);                                                                                               
+                  
+                rtl8306e_reg_get(1, 27, 3, &regValue);
+                regValue &= 0x3;
+                *pValue |= (regValue << 5);                                                                                                       
+            } 
+            else  
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);
+                regValue &= 0xe0;
+                regValue = regValue >> 5;
+                *pValue |= (regValue << 4);  
+            }
+        
+        break;
+        
+        case 2 :    /*set 0, turn on, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 18;
+            else if (RTL8306_QUEUE1 == queue) 
+                reg = 19;
+            else if (RTL8306_QUEUE2 == queue)
+                reg = 21;
+            else  
+                reg = 22;
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = regValue & 0x3F;
+
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_get(5, 21, 7, 2, &regValue);
+                *pValue |= (regValue << 6);
+            }      
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_regbit_get(5, 21, 15, 2, &regValue);
+                *pValue |= (regValue << 6);                
+            }      
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_get(5, 24, 7, 2, &regValue);
+                *pValue |= (regValue << 6);                             
+            }      
+            else  
+            {
+                rtl8306e_regbit_get(5, 24, 15, 2, &regValue);
+                *pValue |= (regValue << 6);                             
+            }              
+            break;
+            
+    case 3:   /*set 0, turn  on, QLEN*/
+        if (RTL8306_QUEUE0 == queue) 
+            reg = 18;
+        else if  (RTL8306_QUEUE1 == queue) 
+            reg = 19;
+        else if (RTL8306_QUEUE2 == queue) 
+            reg = 21;
+        else  
+            reg = 22;
+        if (queue != RTL8306_QUEUE3) 
+        {
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = (regValue & 0x3F00) >> 8 ;
+        } else 
+        {
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = (regValue & 0xFC00) >> 10;
+        }
+
+        if (RTL8306_QUEUE0 == queue) 
+        {
+            rtl8306e_regbit_get(5, 21, 6, 2, &regValue);
+            *pValue |= (regValue << 6);
+        }      
+        else if (RTL8306_QUEUE1 == queue) 
+        {
+            rtl8306e_regbit_get(5, 21, 14, 2, &regValue);
+            *pValue |= (regValue << 6);                
+        }      
+        else if (RTL8306_QUEUE2 == queue)
+        {
+            rtl8306e_regbit_get(5, 24, 6, 2, &regValue);
+            *pValue |= (regValue << 6);                             
+        }      
+        else  
+        {
+            rtl8306e_regbit_get(5, 24, 14, 2, &regValue);
+            *pValue |= (regValue << 6);                             
+        }               
+        break;
+        
+        case 4:     /*set 1, turn off, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                reg = 23;
+                mask = 0x000F;
+                shift =0;
+            } 
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                reg = 23;
+                mask = 0x0F00;
+                shift =8;
+            }
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                reg = 26;
+                mask = 0x000F;
+                shift =0;
+            }
+            else 
+            {
+                reg = 26;
+                mask = 0x0F00;
+                shift =8;
+            }
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = (regValue & mask) >> shift;
+        
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);
+                regValue &= 0x700;
+                regValue = regValue >> 8;                 
+                *pValue |= (regValue << 4);                    
+            }
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                rtl8306e_reg_get(1, 27, 3, &regValue);
+                regValue &= 0xc000;
+                regValue = regValue >> 14;                 
+                *pValue |= (regValue << 4);
+                rtl8306e_regbit_get(1, 28, 0, 3, &regValue);
+                *pValue |= (regValue << 6);                 
+            }
+            else if (RTL8306_QUEUE2 == queue) 
+            {
+                rtl8306e_reg_get(1, 28, 3, &regValue);
+                regValue &= 0x70;
+                 regValue = regValue >> 4;                 
+                 *pValue |= (regValue << 4);  
+            } else  
+            {
+                rtl8306e_reg_get(1, 28, 3, &regValue);
+                regValue &= 0x1c00;
+                regValue = regValue >> 10;                 
+                *pValue |= (regValue << 4);  
+            }                             
+            break;
+        
+    case 5:     /*set 1, turn off, QLEN*/
+        if (RTL8306_QUEUE0 == queue) 
+        {
+            reg = 23;
+            mask = 0xF0;
+            shift = 4;
+        } 
+        else if (RTL8306_QUEUE1 == queue)
+        {
+            reg = 23;
+            mask = 0xF000;
+            shift = 12;
+        }
+        else if (RTL8306_QUEUE2 == queue)
+        {
+            reg = 26;
+            mask = 0xF0;
+            shift = 4;
+        } 
+        else  
+        {
+            reg = 26;
+            mask = 0xF000;
+            shift = 12;
+        }
+        rtl8306e_reg_get(5, reg, 2, &regValue);
+        *pValue = (regValue & mask) >> shift;
+
+        if (RTL8306_QUEUE0 == queue) 
+        {
+            rtl8306e_reg_get(1, 27, 3, &regValue);
+            regValue &= 0x3800;
+            regValue = regValue >> 11;                 
+            *pValue |= (regValue << 4);                    
+        } 
+        else if (RTL8306_QUEUE1 == queue) 
+        {
+            rtl8306e_reg_get(1, 28, 3, &regValue);
+            regValue &= 0xe;
+            regValue = regValue >> 1;                 
+            *pValue |= (regValue << 4);                    
+        } 
+        else if (RTL8306_QUEUE2 == queue)   
+        {
+            rtl8306e_reg_get(1, 28, 3, &regValue);
+            regValue &= 0x380;
+            regValue = regValue >> 7;                 
+            *pValue |= (regValue << 4);
+        }
+        else  
+        {
+            rtl8306e_reg_get(1, 28, 3, &regValue);
+            regValue &= 0xe000;
+            regValue = regValue >> 13;                 
+            *pValue |= (regValue << 4);
+        }                             
+        break;
+        
+        case 6:     /*set 1, turn on, DSC*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 24;
+            else if (RTL8306_QUEUE1 == queue) 
+                reg =25;
+            else if (RTL8306_QUEUE2 == queue) 
+                reg = 27;
+            else  
+                reg = 28;
+            rtl8306e_reg_get(5, reg, 2, &regValue);
+            *pValue = (regValue & 0x3F) >> shift;
+        
+             /*bit 6*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_get(5, 25, 7, 2, &regValue);
+                *pValue |= (regValue << 6);
+            }      
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                 rtl8306e_regbit_get(5, 25, 15, 2, &regValue);
+                 *pValue |= (regValue << 6);                
+             }      
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_get(5, 27, 7, 2, &regValue);
+                *pValue |= (regValue << 6);                             
+            }      
+            else  
+            {
+                rtl8306e_regbit_get(5, 27, 15, 2, &regValue);
+                *pValue |= (regValue << 6);                             
+            }      
+        
+            break;
+        
+        case 7:      /*set 1, turn  on, QLEN*/
+            if (RTL8306_QUEUE0 == queue) 
+                reg = 24;
+            else if (RTL8306_QUEUE1 == queue) 
+                reg =25;
+            else if (RTL8306_QUEUE2 == queue) 
+                reg = 27;
+            else  
+                reg = 28;
+            if (queue != RTL8306_QUEUE3) 
+            {
+                rtl8306e_reg_get(5, reg, 2, &regValue);
+                *pValue = (regValue & 0x3F00) >> 8 ;
+            } 
+            else 
+            {
+                rtl8306e_reg_get(5, reg, 2, &regValue);
+                *pValue = (regValue & 0xFC00) >> 10;
+            }
+             /*bit 6*/
+            if (RTL8306_QUEUE0 == queue) 
+            {
+                rtl8306e_regbit_get(5, 25, 6, 2, &regValue);
+                *pValue |= (regValue << 6);
+            }      
+            else if (RTL8306_QUEUE1 == queue) 
+            {
+                 rtl8306e_regbit_get(5, 25, 14, 2, &regValue);
+                 *pValue |= (regValue << 6);                
+            }      
+            else if (RTL8306_QUEUE2 == queue)
+            {
+                rtl8306e_regbit_get(5, 27, 6, 2, &regValue);
+                *pValue |= (regValue << 6);                             
+            }      
+            else  
+            {
+                rtl8306e_regbit_get(5, 27, 14, 2, &regValue);
+                 *pValue |= (regValue << 6);                             
+            }               
+            break;
+
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+int32 rtl8306e_qos_portFlcThr_set(uint32 port, uint32 onthr, uint32 offthr, uint32 direction ) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) || (direction > 1))
+        return FAILED;
+    
+    regValue = (offthr << 8) + onthr;
+
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;
+    
+    if (RTL8306_PORT_TX == direction) 
+        rtl8306e_reg_set(port, 20, 2, regValue);
+    else 
+        rtl8306e_reg_set(port, 19, 3, regValue);
+    return SUCCESS;
+}
+
+int32 rtl8306e_qos_portFlcThr_get(uint32 port, uint32 *pOnthr, uint32 *pOffthr, uint32 direction) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) || (NULL == pOnthr) || (NULL == pOffthr) || (direction > 1))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ; 
+    
+    if (RTL8306_PORT_TX == direction) 
+        rtl8306e_reg_get(port, 20, 2, &regValue);
+    else 
+        rtl8306e_reg_get(port, 19, 3, &regValue);
+    *pOnthr = regValue & 0xFF;
+    *pOffthr = (regValue & 0xFF00) >> 8;
+    return SUCCESS;
+}
+
+
+int32 rtl8306e_qos_portFlcMode_set(uint32 port, uint32 set) 
+{
+    if ((port > RTL8306_PORT5) || (set > RTL8306_FCO_SET1))
+        return FAILED;
+    
+    if (port < RTL8306_PORT5) 
+        rtl8306e_regbit_set(port, 18, 12, 2, set);
+    else 
+        rtl8306e_regbit_set(6, 18, 12, 2, set);
+    return SUCCESS;
+}
+
+
+int32 rtl8306e_qos_portFlcMode_get(uint32 port , uint32 *set) 
+{
+    if ((port > RTL8306_PORT5) || (set == NULL))
+        return FAILED;
+    
+    if (port < RTL8306_PORT5)
+        rtl8306e_regbit_get(port, 18, 12, 2, set);
+    else
+        rtl8306e_regbit_get(6, 18, 12, 2, set);
+    return SUCCESS;
+}
+
+int32 rtl8306e_qos_queFlcEnable_set( uint32 port, uint32 queue, uint32 enabled) 
+{
+
+    if ((port > RTL8306_PORT5) ||(queue > RTL8306_QUEUE3))
+        return FAILED;
+    
+    /*Enable/Disable Flow control of the specified queue*/
+    switch (port) 
+    {
+        case RTL8306_PORT0:
+            rtl8306e_regbit_set(6, 17, (4 + queue), 0, enabled ? 0:1);
+            break;
+        case RTL8306_PORT1:
+            rtl8306e_regbit_set(6, 18, (4 + queue), 0, enabled ? 0:1);
+            break;
+        case RTL8306_PORT2:
+            rtl8306e_regbit_set(6, 19, (4 + queue), 0, enabled ? 0:1);
+            break;
+        case RTL8306_PORT3:
+            rtl8306e_regbit_set(6, 20, (4 + queue), 0, enabled ? 0:1);
+            break;
+        case RTL8306_PORT4:
+            rtl8306e_regbit_set(6, 21, (4 + queue), 0, enabled ? 0:1);
+            break;
+        case RTL8306_PORT5:
+            rtl8306e_regbit_set(6, 23, (4 + queue), 0, enabled ? 0:1);
+            break;    
+        default:
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+int32 rtl8306e_qos_queFlcEnable_get(uint32 port, uint32 queue, uint32 *pEnabled) 
+{
+    uint32 bitValue;
+
+    if ((port > RTL8306_PORT5) || (queue > RTL8306_QUEUE3) || (NULL == pEnabled))
+        return FAILED;
+    
+    switch (port) 
+    {
+        case RTL8306_PORT0:
+            rtl8306e_regbit_get(6, 17, (4 + queue), 0, &bitValue);
+            break;
+        case RTL8306_PORT1:
+            rtl8306e_regbit_get(6, 18, (4 + queue), 0, &bitValue);
+            break;
+        case RTL8306_PORT2:
+            rtl8306e_regbit_get(6, 19, (4 + queue), 0, &bitValue);
+            break;
+        case RTL8306_PORT3:
+            rtl8306e_regbit_get(6, 20, (4 + queue), 0, &bitValue);
+            break;
+        case RTL8306_PORT4:
+            rtl8306e_regbit_get(6, 21, (4 + queue), 0, &bitValue);
+            break;
+        case RTL8306_PORT5:
+            rtl8306e_regbit_get(6, 23, (4 + queue), 0, &bitValue);
+            break;    
+        default:
+            return FAILED;
+    }
+    *pEnabled = (bitValue ? FALSE : TRUE);
+    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_acl_entry_set
+ * Description:
+ *      Set Asic ACL table
+ * Input:
+ *      entryadd   - Acl entry address (0~15)
+ *      phyport    -  Acl physical port
+ *      action      -  Acl action 
+ *      protocol   -  Acl protocol
+ *      data        -  ether type value or TCP/UDP port
+ *      priority     -  Acl priority
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      phyport could be 
+ *            0~5:       port number, 
+ *            RTL8306_ACL_INVALID: invalid entry,
+ *            RTL8306_ACL_ANYPORT: any port.
+ *      Acl action could be
+ *          RTL8306_ACT_DROP,
+ *          RTL8306_ACT_PERMIT, 
+ *          RTL8306_ACT_TRAPCPU, 
+ *          RTL8306_ACT_MIRROR
+ *      Acl protocol could be
+ *          RTL8306_ACL_ETHER(ether type), 
+ *          RTL8306_ACL_TCP(TCP), 
+ *          RTL8306_ACL_UDP(UDP),
+ *          RTL8306_ACL_TCPUDP(TCP or UDP)
+ *
+ *      Acl priority:
+ *          RTL8306_PRIO0~RTL8306_PRIO3
+ *       
+ */
+
+int32 rtl8306e_acl_entry_set(uint32 entryadd, uint32 phyport, uint32 action, uint32 protocol, uint32 data, uint32 priority) 
+{
+    uint32 regValue, value;
+    uint32 pollcnt  ;
+    uint32 bitValue;
+
+    if ((entryadd > RTL8306_ACL_ENTRYNUM - 1) || (phyport > RTL8306_ACL_ANYPORT) || 
+        (action > RTL8306_ACT_MIRROR) ||(protocol > RTL8306_ACL_TCPUDP) ||
+        (priority > RTL8306_PRIO3))
+        return FAILED;
+
+    /*Enable CPU port function, Enable inserting CPU TAG, Enable removing CPU TAG */
+    rtl8306e_reg_get(2, 21, 3, &regValue);
+    regValue = (regValue & 0x7FFF) | (1 << 11) | (1<<12);
+    rtl8306e_reg_set(2, 21, 3, regValue);
+    
+    /*set EtherType or TCP/UDP Ports, ACL entry access register 0*/
+    rtl8306e_reg_set(3, 21, 3, data);
+    
+    /*set ACL entry access register 1*/
+    rtl8306e_reg_get(3, 22, 3, &regValue);
+    value = (1 << 14) | (entryadd << 9)  | (priority << 7) | (action << 5) | (phyport << 2) | protocol ;
+    regValue = (regValue & 0x8000) | value  ;
+    rtl8306e_reg_set(3, 22, 3, regValue);
+    
+    /*Polling whether the command is done*/
+    for (pollcnt = 0; pollcnt < RTL8306_IDLE_TIMEOUT; pollcnt++) 
+    {
+        rtl8306e_regbit_get(3, 22, 14, 3, &bitValue);
+        if (!bitValue)
+            break;
+    }
+    if (pollcnt == RTL8306_IDLE_TIMEOUT)
+        return FAILED;
+
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.aclTbl[entryadd].phy_port = phyport;
+    rtl8306_TblBak.aclTbl[entryadd].action = action;
+    rtl8306_TblBak.aclTbl[entryadd].proto = protocol;
+    rtl8306_TblBak.aclTbl[entryadd].data = data;
+    rtl8306_TblBak.aclTbl[entryadd].pri = priority;
+#endif  
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_acl_entry_get
+ * Description:
+ *      Get Asic ACL entry
+ * Input:
+ *      entryadd   - Acl entry address (0~15)
+ * Output:
+ *      pPhyport    -  Acl physical port 
+ *      pAction      -  Acl action 
+ *      pProtocol   -  Acl protocol
+ *      pData        -  ether type value or TCP/UDP port
+ *      pPriority     -  Acl priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      phyport could be 
+ *            0~5:       port number, 
+ *            RTL8306_ACL_INVALID: invalid entry,
+ *            RTL8306_ACL_ANYPORT: any port.
+ *      Acl action could be
+ *          RTL8306_ACT_DROP,
+ *          RTL8306_ACT_PERMIT, 
+ *          RTL8306_ACT_TRAPCPU, 
+ *          RTL8306_ACT_MIRROR
+ *      Acl protocol could be
+ *          RTL8306_ACL_ETHER(ether type), 
+ *          RTL8306_ACL_TCP(TCP), 
+ *          RTL8306_ACL_UDP(UDP),
+ *          RTL8306_ACL_TCPUDP(TCP or UDP)
+ *
+ *      Acl priority:
+ *          RTL8306_PRIO0~RTL8306_PRIO3
+ *       
+ */
+int32 rtl8306e_acl_entry_get(uint32 entryadd, uint32 *pPhyport, uint32 *pAction, uint32 *pProtocol, uint32  *pData, uint32 *pPriority)
+{
+    uint32 regValue;
+    uint32 pollcnt  ;
+    uint32 bitValue;
+
+    if ((entryadd > RTL8306_ACL_ENTRYNUM - 1) || (NULL == pPhyport) || (NULL == pAction) || 
+        (NULL == pProtocol) || (NULL == pData) || (NULL == pPriority))
+        return FAILED;
+
+    /*trigger a command to read ACL entry*/
+    rtl8306e_reg_get(3, 22, 3, &regValue);
+    regValue = (regValue & 0x81FF) | (0x3 << 13) | (entryadd << 9);
+    rtl8306e_reg_set(3, 22, 3, regValue);
+    
+    /*Polling whether the command is done*/
+    for (pollcnt = 0; pollcnt < RTL8306_IDLE_TIMEOUT ; pollcnt++) 
+    {
+        rtl8306e_regbit_get(3, 22, 14, 3, &bitValue);
+        if (!bitValue)
+            break;
+    }
+    if (pollcnt == RTL8306_IDLE_TIMEOUT)
+        return FAILED;
+    
+    rtl8306e_reg_get(3, 21, 3, &regValue);
+    *pData = regValue;
+    rtl8306e_reg_get(3, 22, 3, &regValue);
+    *pPriority = (regValue  >> 7) & 0x3;
+    *pAction  = (regValue  >> 5) & 0x3;
+    *pPhyport = (regValue >> 2) & 0x7;
+    *pProtocol = regValue & 0x3;
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mib_get
+ * Description:
+ *      Get the MIB counter for the specified port
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ *      counter    -  Specify counter type  
+ * Output:
+ *      pValue -  the pointer of counter value 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are five MIB counter for each port, they are:
+ *      RTL8306_MIB_CNT1 - TX count
+ *      RTL8306_MIB_CNT2 - RX count
+ *      RTL8306_MIB_CNT3 - RX Drop Count<nl>
+ *      RTL8306_MIB_CNT4 - RX CRC error Count
+ *      RTL8306_MIB_CNT5 - RX Fragment Count<nl>
+ */
+int32 rtl8306e_mib_get(uint32 port, uint32 counter, uint32 *pValue) 
+{
+    uint32 regValue1, regValue2;
+
+    if ((port > RTL8306_PORT5) || (counter > RTL8306_MIB_CNT5) ||
+        (NULL == pValue))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    
+    switch(counter) 
+    {
+        case RTL8306_MIB_CNT1:            
+            /*Must read low 16 bit first, then hight 16 bit*/
+            rtl8306e_reg_get(port, 22, 2, &regValue1);
+            rtl8306e_reg_get(port, 23, 2, &regValue2);
+            *pValue = (regValue2 << 16) + regValue1;
+            break;
+            
+        case RTL8306_MIB_CNT2:
+            /*Must read low 16 bit first, then hight 16 bit*/
+            rtl8306e_reg_get(port, 24, 2, &regValue1);
+            rtl8306e_reg_get(port, 25, 2, &regValue2);
+            *pValue = (regValue2 << 16) + regValue1;
+            break;
+            
+        case RTL8306_MIB_CNT3:
+            /*Must read low 16 bit first, then hight 16 bit*/
+            rtl8306e_reg_get(port, 26, 2, &regValue1);
+            rtl8306e_reg_get(port, 27, 2, &regValue2);
+            *pValue = (regValue2 << 16) + regValue1;            
+            break;
+            
+        case RTL8306_MIB_CNT4:
+            /*Must read low 16 bit first, then hight 16 bit*/
+            rtl8306e_reg_get(port, 28, 2, &regValue1);
+            rtl8306e_reg_get(port, 29, 2, &regValue2);
+            *pValue = (regValue2 << 16) + regValue1;            
+            break;
+            
+        case RTL8306_MIB_CNT5:
+            /*Must read low 16 bit first, then hight 16 bit*/
+            rtl8306e_reg_get(port, 30, 2, &regValue1);
+            rtl8306e_reg_get(port, 31, 2, &regValue2);
+            *pValue = (regValue2 << 16) + regValue1;            
+            break;
+        default:
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_mibUnit_set
+ * Description:
+ *      Set RX/Tx Mib counting unit: byte or packet
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ *      counter    -  Specify counter type  
+ *      uint         -  Specify counting unit
+ * Output:
+ *      none  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.There are five MIB counter for each port, they are:
+ *      RTL8306_MIB_CNT1 - TX count
+ *      RTL8306_MIB_CNT2 - RX count
+ *      RTL8306_MIB_CNT3 - RX Drop Count<nl>
+ *      RTL8306_MIB_CNT4 - RX CRC error Count
+ *      RTL8306_MIB_CNT5 - RX Fragment Count<nl>
+ *      2.Only RTL8306_MIB_CNT1 and RTL8306_MIB_CNT2 could set counting unit  
+ *      RTL8306_MIB_PKT or RTL8306_MIB_BYTE, default is RTL8306_MIB_PKT.
+ *      the other counters' counting uint is RTL8306_MIB_PKT
+ */
+int32 rtl8306e_mibUnit_set(uint32 port, uint32 counter, uint32 unit) 
+{
+
+    if ((port > RTL8306_PORT5) ||(unit > RTL8306_MIB_PKT))
+        return FAILED;
+    /*Port 5 corresponding PHY6*/
+    if (port == RTL8306_PORT5 )  
+        port ++ ;  
+    switch(counter) 
+    {
+        case RTL8306_MIB_CNT1:
+            rtl8306e_regbit_set(port, 17, 3, 2, unit);
+            break;
+        case RTL8306_MIB_CNT2:
+            rtl8306e_regbit_set(port, 17, 4, 2, unit);
+            break;
+        default :
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mibUnit_get
+ * Description:
+ *      Get Rx/Tx Mib counting unit
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ *      counter    -  Specify counter type  
+ * Output:
+ *      pUnit         -  the pointer of counting unit
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.There are five MIB counter for each port, they are:
+ *      RTL8306_MIB_CNT1 - TX count
+ *      RTL8306_MIB_CNT2 - RX count
+ *      RTL8306_MIB_CNT3 - RX Drop Count<nl>
+ *      RTL8306_MIB_CNT4 - RX CRC error Count
+ *      RTL8306_MIB_CNT5 - RX Fragment Count<nl>
+ *      2.Only RTL8306_MIB_CNT1 and RTL8306_MIB_CNT2 could set counting unit  
+ *      RTL8306_MIB_PKT or RTL8306_MIB_BYTE, default is RTL8306_MIB_PKT.
+ *      the other counters' counting uint is RTL8306_MIB_PKT
+ */
+int32 rtl8306e_mibUnit_get(uint32 port, uint32 counter, uint32 *pUnit) 
+{ 
+    uint32 bitValue;
+    if ((port > RTL8306_PORT5) ||(pUnit == NULL))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (port == RTL8306_PORT5 )  
+        port ++ ;  
+    switch(counter) 
+    {
+        case RTL8306_MIB_CNT1:
+            rtl8306e_regbit_get(port, 17, 3, 2, &bitValue);
+            break;
+        case RTL8306_MIB_CNT2:
+            rtl8306e_regbit_get(port, 17, 4, 2, &bitValue);
+            break;
+        default:
+            return FAILED;
+    }
+    *pUnit = (bitValue ? RTL8306_MIB_PKT : RTL8306_MIB_BYTE);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mib_reset
+ * Description:
+ *      reset MIB counter
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+int32 rtl8306e_mib_reset(uint32 port) 
+{
+
+    if ((port > RTL8306_PORT5))
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+
+    /*stop counting and clear Mib counter to 0*/
+    rtl8306e_regbit_set(port, 17, 2, 2, 1);    
+    
+    /*Start counting*/
+    rtl8306e_regbit_set(port, 17, 2, 2, 0);    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mirror_portBased_set
+ * Description:
+ *      Set asic Mirror port
+ * Input:
+ *      mirport         -  Specify mirror port 
+ *      rxmbr           -  Specify Rx mirror port mask
+ *      txmbr           -  Specify Tx mirror port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      mirport could be 0 ~ 5, represent physical port number, 
+ *      7 means that no port has mirror ability. rxmbr and txmbr
+ *      is 6 bit value, each bit corresponds one port. ingress packet
+ *      of port in rxmbr will be mirrored to mirport, egress packet 
+ *      of port in txmbr will be mirrored to mirport.
+ */
+int32 rtl8306e_mirror_portBased_set(uint32 mirport, uint32 rxmbr, uint32 txmbr) 
+{
+    uint32 regValue;
+
+    if ((mirport > 7) ||(rxmbr > 0x3F) || (txmbr > 0x3F) )
+        return FAILED;
+
+    /*Set Mirror Port*/
+    rtl8306e_reg_get(2, 22, 3, &regValue);
+    regValue = (regValue & 0xC7FF) | (mirport << 11);
+    rtl8306e_reg_set(2, 22, 3, regValue);
+    
+    /*enable mirror port to filter the mirrored packet sent from itself */
+    rtl8306e_regbit_set(6, 21, 7, 3, 1);
+        
+    /*Set Ports Whose RX Data are Mirrored */
+    rtl8306e_reg_get(6, 21, 3, &regValue);
+    regValue = (regValue & 0xFFC0) | rxmbr ;
+    rtl8306e_reg_set(6, 21, 3, regValue);
+    
+    /*Set Ports Whose TX Data are Mirrored */
+    rtl8306e_reg_get(6, 21, 3, &regValue);
+    regValue = (regValue & 0xC0FF) | (txmbr << 8);
+    rtl8306e_reg_set(6, 21, 3, regValue);
+
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.mir.mirPort = (uint8)mirport;
+    rtl8306_TblBak.mir.mirRxPortMask = (uint8)rxmbr;
+    rtl8306_TblBak.mir.mirTxPortMask = (uint8)txmbr;
+#endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mirror_portBased_get
+ * Description:
+ *      Get asic Mirror port
+ * Input:
+ *      none 
+ * Output:
+ *      pMirport     -  the pointer of mirror port
+ *      pRxmbr       -  the pointer of  Rx mirror port mask
+ *      pTxmbr       -  the pointer of Tx mirror port mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      mirport could be 0 ~ 5, represent physical port number, 
+ *      7 means that no port has mirror ability. rxmbr and txmbr
+ *      is 6 bit value, each bit corresponds one port. ingress packet
+ *      of port in rxmbr will be mirrored to mirport, egress packet 
+ *      of port in txmbr will be mirrored to mirport.
+ */
+int32 rtl8306e_mirror_portBased_get(uint32 *pMirport, uint32 *pRxmbr, uint32* pTxmbr) 
+{
+    uint32 regValue;
+
+    if ((NULL == pMirport) ||(NULL == pRxmbr) || (NULL == pTxmbr)) 
+        return FAILED;
+
+    /*Get Mirror Port*/
+    rtl8306e_reg_get(2, 22, 3, &regValue);
+    *pMirport = (regValue & 0x3800) >> 11;
+    
+    /*Get Ports Whose RX Data are Mirrored*/
+    rtl8306e_reg_get(6, 21, 3, &regValue);
+    *pRxmbr = regValue & 0x3F;
+    
+    /*Get Ports Whose TX Data are Mirrored */
+    rtl8306e_reg_get(6, 21, 3, &regValue);
+    *pTxmbr = (regValue & 0x3F00) >> 8;
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mirror_macBased_set
+ * Description:
+ *      Set Mac address for mirror packet
+ * Input:
+ *      macAddr  - mirrored mac address, it could be SA or DA of the packet 
+ *      enabled   - enable mirror packet by mac address
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+int32 rtl8306e_mirror_macBased_set(uint8 *macAddr, uint32 enabled) 
+{
+
+    if (NULL == macAddr)
+        return FAILED;
+
+    if (!enabled) 
+    {
+        rtl8306e_regbit_set(6, 21, 14, 3, 0);
+#ifdef RTL8306_TBLBAK
+        rtl8306_TblBak.mir.enMirMac = (uint8)enabled;
+#endif
+    } 
+    else 
+    {
+        rtl8306e_regbit_set(6, 21, 14, 3, 1);
+        rtl8306e_reg_set(6, 22, 3, (macAddr[1] << 8) | macAddr[0]);
+        rtl8306e_reg_set(6, 23, 3, (macAddr[3] << 8) | macAddr[2]);
+        rtl8306e_reg_set(6, 24, 3, (macAddr[5] << 8) | macAddr[4]);
+#ifdef RTL8306_TBLBAK
+        rtl8306_TblBak.mir.enMirMac = (uint8)enabled;
+        rtl8306_TblBak.mir.mir_mac[0] = macAddr[0];
+        rtl8306_TblBak.mir.mir_mac[1] = macAddr[1];
+        rtl8306_TblBak.mir.mir_mac[2] = macAddr[2];
+        rtl8306_TblBak.mir.mir_mac[3] = macAddr[3];
+        rtl8306_TblBak.mir.mir_mac[4] = macAddr[4];
+        rtl8306_TblBak.mir.mir_mac[5] = macAddr[5];   
+#endif
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_mirror_macBased_set
+ * Description:
+ *      Set Mac address for mirror packet
+ * Input:
+ *      none 
+ * Output:
+ *      macAddr   - mirrored mac address, it could be SA or DA of the packet 
+ *      pEnabled   - the pointer of enable mirror packet by mac address 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ * 
+ */
+int32 rtl8306e_mirror_macBased_get(uint8 *macAddr, uint32 *pEnabled) 
+{
+    uint32 regValue;
+    uint32 bitValue;
+
+    if (NULL == macAddr)
+        return FAILED;
+    
+    rtl8306e_regbit_get(6, 21, 14, 3, &bitValue);
+    *pEnabled = (bitValue  ? TRUE : FALSE);
+    rtl8306e_reg_get(6, 22, 3, &regValue);
+    macAddr[0] = regValue & 0xFF;
+    macAddr[1] = (regValue & 0xFF00) >> 8;
+    rtl8306e_reg_get(6, 23, 3, &regValue);
+    macAddr[2] = regValue & 0xFF;
+    macAddr[3] = (regValue & 0xFF00) >> 8;
+    rtl8306e_reg_get(6, 24, 3, &regValue);
+    macAddr[4] = regValue & 0xFF;
+    macAddr[5] = (regValue & 0xFF00) >> 8;
+    return SUCCESS;
+    
+}
+
+
+/* Function Name:
+ *      rtl8306e_l2_MacToIdx_get
+ * Description:
+ *      get L2 table hash value from mac address
+ * Input:
+ *      macAddr        -  mac address
+ * Output:
+ *      pIndex           -  mac address table index   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      when a mac address is learned into mac address table, 
+ *      9 bit index value is got from the mac address by hashing 
+ *      algorithm, each index corresponds to 4 entry, it means
+ *      the table could save 4 mac addresses at the same time
+ *      whose index value is equal, so switch mac address table 
+ *      has 2048 entry. the API could get hash index from 
+ *      a specified mac address.
+ */
+int32 rtl8306e_l2_MacToIdx_get(uint8 *macAddr, uint32* pIndex)
+{
+    uint32 tmp_index;
+    uint32 status;
+
+    if ((NULL == macAddr) || (NULL == pIndex))
+        return FAILED;
+
+
+    rtl8306e_regbit_get(1, 23, 12, 0, &status);    
+    *pIndex = 0;
+    
+    if (status) 
+    {  
+        /* xor hash algorithm*/
+        
+        /* Index 0 = 4 ^ 11 ^ 18 ^ 25 ^ 32 */
+        *pIndex |= ((macAddr[5] & 0x8) >> 3) ^ ((macAddr[4] & 0x10) >> 4) ^ ((macAddr[3] & 0x20) >> 5) ^ ((macAddr[2] & 0x40) >> 6) ^  ((macAddr[1] & 0x80) >> 7); 
+
+        /* Index_1 = 3 ^ 10 ^ 17 ^ 24 ^ 47 */
+        tmp_index = ((macAddr[5] & 0x10) >> 4) ^ ((macAddr[4] & 0x20) >> 5) ^ ((macAddr[3] & 0x40) >> 6) ^ ((macAddr[2] & 0x80) >> 7) ^ ((macAddr[0] & 0x1) >> 0);
+        *pIndex |= tmp_index << 1;
+
+        /* Index_2 = 2 ^ 9 ^ 16 ^ 39 ^ 46 */
+        tmp_index = ((macAddr[5] & 0x20) >> 5) ^ ((macAddr[4] & 0x40) >> 6) ^ ((macAddr[3] & 0x80) >> 7) ^ ((macAddr[1] & 0x1) >> 0) ^ ((macAddr[0] & 0x2) >> 1);
+        *pIndex |= tmp_index << 2;
+
+        /* Index_3 = 1 ^ 8 ^ 31 ^ 38 ^ 45 */
+        tmp_index = ((macAddr[5] & 0x40) >> 6) ^ ((macAddr[4] & 0x80) >> 7) ^ ((macAddr[2] & 0x1) >> 0) ^ ((macAddr[1] & 0x2) >> 1) ^ ((macAddr[0] & 0x4) >> 2);
+        *pIndex |= tmp_index << 3;
+
+        /* Index_4 = 0 ^ 23 ^ 30 ^ 37 ^ 44 */
+        tmp_index = ((macAddr[5] & 0x80) >> 7) ^ ((macAddr[3] & 0x1) >> 0) ^ ((macAddr[2] & 0x2) >> 1) ^ ((macAddr[1] & 0x4) >> 2) ^ ((macAddr[0] & 0x8) >> 3);
+        *pIndex |= tmp_index << 4;
+
+        /* Index_5 = 15 ^ 22 ^ 29 ^ 36 ^ 43 */
+        tmp_index = ((macAddr[4] & 0x1) >> 0) ^ ((macAddr[3] & 0x2) >> 1) ^ ((macAddr[2] & 0x4) >> 2) ^ ((macAddr[1] & 0x8) >> 3) ^ ((macAddr[0] & 0x10) >> 4);
+        *pIndex |= tmp_index << 5;
+
+        /* Index_6 = 7 ^  14 ^ 21 ^ 28 ^ 35 ^ 42 */
+        tmp_index = ((macAddr[5] & 0x1) >> 0) ^ ((macAddr[4] & 0x2) >> 1) ^ ((macAddr[3] & 0x4) >> 2) ^ ((macAddr[2] & 0x8) >> 3) ^ ((macAddr[1] & 0x10) >> 4) ^ ((macAddr[0] & 0x20) >> 5);
+        *pIndex |= tmp_index << 6;
+
+        /* Index_7 = 6 ^ 13 ^ 20 ^ 27 ^ 34 ^ 41 */
+        tmp_index = ((macAddr[5] & 0x2) >> 1) ^ ((macAddr[4] & 0x4) >> 2) ^ ((macAddr[3] & 0x8) >> 3) ^ ((macAddr[2] & 0x10) >> 4) ^ ((macAddr[1] & 0x20) >> 5) ^ ((macAddr[0] & 0x40) >> 6);
+        *pIndex |= tmp_index << 7;
+
+        /* Index_8 = 5 ^ 12 ^ 19 ^ 26 ^ 33 ^ 40 */
+        tmp_index = ((macAddr[5] & 0x4) >> 2) ^ ((macAddr[4] & 0x8) >> 3) ^ ((macAddr[3] & 0x10) >> 4) ^ ((macAddr[2] & 0x20) >> 5) ^ ((macAddr[1] & 0x40) >> 6)  ^ ((macAddr[0] & 0x80) >> 7);
+        *pIndex |= tmp_index << 8;
+    }
+    else  
+    {
+        /*index direct from mac: LUT index MAC[13:15] + MAC[0:5]*/
+        *pIndex = ((macAddr[4] & 0x7) << 6) | ((macAddr[5] & 0xFC) >> 2);
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_IdxToMac_get
+ * Description:
+ *      get Mac address for hash index
+ * Input:
+ *      pIndex        -  the pointer of address table index
+ * Output:
+ *      macAddr     -   the mac address   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *   
+ */ 
+static int32 rtl8306e_l2_IdxToMac_get(uint8 *macAddr, uint32* pIndex)
+{
+    uint32 tmp_index, regValue, status;
+
+    if ((NULL == macAddr) || (NULL == pIndex))
+        return FAILED;
+
+    rtl8306e_regbit_get(1, 23, 12, 0, &status);
+    
+    if (status) 
+    {
+        /* xor hash algorithm*/
+
+        /*Read Data[47:32]*/
+        rtl8306e_reg_get(4, 18, 0, &regValue);
+        macAddr[5] = (regValue & 0x300) >> 8; 
+        macAddr[4] = regValue & 0xF8;            
+  
+        /*Read Data[31:16]*/
+        rtl8306e_reg_get(4, 19, 0, &regValue);
+        macAddr[3] = (regValue & 0xFF00) >> 8; 
+        macAddr[2] = regValue & 0xFF;
+
+        /*Read Data[15:0]*/
+        rtl8306e_reg_get(4, 20, 0, &regValue);
+        macAddr[1] = (regValue & 0xFF00) >> 8;
+        macAddr[0] = regValue & 0xFF;
+
+        /* bit 4 =  Index_0 ^ 11 ^ 18 ^ 25 ^ 32; */
+        tmp_index = ((*pIndex & 0x4) >> 2) ^ ((macAddr[4] & 0x10) >> 4) ^ ((macAddr[3] & 0x20) >> 5) ^ ((macAddr[2] & 0x40) >> 6) ^  ((macAddr[1] & 0x80) >> 7); 
+        macAddr[5] |= (uint8)(tmp_index << 3);
+        /* bit 3 =  Index_1 ^ 10 ^ 17 ^ 24 ^ 47 */
+        tmp_index = ((*pIndex & 0x8) >> 3) ^ ((macAddr[4] & 0x20) >> 5) ^ ((macAddr[3] & 0x40) >> 6) ^ ((macAddr[2] & 0x80) >> 7) ^ ((macAddr[0] & 0x1) >> 0);
+        macAddr[5] |= (uint8)(tmp_index << 4);
+        /* bit 2 =  Index_2 ^ 9 ^ 16 ^ 39 ^ 46 */
+        tmp_index = ((*pIndex & 0x10) >> 4) ^ ((macAddr[4] & 0x40) >> 6) ^ ((macAddr[3] & 0x80) >> 7) ^ ((macAddr[1] & 0x1) >> 0) ^ ((macAddr[0] & 0x2) >> 1);
+        macAddr[5] |= (uint8)(tmp_index << 5);
+
+        /* bit 1 = Index_3 ^ 8 ^ 31 ^ 38 ^ 45 */
+        tmp_index = ((*pIndex & 0x20) >> 5) ^ ((macAddr[4] & 0x80) >> 7)  ^ ((macAddr[2] & 0x1) >> 0) ^ ((macAddr[1] & 0x2) >> 1) ^ ((macAddr[0] & 0x4) >> 2);
+        macAddr[5] |= (uint8)(tmp_index << 6);
+
+        /* bit 0 = Index_4 ^ 23 ^ 30 ^ 37 ^ 44 */
+        tmp_index = ((*pIndex & 0x40) >> 6) ^ ((macAddr[3] & 0x1) >> 0)  ^ ((macAddr[2] & 0x2) >> 1) ^ ((macAddr[1] & 0x4) >> 2) ^ ((macAddr[0] & 0x8) >> 3);
+        macAddr[5] |= (uint8)(tmp_index << 7);
+
+        /* bit 15 = Index_5 ^ 22 ^ 29 ^ 36 ^ 43 */
+        tmp_index = ((*pIndex & 0x80) >> 7) ^ ((macAddr[3] & 0x2) >> 1) ^ ((macAddr[2] & 0x4) >> 2) ^ ((macAddr[1] & 0x8) >> 3) ^ ((macAddr[0] & 0x10) >> 4);
+        macAddr[4] |= (uint8)(tmp_index << 0);
+        
+        /* bit 14 =  Index_6 ^ 7 ^ 21 ^ 28 ^ 35 ^ 42 */
+        tmp_index = ((*pIndex & 0x100) >> 8) ^ ((macAddr[5] & 0x1) >> 0) ^ ((macAddr[3] & 0x4) >> 2) ^ ((macAddr[2] & 0x8) >> 3) ^ ((macAddr[1] & 0x10) >> 4) ^ ((macAddr[0] & 0x20) >> 5);
+        macAddr[4] |= (uint8)(tmp_index << 1);
+
+        /* bit 13 =  Index_7 ^ 6 ^ 20 ^ 27 ^ 34 ^ 41 */
+        tmp_index = ((*pIndex & 0x200) >> 9) ^ ((macAddr[5] & 0x2) >> 1) ^ ((macAddr[3] & 0x8) >> 3) ^ ((macAddr[2] & 0x10) >> 4) ^ ((macAddr[1] & 0x20) >> 5) ^ ((macAddr[0] & 0x40) >> 6);
+        macAddr[4] |= (uint8)(tmp_index << 2);
+        
+        /* bit 5 =  Index_8 ^ 12 ^ 19 ^ 26 ^ 33 ^ 40 */
+        tmp_index = ((*pIndex & 0x400) >> 10) ^ ((macAddr[4] & 0x8) >> 3) ^ ((macAddr[3] & 0x10) >> 4) ^ ((macAddr[2] & 0x20) >> 5) ^ ((macAddr[1] & 0x40) >> 6)  ^ ((macAddr[0] & 0x80) >> 7);
+        macAddr[5] |= (uint8)(tmp_index << 2);
+ 
+    }
+    else  
+    {
+        /*Read Data[47:32]*/
+      rtl8306e_reg_get(4, 18, 0, &regValue);
+      macAddr[5] = ((regValue & 0x300) >> 8) | (*pIndex & 0xFC);
+      macAddr[4] = (regValue & 0xF8) | ((*pIndex >> 8) & 0x7);
+
+      /*Read Data[31:16]*/
+      rtl8306e_reg_get(4, 19, 0, &regValue);
+      macAddr[3] = (regValue & 0xFF00) >> 8;
+      macAddr[2] = regValue & 0xFF;
+
+      /*Read Data[15:0]*/
+      rtl8306e_reg_get(4, 20, 0, &regValue);
+      macAddr[1] = (regValue & 0xFF00) >> 8;
+      macAddr[0] = regValue & 0xFF;
+    }
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_unicastEntry_set
+ * Description:
+ *      write an unicast mac address into L2 table
+ * Input:
+ *      macAddress        -  Specify the unicast Mac address(6 bytes) to be written into LUT
+ *      entry                 -  Specify the 4-way entry to be written (0~3)
+ *      age                   -  Specify age time
+ *      isStatic              -  TRUE(static entry), FALSE(dynamic entry)
+ *      isAuth                -  Whether the mac address is authorized by IEEE 802.1x
+ *      port                  -   Specify the port number to be forwarded to  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :
+ *          RTL8306_LUT_AGEOUT, 
+ *          RTL8306_LUT_AGE100(100s)
+ *          RTL8306_LUT_AGE200(200s)
+ *          RTL8306_LUT_AGE300(300s)
+ */ 
+
+int32 rtl8306e_l2_unicastEntry_set(uint8 *macAddress, uint32 entry, uint32 age, uint32 isStatic, uint32 isAuth, uint32 port) 
+{
+    uint32 regValue, index, pollcnt;
+    uint32 bitValue;
+
+    if ((NULL == macAddress) || (entry > RTL8306_LUT_ENTRY3) || (age > RTL8306_LUT_AGE300) ||
+        (port > RTL8306_PORT5))
+        return FAILED;
+
+    /*For unicast entry, MAC[47] is 0  */
+    if (macAddress[0] & 0x1)
+        return FAILED;
+    
+    /*Enable lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 1);
+    
+    /*Write Data[55:48]*/
+    if (RTL8306_LUT_AGE300 == age) 
+        age = 0x2;
+    else if (RTL8306_LUT_AGE200 == age)
+        age = 0x3;
+    else if (RTL8306_LUT_AGE100 == age)
+        age = 0x1;
+    else 
+        age = 0;
+
+    regValue = ((isAuth ? 1:0 ) << 7) | ((isStatic ? 1:0) << 6) | (age << 4) | port;
+    rtl8306e_reg_set(4, 17, 0, regValue & 0xFF);
+    /*write Data[47:32]*/
+    rtl8306e_reg_set(4, 18, 0, macAddress[5] << 8 | macAddress[4]);
+    /*wrtie Data[31:16]*/
+    rtl8306e_reg_set(4, 19, 0, macAddress[3] << 8 | macAddress[2]);
+    /*wrtie Data[15:0]*/
+    rtl8306e_reg_set(4, 20, 0, macAddress[1] << 8 | macAddress[0]);
+
+    /*LUT index */
+    rtl8306e_l2_MacToIdx_get(macAddress, &index);
+
+    /*Write Command, 2-bit indicating four-way lies in highest bit of Entry_Addr[10:0]*/
+    regValue = (entry << 13) | (index << 4) | 0x0;
+    rtl8306e_reg_set(4, 16, 0, regValue);
+    rtl8306e_regbit_set(4, 16, 1, 0, 1);
+    
+    /*Waiting for write command done and prevent polling dead loop*/
+    for (pollcnt = 0; pollcnt < RTL8306_IDLE_TIMEOUT; pollcnt ++) 
+    {
+        rtl8306e_regbit_get(4, 16, 1, 0, &bitValue);
+        if (!bitValue)
+            break;
+    }
+    if (pollcnt == RTL8306_IDLE_TIMEOUT)
+        return FAILED;
+
+    /*Disable lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 0);
+ #ifdef RTL8306_LUT_CACHE
+     memcpy(rtl8306_LutCache[ (index << 2) | entry].mac, macAddress, 6);
+     rtl8306_LutCache[ (index << 2) | entry].un.unicast.auth = isAuth;
+     rtl8306_LutCache[ (index << 2) | entry].un.unicast.spa= port;
+     rtl8306_LutCache[ (index << 2) | entry].un.unicast.isStatic= isStatic;
+     rtl8306_LutCache[ (index << 2) | entry].un.unicast.age= age;
+ #endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_unicastEntry_get
+ * Description:
+ *      read an unicast mac address into L2 table
+ * Input:
+ *      entry               -  Specify the entry address to be read (0 ~ 2047), not four-way entry
+ * Output:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      pAge               -  the pointer of the age time
+ *      pIsStatic         -   the pointer of static or dynamic entry
+ *      pIsAuth           -   the pointer of IEEE 802.1x authorized status
+ *      pPort              -   the pointer of the port the mac belongs to   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :
+ *          RTL8306_LUT_AGEOUT
+ *          RTL8306_LUT_AGE100(100s)
+ *          RTL8306_LUT_AGE200(200s)
+ *          RTL8306_LUT_AGE300(300s)
+ */ 
+ 
+int32 rtl8306e_l2_unicastEntry_get(uint8 *macAddress, uint32 entryAddr, uint32 *pAge, uint32 *pIsStatic, uint32 *pIsAuth, uint32 *pPort) 
+{
+    uint32 entryAddrHd;
+    uint32 regValue, pollcnt;
+    uint32 bitValue;
+
+    if ((NULL == macAddress) || (entryAddr > 0x7FF) || (NULL == pAge) || (NULL == pIsStatic) ||
+        (pIsAuth == NULL) || (pPort == NULL))
+        return FAILED;
+    
+    /*Hardware data format, four-way info is the highest 2 bits of 11-bit entry info*/
+    entryAddrHd = (entryAddr >> 2) | ((entryAddr & 0x3) << 9);
+    
+    /*Enable lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 1);
+    /*Read Command*/
+    regValue = (entryAddrHd << 4) | 0x1;
+    rtl8306e_reg_set(4, 16, 0, regValue);
+    rtl8306e_regbit_set(4, 16, 1, 0, 1);
+    
+    /*Waiting for Read command done and prevent polling dead loop*/
+    for (pollcnt = 0; pollcnt < RTL8306_IDLE_TIMEOUT; pollcnt ++) 
+    {
+        rtl8306e_regbit_get(4, 16, 1, 0, &bitValue);
+        if (!bitValue)
+            break;
+    }
+    if (pollcnt == RTL8306_IDLE_TIMEOUT)
+        return FAILED;
+    
+    /*Read Data[55:48]*/
+    rtl8306e_reg_get(4, 17, 0, &regValue);
+    *pIsAuth = (regValue & 0x80) ? TRUE: FALSE;
+    *pIsStatic = (regValue & 0x40) ? TRUE:FALSE;
+    *pAge = (regValue & 0x30) >> 4;
+    if (*pAge == 0x2) 
+        *pAge = RTL8306_LUT_AGE300;
+    else if (*pAge == 0x3)
+        *pAge = RTL8306_LUT_AGE200;
+    else if (*pAge == 0x1 )
+        *pAge = RTL8306_LUT_AGE100;
+    else 
+        *pAge = RTL8306_LUT_AGEOUT;
+    *pPort = regValue & 0x7;
+
+    rtl8306e_l2_IdxToMac_get(macAddress, &entryAddr);
+
+    /*Disable lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 0);
+    return SUCCESS;
+}
+
+#ifdef RTL8306_LUT_CACHE
+ 
+int32 rtl8306e_fastGetAsicLUTUnicastEntry(uint8 *macAddress, uint32 entryAddr, uint32 *pAge, uint32 *pIsStatic, uint32 *pIsAuth, uint32 *pPort) 
+{    
+    if ((NULL == macAddress) || (entryAddr > 0x7FF) || (NULL == pAge) || (NULL == pIsStatic ) ||
+        (NULL == pIsAuth) || (NULL == pPort))
+        return FAILED;
+
+    memcpy(macAddress, rtl8306_LutCache[entryAddr].mac, 6);
+
+    *pIsStatic= rtl8306_LutCache[entryAddr].un.unicast.isStatic;
+    *pIsAuth = rtl8306_LutCache[entryAddr].un.unicast.auth;
+    *pPort   = rtl8306_LutCache[entryAddr].un.unicast.spa;
+    *pAge     = rtl8306_LutCache[entryAddr].un.unicast.age;
+
+    return SUCCESS;
+}
+
+int32 rtl8306e_fastGetAsicLUTMulticastEntry(uint8 *macAddress, uint32 entryAddr, uint32 *pIsAuth, uint32 *pPortMask) 
+{
+    
+    if ((NULL == macAddress) || (entryAddr > 0x7FF) ||(NULL == pIsAuth) || (NULL == pPortMask))
+        return FAILED;      
+    memcpy(macAddress, rtl8306_LutCache[entryAddr].mac, 6);
+
+    *pIsAuth = rtl8306_LutCache[entryAddr].un.multicast.auth;
+    *pPortMask = rtl8306_LutCache[entryAddr].un.multicast.portMask;
+
+    return SUCCESS;   
+}
+
+#endif
+/* Function Name:
+ *      rtl8306e_l2_multicastEntry_set
+ * Description:
+ *      write an multicast mac address into L2 table
+ * Input:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      entry               -  Specify the 4-way entry to be written (0~3)
+ *      isAuth              -  IEEE 802.1x authorized status
+ *      portMask          -  switch received thepacket with the specified macAddress, 
+ *                                and forward it to the member port of portMask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      get 9-bit as index value of lookup table by hashing the mac address , for each index value, 
+ *      there are 4-entry to save hash collision mac address, thus there are 2048 entries all together.
+ *      the entry could save both unicast multicast mac address.  multicast entry has no age time and
+ *      static bit, which has been set by software, unicast entry could be both auto learned and set by 
+ *      software. you had better set isAuth TRUE for general application because  IEEE 802.1x is usually
+ *      for unicast packet.portMask is 6-bit value, each bit represents one port, bit 0 corresponds to port 0
+ *      and bit 5 corresponds port 5.
+ */ 
+
+int32 rtl8306e_l2_multicastEntry_set(uint8 *macAddress, uint32 entry, uint32 isAuth, uint32 portMask) 
+{
+    uint32 regValue, index, pollcnt;
+    uint32 bitValue;
+
+    if ((NULL == macAddress) || (entry > RTL8306_LUT_ENTRY3) || (portMask > 0x3F ))
+        return FAILED;
+
+    /*For Muticast entry, MAC[47] is 1  */
+    if (!(macAddress[0] & 0x1))
+        return FAILED;
+    
+    /*Enalbe Lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 1);
+    
+    /*Write Data[55:48]*/
+    /*Multicast entry portmask bits is Data[54:52], Data[50:48]*/
+    regValue = ((isAuth ? 1: 0) << 7) | (portMask & 0x38) << 1 | (portMask & 0x7); 
+    rtl8306e_reg_set(4, 17, 0, regValue);
+    /*Write Data[47:32]*/
+    rtl8306e_reg_set(4, 18, 0, (macAddress[5] << 8) |macAddress[4]);
+    /*Write Data[31:16]*/
+    rtl8306e_reg_set(4, 19, 0, (macAddress[3] << 8) |macAddress[2]);
+    /*Write Data[15:0]*/
+    rtl8306e_reg_set(4, 20, 0, (macAddress[1] << 8) |macAddress[0]);
+
+    /*LUT index */
+    rtl8306e_l2_MacToIdx_get(macAddress, &index);
+
+    /*Write Command, 2-bit indicating four-way lies in highest bit of Entry_Addr[10:0]*/
+    regValue = (entry << 13) | (index << 4) | 0x2;
+    rtl8306e_reg_set(4, 16, 0, regValue);
+    
+    /*Waiting for write command done and prevent polling dead loop*/
+    for (pollcnt = 0; pollcnt < RTL8306_IDLE_TIMEOUT; pollcnt ++)
+    {
+        rtl8306e_regbit_get(4, 16, 1, 0, &bitValue);
+        if (!bitValue)
+          break;
+    }
+    
+    if (pollcnt == RTL8306_IDLE_TIMEOUT)
+        return FAILED;
+    
+    /*Disable Lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 0);
+    /*record it in software cache if define RTL8306_LUT_CACHE*/
+ #ifdef RTL8306_LUT_CACHE
+     memcpy(rtl8306_LutCache[ (index << 2) | entry].mac, macAddress, 6);
+     rtl8306_LutCache[ (index << 2) | entry].un.multicast.auth = isAuth;
+     rtl8306_LutCache[ (index << 2) | entry].un.multicast.portMask= portMask;
+ #endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306_getAsicLUTMulticastEntry
+ * Description:
+ *      Get LUT multicast entry
+ * Input:
+ *      entryAddr         -  Specify the LUT entry address(0~2047)
+
+ * Output:
+ *      macAddress      -  The read out multicast Mac address  
+ *      pIsAuth            -  the pointer of IEEE 802.1x authorized status
+ *      portMask          -  port mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Get multicast entry
+ */ 
+
+int32 rtl8306e_l2_multicastEntry_get(uint8 *macAddress, uint32 entryAddr, uint32 *pIsAuth, uint32 *pPortMask) 
+{
+    uint32 entryAddrHd;
+    uint32 regValue, pollcnt;
+    uint32 bitValue;
+
+    if ((NULL == macAddress) || (entryAddr > 0x7FF) ||(NULL == pIsAuth) || (NULL == pPortMask))
+        return FAILED;
+
+    /*Hardware data format, four-way info is the highest 2 bits of 11-bit entry info*/
+    entryAddrHd = (entryAddr >> 2) | ((entryAddr & 0x3) << 9);
+    
+    /*Enalbe Lookup table access*/
+    rtl8306e_regbit_set(0, 16, 13, 0, 1);
+    
+    /*Write Command*/
+    regValue = (entryAddrHd << 4) | 0x3;
+    rtl8306e_reg_set(4, 16, 0, regValue);
+    
+    /*Waiting for Read command done and prevent polling dead loop*/
+    for (pollcnt = 0; pollcnt < RTL8306_IDLE_TIMEOUT; pollcnt ++) 
+    {
+        rtl8306e_regbit_get(4, 16, 1, 0, &bitValue);
+        if (!bitValue)
+            break;
+    }
+    if (pollcnt == RTL8306_IDLE_TIMEOUT)
+        return FAILED;
+    
+    /*Read Data[55:48]*/
+    rtl8306e_reg_get(4, 17, 0, &regValue);
+    *pIsAuth = (regValue & 0x80 ? 1:0);
+    
+    /*Multicast entry portmask bits is Data[54:52], Data[50:48]*/
+    *pPortMask = ((regValue & 0x70) >> 4) << 3 | (regValue & 0x7);
+
+    rtl8306e_l2_IdxToMac_get(macAddress, &entryAddr);
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_unicastMac_add
+ * Description:
+ *     Add an unicast mac address, software will detect empty entry
+ * Input:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      age                 -  Specify age time
+ *      isStatic            -  TRUE(static entry), FALSE(dynamic entry)
+ *      isAuth              -  IEEE 802.1x authorized status
+ *      port                 -  the port which the mac address belongs to  
+ * Output:
+ *      pEntryaddr        -   the entry address (0 ~2047) which the unicast mac address is written into
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :RTL8306_LUT_AGEOUT, RTL8306_LUT_AGE100(100s), 
+ *      RTL8306_LUT_AGE200(200s), RTL8306_LUT_AGE300(300s)
+ *      The lut has a 4-way entry of an index. If the macAddress has existed in the lut, it will update the entry,
+ *      otherwise the function will find an empty entry to put it.
+ *      When the index is full, it will find a dynamic & unauth unicast macAddress entry to replace with it. 
+ *      If the mac address has been written into LUT, function return value is SUCCESS,  *pEntryaddr is recorded the 
+ *      entry address of the Mac address stored.
+ *      If all the four entries can not be replaced, it will return a  RTL8306_LUT_FULL error, you can delete one of them 
+ *      and rewrite the unicast address.  
+ */ 
+
+int32 rtl8306e_l2_unicastMac_add(uint8 *macAddress, uint32 age, uint32 isStatic, uint32 isAuth, uint32 port, uint32 *pEntryaddr)
+{
+    int32 i;
+    uint8 macAddr[6];
+    uint32 index,entryaddr;
+    uint32 isStatic1,isAuth1,age1,port1;
+
+    /*check for macAddress. must be unicast address*/
+    if( (NULL == macAddress) || (macAddress[0] & 0x1))
+        return FAILED;
+
+    /*check port*/
+    if (port > 5)
+        return FAILED;
+
+    rtl8306e_l2_MacToIdx_get(macAddress, &index);
+
+    /*
+      *First scan four-ways, if the unicast entry has existed, only update the entry, that could 
+      *prevent two same Mac in four-ways; if the mac was not written into entry before, then scan 
+      *four-ways again, to Find an dynamic & unauthorized unicast entry which is auto learned, then  
+      *replace it with the multicast Mac addr. scanning sequence is from entry 3 to entry 0, because 
+      *priority of four way is entry 3 > entry 2 > entry 1 > entry 0
+      */
+    for (i = 3; i >= 0; i--) 
+    {
+        entryaddr = (index << 2) | (uint32)i;
+        if (rtl8306e_l2_unicastEntry_get(macAddr, entryaddr, &age1, &isStatic1, &isAuth1, &port1) != SUCCESS) 
+        {
+            return FAILED;
+        }
+        else if ((macAddress[0] == macAddr[0]) && (macAddress[1] == macAddr[1]) && 
+                   (macAddress[2] == macAddr[2]) && (macAddress[3] == macAddr[3]) &&
+                    (macAddress[4] == macAddr[4]) && (macAddress[5] == macAddr[5])) 
+        {
+            rtl8306e_l2_unicastEntry_set(macAddress, (uint32)i , age, isStatic, isAuth, port);
+            *pEntryaddr = entryaddr;
+            return SUCCESS;
+        }
+    }
+    
+    for (i = 3; i >= 0; i--) 
+    {
+        entryaddr = (index << 2) | (uint32)i ;
+        if (rtl8306e_l2_unicastEntry_get(macAddr, entryaddr, &age1, &isStatic1, &isAuth1, &port1) != SUCCESS) 
+        {
+            return FAILED;
+        }
+        else if (((macAddr[0] & 0x1) == 0) && (!isStatic1) && (!isAuth1))  
+        {
+            rtl8306e_l2_unicastEntry_set(macAddress, (uint32)i , age, isStatic, isAuth, port);
+            *pEntryaddr = entryaddr;
+            return SUCCESS;
+        }
+    }
+
+    /* four way are all full, return RTL8306_LUT_FULL*/
+    return RTL8306_LUT_FULL;
+}
+
+
+/* Function Name:
+ *      rtl8306e_l2_multicastMac_add
+ * Description:
+ *     Add an multicast mac address, software will detect empty entry
+ * Input:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      isAuth              -  IEEE 802.1x authorized status
+ *      portMask          -  switch received the packet with the specified macAddress, 
+ *                                and forward it to the member port of portMask
+ * Output:
+ *      pEntryaddr        -   the entry address (0 ~2047) which the multicast mac address is written into
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Add an multicast entry, it need not specify the 4-way like function rtl8306e_l2_multicastEntry_set,
+ *      if the mac address has written into LUT, function return value is SUCCESS,  *pEntryaddr is recorded the 
+ *      entry address of the Mac address stored, if  4-way entries are all written by cpu, this mac address could 
+ *      not written into LUT and the function return value is  RTL8306_LUT_FULL, but if the Mac address has exist, 
+ *      the port mask will be updated. When function return value is RTL8306_LUT_FULL, you can delete one of them 
+ *      and rewrite the multicast address. 
+ */ 
+int32  rtl8306e_l2_multicastMac_add(uint8 *macAddr,uint32 isAuth, uint32 portMask, uint32 *pEntryaddr) 
+{
+    int32  i;
+    uint8 macAddress[4][6];
+    uint32 index, entryAddress[4], age[4];
+    uint32 isStatic[4], isAuthority[4];
+    uint32 port[4];
+    uint32 isFull = TRUE;
+
+
+    if ((NULL == macAddr) || (!(macAddr[0] & 0x1)) || (NULL == pEntryaddr))
+        return FAILED;
+
+    rtl8306e_l2_MacToIdx_get(macAddr, &index);
+
+    /*
+      *First scan four-ways, if the multicast entry has existed, only update the entry, that could 
+      *prevent two same Mac in four-ways; if the mac was not written into entry before, then scan 
+      *four-ways again, to Find an dynamic & unauthorized unicast entry which is auto learned, then  
+      *replace it with the multicast Mac addr. scanning sequence is from entry 3 to entry 0, because priority
+      *of four way is entry 3 > entry 2 > entry 1 > entry 0
+      */
+    for (i = 3; i >= 0; i--) 
+    {
+        entryAddress[i] = (index << 2) | (uint32)i;
+#ifdef RTL8306_LUT_CACHE
+        if (rtl8306e_fastGetAsicLUTUnicastEntry(macAddress[i], entryAddress[i], &age[i], &isStatic[i], &isAuthority[i], &port[i]) != SUCCESS)
+#else
+        if (rtl8306e_l2_unicastEntry_get(macAddress[i], entryAddress[i], &age[i], &isStatic[i], &isAuthority[i], &port[i]) != SUCCESS) 
+#endif
+        {
+            return FAILED;
+        }
+        else if ((macAddr[0] == macAddress[i][0]) && (macAddr[1] == macAddress[i][1]) && 
+                    (macAddr[2] == macAddress[i][2]) && (macAddr[3] == macAddress[i][3]) &&
+                    (macAddr[4] == macAddress[i][4]) && (macAddr[5] == macAddress[i][5])) 
+        {
+            rtl8306e_l2_multicastEntry_set(macAddr, (uint32)i, isAuth, portMask);
+            *pEntryaddr = entryAddress[i];
+            isFull = FALSE;
+            return SUCCESS;
+        }
+    }
+    
+    for (i = 3; i >= 0; i--) 
+    {
+        if (((macAddress[i][0] & 0x1) == 0) && (!isStatic[i]) && (!isAuthority[i])) 
+        {
+            rtl8306e_l2_multicastEntry_set(macAddr, (uint32)i , isAuth, portMask);
+            *pEntryaddr = entryAddress[i];
+            isFull = FALSE;
+            break;
+        }
+    }
+
+    /*If four way are all full, return RTL8306_LUT_FULL*/
+    if (isFull) 
+    {
+        *pEntryaddr = 10000;
+        return RTL8306_LUT_FULL;
+    }
+    return SUCCESS;
+
+}
+
+/* Function Name:
+ *      rtl8306e_l2_mac_get
+ * Description:
+ *      Get an mac address information
+ * Input:
+ *      macAddress         -   the mac to be find in LUT  
+ * Output:
+ *      pIsStatic             -   the pointer of static or dynamic entry, for unicast mac address
+ *      pIsAuth               -   the pointer of IEEE 802.1x authorized status
+ *      pPortInfo             -   for unicast mac, it is the pointer of the port the mac belongs to;
+ *                                    for multicast mac, it is the pointer of portmask the mac forwarded to;
+ *      pEntryaddr           -   the entry address (0 ~2047) which the mac address is written into
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ *      RTL8306_LUT_NOTEXIST
+ * Note:
+ *      use this API to get a mac address information in LUT.
+ */ 
+int32 rtl8306e_l2_mac_get(uint8 *macAddr, uint32 *pIsStatic, uint32 *pIsAuth, uint32 *pPortInfo, uint32 *pEntryaddr) 
+{
+    int32  i;
+    uint8 macAddress[6];
+    uint32 index, entryAddress, age;
+    uint32 isStatic, isAuth;
+    uint32 port, portmask;
+    uint32 isHit ;
+
+    if((NULL == macAddr) || (NULL == pIsAuth) || (NULL == pPortInfo) || (NULL == pEntryaddr))
+        return FAILED;
+    
+    isHit = FALSE;
+    
+    rtl8306e_l2_MacToIdx_get(macAddr, &index);
+
+    /*scanning sequence is from entry 3 to entry 0, because priority
+      *of four way is entry 3 > entry 2 > entry 1 > entry 0
+      */
+    for (i = 3; i >= 0; i--) 
+    {
+        entryAddress = (index << 2) |(uint32) i;
+        if (rtl8306e_l2_unicastEntry_get(macAddress, entryAddress, &age, &isStatic, &isAuth, &port) != SUCCESS) 
+        {
+            return FAILED;
+        }
+        else if ((macAddr[0] == macAddress[0]) && (macAddr[1] == macAddress[1]) && 
+                    (macAddr[2] == macAddress[2]) && (macAddr[3] == macAddress[3]) &&
+                    (macAddr[4] == macAddress[4]) && (macAddr[5] == macAddress[5])) 
+        {
+            if(macAddr[0] & 0x1)
+            {
+                rtl8306e_l2_multicastEntry_get(macAddress, entryAddress, &isAuth, &portmask);
+                *pIsStatic = TRUE;
+                *pIsAuth = isAuth;
+                *pPortInfo = portmask;
+            }
+            else 
+            {
+                *pIsStatic = isStatic;
+                *pIsAuth = isAuth;
+                *pPortInfo = port;
+                if ((RTL8306_LUT_AGEOUT == age) && !isStatic && !isAuth)
+                    return  RTL8306_LUT_NOTEXIST;                                                                  
+            }
+
+            *pEntryaddr = entryAddress;
+            isHit = TRUE;
+            return SUCCESS;
+        }
+    }
+
+    if(!isHit)
+        return RTL8306_LUT_NOTEXIST;
+
+    return SUCCESS;
+}
+    
+
+/* Function Name:
+ *      rtl8306e_l2_mac_del
+ * Description:
+ *     Delete the specified Mac address, could be both unicast and multicast 
+ * Input:
+ *      macAddress      -  the Mac address(unicast or multicast) to be delete  
+ *                                and forward it to the member port of portMask
+ * Output:
+ *      pEntryaddr        -  entry address from which the Mac address is deleted
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function to delete a Mac address, it does not require to specify the 
+ *      entry address, if the Mac has existed in the LUT, it will be deleted and function
+ *      return value is SUCCESS, *pEntryaddr is recorded the entry address of the Mac 
+ *      address stored. if the Mac does not existed in the LUT, function return value is
+ *      RTL8306_LUT_NOTEXIST, and *pEntryaddr equals 10000.
+ */ 
+int32 rtl8306e_l2_mac_del(uint8 *macAddr, uint32 *pEntryaddr)
+{
+    uint32  i, port, portmask;
+    uint8 macAddr1[6];
+    uint32 index, entryaddr1, age;
+    uint32 isStatic, isAuth;
+    uint32 isHit = FALSE;
+    uint32 hashStatus;
+    
+    if ((NULL == macAddr) || (NULL == pEntryaddr))
+        return FAILED;
+
+    rtl8306e_l2_MacToIdx_get(macAddr, &index);
+    
+    if (!(macAddr[0] & 0x1)) 
+    {  
+        /*Delete an unicast entry*/
+        for (i = 4; i >= 1; i --) 
+        {
+            entryaddr1 = (index << 2) | (i - 1);
+            if(rtl8306e_l2_unicastEntry_get(macAddr1, entryaddr1, &age, &isStatic, &isAuth, &port) != SUCCESS) 
+                return FAILED;
+            else if (macAddr[0] ==macAddr1[0] && macAddr[1] ==macAddr1[1] 
+                       && macAddr[2] ==macAddr1[2] && macAddr[3] ==macAddr1[3]
+                       && macAddr[4] ==macAddr1[4] && macAddr[5] ==macAddr1[5]) 
+            {  
+                rtl8306e_l2_unicastEntry_set(macAddr, i -1, 0, FALSE, FALSE, port);
+                *pEntryaddr = entryaddr1;
+                isHit = TRUE;
+            } 
+        }
+    }
+    else 
+    {
+        /*Delet an multicast entry*/
+        for (i = 4; i >= 1; i --)
+        {
+            entryaddr1 = (index << 2) | (i - 1);
+#ifdef RTL8306_LUT_CACHE
+            if(rtl8306e_fastGetAsicLUTMulticastEntry(macAddr1, entryaddr1, &isAuth, &portmask) == FAILED) 
+#else
+            if(rtl8306e_l2_multicastEntry_get(macAddr1, entryaddr1, &isAuth, &portmask) != SUCCESS)
+#endif
+                return FAILED;
+            else if (macAddr[0] ==macAddr1[0] && macAddr[1] ==macAddr1[1] 
+                       && macAddr[2] ==macAddr1[2] && macAddr[3] ==macAddr1[3]
+                       && macAddr[4] ==macAddr1[4] && macAddr[5] ==macAddr1[5]) 
+            {  
+               /*
+                 * Turn multicast address to unicast address. If new hash is used 
+                 * bit 24 will be performed not operation to make the Index unchange
+                 */
+                rtl8306e_regbit_get(1, 23, 12, 0, &hashStatus);            
+
+                if (hashStatus) 
+                {
+                    macAddr1[0] = macAddr1[0] & 0xFE; 
+                    macAddr1[2] ^= 0x80;
+                } 
+                else 
+                {
+                    macAddr1[0] = macAddr1[0] & 0xFE; 
+                }
+                
+                if (rtl8306e_l2_unicastEntry_set(macAddr1, (uint32)(i -1), 0, FALSE, FALSE, 0) != SUCCESS)
+                    return FAILED;
+                *pEntryaddr = entryaddr1;
+                isHit = TRUE;
+            } 
+        }
+
+    }
+
+    if (!isHit) 
+    {
+        *pEntryaddr = 10000;
+        return RTL8306_LUT_NOTEXIST;
+    }
+    else 
+        return SUCCESS;
+
+}
+
+/* Function Name:
+ *      rtl8306e_l2_portMacLimit_set
+ * Description:
+ *      Set per port mac limit ability and auto learning limit number
+ * Input:
+ *      port         -  port number (0 ~ 5)  
+ *      enabled    - TRUE of FALSE  
+ *      macCnt    - auto learning MAC limit number
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */ 
+int32 rtl8306e_l2_portMacLimit_set(uint32 port, uint32 enabled, uint32 macCnt) 
+{
+    uint32 regValue;
+
+    if (port > RTL8306_PORT5)
+        return FAILED;
+    if (5 == port)
+        port ++;
+
+    if (0 == port)
+    {
+        rtl8306e_regbit_set(0, 26, 12, 3, enabled ? 1 : 0);
+        rtl8306e_reg_get(0, 27, 3, &regValue);
+        regValue &= ~(0x1F << 11);
+        regValue |= ((macCnt & 0x1F) << 11);
+        rtl8306e_reg_set(0, 27, 3, regValue);
+    }
+    else
+    {
+        rtl8306e_regbit_set(port, 30, 15, 1, enabled ? 1 : 0);
+        rtl8306e_reg_get(port, 31, 1, &regValue);
+        regValue &= ~(0x1F << 11);
+        regValue |= ((macCnt & 0x1F) << 11);
+        rtl8306e_reg_set(port, 31, 1, regValue);
+    }
+ 
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_portMacLimit_get
+ * Description:
+ *      Get per port mac limit ability and auto learning limit number
+ * Input:
+ *      port         -  port number (0 ~ 5)  
+ * Output:
+ *      pEnabled    -  enabled or disabled the port mac limit
+ *      pMacCnt     -  auto learning MAC limit number
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */ 
+int32 rtl8306e_l2_portMacLimit_get(uint32 port, uint32 *pEnabled, uint32 *pMacCnt) 
+{
+    uint32 regValue;
+    uint32 bitValue;
+
+    if (port > RTL8306_PORT5 || NULL == pEnabled || NULL == pMacCnt)
+        return FAILED;
+    if (5 == port)
+        port ++;
+
+    if (0 == port)
+    {
+        rtl8306e_regbit_get(0, 26, 12, 3, &bitValue);
+        *pEnabled = bitValue ? TRUE : FALSE;
+        rtl8306e_reg_get(0, 27, 3, &regValue);
+        *pMacCnt = (regValue & (0x1F << 11)) >> 11;
+    }
+    else
+    {
+        rtl8306e_regbit_get(port, 30, 15, 1, &bitValue);
+        *pEnabled = bitValue ? TRUE : FALSE;
+        rtl8306e_reg_get(port, 31, 1, &regValue);
+        *pMacCnt = (regValue & (0x1F << 11)) >> 11;
+    }
+ 
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_systemMacLimit_set
+ * Description:
+ *      Set the system mac limit ability and auto learning limit number
+ * Input:
+ *      enabled    - TRUE of FALSE  
+ *      macCnt    - system auto learning MAC limit number
+ *      mergMask  -  port mask for the ports merged to system mac limit
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Besides per port mac limit function, 8306E also supports system MAC limit function.
+ *      mergMask is to decide whitch ports are limited by system MAC limit function.
+ *      For example, when system mac limit is enabled, and mergMask is 0x15(0b010101),
+ *      that means the auto learning MAC number of port 0, port 2 and port 4 will also be
+ *      influenced by system MAC limit.    
+ */ 
+int32 rtl8306e_l2_systemMacLimit_set(uint32 enabled, uint32 macCnt, uint32 mergMask) 
+{
+    uint32 regValue;
+
+    rtl8306e_regbit_set(0, 26, 11, 3, enabled ? 1 : 0);
+    
+    rtl8306e_reg_get(0, 31, 0, &regValue);
+    regValue &= ~(0x7F);
+    regValue |= (macCnt & 0x7F) ;
+    rtl8306e_reg_set(0, 31, 0, regValue);
+    
+    rtl8306e_reg_get(0, 31, 0, &regValue);
+    regValue &= ~(0x3F << 10);
+    regValue |= ((mergMask & 0x3F) << 10);
+    rtl8306e_reg_set(0, 31, 0, regValue);
+ 
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_systemMacLimit_get
+ * Description:
+ *      Get the system mac limit ability and auto learning limit number
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled    -  enabled or disabled the system mac limit
+ *      pMacCnt    -   system auto learning MAC limit number
+ *      pMergMask  -  port mask for the ports merged to system mac limit
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */ 
+int32 rtl8306e_l2_systemMacLimit_get(uint32 *pEnabled, uint32 *pMacCnt, uint32 *pMergMask) 
+{
+    uint32 regValue;
+    uint32 bitValue;
+
+    rtl8306e_regbit_get(0, 26, 11, 3, &bitValue);
+    *pEnabled = bitValue ? TRUE : FALSE;
+    
+    rtl8306e_reg_get(0, 31, 0, &regValue);
+    *pMacCnt = (regValue & 0x7F);
+    
+    rtl8306e_reg_get(0, 31, 0, &regValue);
+    *pMergMask = (regValue & (0x3F << 10)) >> 10;
+    
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_macLimitAction_set
+ * Description:
+ *      Set the action taken by switch when auto learning MAC reach to the limit number
+ * Input:
+ *      action      -  the action taken when auto learning MAC reach to the max value 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */ 
+int32 rtl8306e_l2_macLimitAction_set(uint32 action) 
+{
+    if (RTL8306_ACT_DROP == action)
+        rtl8306e_regbit_set(0, 31, 9, 0, 0);
+    else if (RTL8306_ACT_TRAPCPU == action)
+        rtl8306e_regbit_set(0, 31, 9, 0, 1);
+    else
+        return FAILED;
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_l2_macLimitAction_get
+ * Description:
+ *      Get the action taken by switch when auto learning MAC reach to the limit number
+ * Input:
+ *      pAction      -  the action taken when auto learning MAC reach to the max value
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */ 
+int32 rtl8306e_l2_macLimitAction_get(uint32 *pAction) 
+{
+    uint32 bitValue;
+
+    if (NULL == pAction)
+        return FAILED;
+    
+    rtl8306e_regbit_get(0, 31, 9, 0, &bitValue);
+    if (bitValue)
+        *pAction = RTL8306_ACT_TRAPCPU;
+    else
+        *pAction = RTL8306_ACT_DROP;
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_stp_set
+ * Description:
+ *      Set IEEE 802.1d port state
+ * Input:
+ *      port   -  Specify port number (0 ~ 5)
+ *      state -   Specify port state
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 port state:
+ *         RTL8306_SPAN_DISABLE   - Disable state
+ *         RTL8306_SPAN_BLOCK      - Blocking state
+ *         RTL8306_SPAN_LEARN      - Learning state
+ *         RTL8306_SPAN_FORWARD - Forwarding state
+ */ 
+int32 rtl8306e_stp_set(uint32 port, uint32 state) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) || (state > RTL8306_SPAN_FORWARD))
+        return FAILED;
+
+    /*Enable BPDU to trap to cpu, BPDU could not be flooded to all port*/
+    rtl8306e_regbit_set(2, 21, 6, 3, 1);
+    rtl8306e_reg_get(4, 21, 3, &regValue);
+    regValue = (regValue & (~(0x3 << (2*port)))) | (state << (2*port));
+    rtl8306e_reg_set(4, 21, 3, regValue);
+
+#ifdef RTL8306_TBLBAK
+    rtl8306_TblBak.dot1DportCtl[port] = (uint8)state;
+#endif
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_stp_get
+ * Description:
+ *      Get IEEE 802.1d port state
+ * Input:
+ *      port    -  Specify port number (0 ~ 5)
+ * Output:
+ *      pState -  get port state
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 port state:
+ *         RTL8306_SPAN_DISABLE   - Disable state
+ *         RTL8306_SPAN_BLOCK      - Blocking state
+ *         RTL8306_SPAN_LEARN      - Learning state
+ *         RTL8306_SPAN_FORWARD - Forwarding state
+ */ 
+int32 rtl8306e_stp_get(uint32 port, uint32 *pState) 
+{
+    uint32 regValue;
+
+    if ((port > RTL8306_PORT5) || (NULL == pState))
+        return FAILED;
+    
+    rtl8306e_reg_get(4, 21, 3, &regValue);
+    *pState = (regValue & (0x3 << (2*port))) >> (2*port);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_dot1x_portBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ *      enabled    -   enable port-based access control
+ *      isAuth      -   Authorized or unauthorized state 
+ *      direction   -    set IEEE802.1x port-based control direction
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are two IEEE802.1x port state:
+ *         RTL8306_PORT_AUTH      - authorized
+ *         RTL8306_PORT_UNAUTH  - unauthorized
+ *
+ *     There are also two 802.1x port-based control direction:
+ *         RTL8306_PORT_BOTHDIR - if port-base access control is enabled, 
+ *                                              forbid forwarding this port's traffic to unauthorized port
+ *         RTL8306_PORT_INDIR     - if port-base access control is enabled, permit forwarding this
+ *                                              port's traffic to unauthorized port
+ */ 
+int32 rtl8306e_dot1x_portBased_set(uint32 port, uint32 enabled, uint32 isAuth, uint32 direction)
+{
+
+    if (port > RTL8306_PORT5)
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    
+    if (!enabled) 
+    {
+        rtl8306e_regbit_set(port, 17, 8, 2, 0);
+        rtl8306e_regbit_set(port, 17, 6, 2, isAuth == RTL8306_PORT_AUTH ? 1:0);
+        rtl8306e_regbit_set(port, 17, 7, 2, direction == RTL8306_PORT_BOTHDIR ? 0:1);
+    } 
+    else 
+    {
+        rtl8306e_regbit_set(port, 17, 8, 2, 1);
+        rtl8306e_regbit_set(port, 17, 6, 2, isAuth == RTL8306_PORT_AUTH ? 1:0);
+        rtl8306e_regbit_set(port, 17, 7, 2, direction == RTL8306_PORT_BOTHDIR ? 0:1);
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_dot1x_portBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ * Output:
+ *      pEnabled    - the pointer of port-based access control status
+ *      pIsAuth      - the pointer of authorized or unauthorized state 
+ *      pDirection   - the pointer of IEEE802.1x port-based control direction
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are two IEEE802.1x port state:
+ *         RTL8306_PORT_AUTH      - authorized
+ *         RTL8306_PORT_UNAUTH  - unauthorized
+ *
+ *     There are also two 802.1x port-based control direction:
+ *         RTL8306_PORT_BOTHDIR - if port-base access control is enabled, 
+ *                                              forbid forwarding this port's traffic to unauthorized port
+ *         RTL8306_PORT_INDIR     - if port-base access control is enabled, permit forwarding this
+ *                                              port's traffic to unauthorized port
+ */ 
+
+int32 rtl8306e_dot1x_portBased_get(uint32 port, uint32 *pEnabled, uint32 *pIsAuth, uint32 *pDirection) 
+{
+    uint32 bitValue;
+
+    if ((port > RTL8306_PORT5) || (NULL == pEnabled) || (NULL == pIsAuth) || (NULL == pDirection)) 
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (port == RTL8306_PORT5 )  
+        port ++ ;  
+    
+    rtl8306e_regbit_get(port, 17, 8, 2, &bitValue);
+    *pEnabled = (bitValue ? TRUE : FALSE);
+    rtl8306e_regbit_get(port, 17, 6, 2, &bitValue);
+    *pIsAuth = (bitValue ? RTL8306_PORT_AUTH : RTL8306_PORT_UNAUTH);
+    rtl8306e_regbit_get(port, 17, 7, 2, &bitValue);
+    *pDirection = (bitValue ? RTL8306_PORT_INDIR : RTL8306_PORT_BOTHDIR);
+    return SUCCESS;
+} 
+
+/* Function Name:
+ *      rtl8306e_dot1x_macBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ * Output:
+ *      enabled    - Enable the port Mac-based access control ability
+ *      direction   -  IEEE802.1x mac-based access control direction
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      the mac address authentication status is saved in L2 table entry,
+ *      it should be set by software.
+ *      there are also two mac-based control directions which are not per 
+ *      port but global configurtion:
+ *      RTL8306_MAC_BOTHDIR - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will be dropped.
+ *      RTL8306_MAC_INDIR   - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will pass mac-based access control igress rule.
+ */ 
+int32 rtl8306e_dot1x_macBased_set(uint32 port, uint32 enabled, uint32 direction)
+{
+
+    if (port > RTL8306_PORT5)
+        return FAILED;
+    
+    /*Port 5 corresponding PHY6*/
+    if (RTL8306_PORT5 == port)  
+        port ++ ;  
+    
+    if (!enabled) 
+    {
+        rtl8306e_regbit_set(port, 17, 9, 2, 0);
+        return SUCCESS;
+    } 
+    else 
+    {
+        rtl8306e_regbit_set(port, 17, 9, 2, 1);
+        rtl8306e_regbit_set(2, 22, 7, 3, direction == RTL8306_MAC_BOTHDIR ?  0 : 1 );
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_dot1x_macBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ * Output:
+ *      enabled    - Enable the port Mac-based access control ability
+ *      direction   -  IEEE802.1x mac-based access control direction
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      the mac address authentication status is saved in L2 table entry,
+ *      it should be set by software.
+ *      there are also two mac-based control directions which are not per 
+ *      port but global configurtion:
+ *      RTL8306_MAC_BOTHDIR - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will be dropped.
+ *      RTL8306_MAC_INDIR   - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will pass mac-based access control igress rule.
+ */ 
+ 
+int32 rtl8306e_dot1x_macBased_get(uint32 port, uint32 *pEnabled, uint32 *pDirection) 
+{
+    uint32 bitValue;
+
+    if ((port > RTL8306_PORT5) || (NULL == pEnabled) || (NULL == pDirection))
+        return FAILED;
+    
+    if (port  < RTL8306_PORT5 ) 
+        rtl8306e_regbit_get(port, 17, 9, 2, &bitValue);
+    else 
+        rtl8306e_regbit_get(6, 17, 9, 2, &bitValue);
+    *pEnabled = (bitValue ? TRUE : FALSE) ; 
+    rtl8306e_regbit_get(2, 22, 7, 3, &bitValue);
+    *pDirection = (bitValue ? RTL8306_PORT_INDIR : RTL8306_PORT_BOTHDIR);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_trap_igmpCtrlPktAction_set
+ * Description:
+ *      Set IGMP/MLD trap function
+ * Input:
+ *      type         -  Specify IGMP/MLD or PPPOE
+ *      action       -  Action could be normal forward or trap
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     type could be:
+ *          RTL8306_IGMP   - igmp packet without pppoe header 
+ *          RTL8306_MLD    - mld packet  without pppoe header
+ *          RTL8306_PPPOE_IGMPMLD - pppoe packet if enable trap RTL8306_IGMP 
+ *                                   or RTL8306_MLD whether pppoe packet 
+ *                                   should be trapped. In some application,
+ *                                   igmp and mld message is encapsulated in pppoed
+ *                                   packet.
+ *         
+ *      action could be:
+ *          RTL8306_ACT_PERMIT    - normal forward
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+
+int32 rtl8306e_trap_igmpCtrlPktAction_set(uint32 type, uint32 action)
+{    
+    switch(type)
+    {
+        case RTL8306_IGMP:
+            if (RTL8306_ACT_PERMIT == action)
+            {
+                rtl8306e_regbit_set(2, 21, 14, 3, 0);
+            }
+            else if (RTL8306_ACT_TRAPCPU == action)
+            {
+                rtl8306e_regbit_set(2, 21, 14, 3, 1);                
+            }
+            else
+            {
+                return FAILED;
+            }            
+            break;
+            
+        case RTL8306_MLD:
+            if (RTL8306_ACT_PERMIT == action)
+            {
+                rtl8306e_regbit_set(2, 21, 13, 3, 0);
+            }
+            else if (RTL8306_ACT_TRAPCPU == action)
+            {
+                rtl8306e_regbit_set(2, 21, 13, 3, 1);                
+            }
+            else
+            {
+                return FAILED;
+            }            
+            
+            break;
+
+         case RTL8306_PPPOE_IGMPMLD:
+            if (RTL8306_ACT_PERMIT == action)
+            {
+                rtl8306e_regbit_set(2, 22, 4, 3, 1);
+            }
+            else if (RTL8306_ACT_TRAPCPU == action)
+            {
+                rtl8306e_regbit_set(2, 22, 4, 3, 0);                
+            }
+            else
+            {
+                return FAILED;
+            }                        
+            break;
+            
+         default:
+            return FAILED;
+           
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_trap_igmpCtrlPktAction_get
+ * Description:
+ *      Get IGMP/MLD trap setting
+ * Input:
+ *      type         -  Specify IGMP/MLD or PPPOE
+ * Output:
+ *      pAction     -  the pointer of action could be normal forward or trap
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     type could be:
+ *          RTL8306_IGMP   - igmp packet without pppoe header 
+ *          RTL8306_MLD    - mld packet  without pppoe header
+ *          RTL8306_PPPOE_IGMPMLD - pppoe packet if enable trap RTL8306_IGMP 
+ *                                   or RTL8306_MLD whether pppoe packet 
+ *                                   should be trapped. In some application,
+ *                                   igmp and mld message is encapsulated in pppoed
+ *                                   packet.
+ *      action could be:
+ *          RTL8306_ACT_PERMIT    - normal forward
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+
+int32 rtl8306e_trap_igmpCtrlPktAction_get(uint32 type, uint32 *pAction)
+{
+    uint32 regval;
+
+    if (NULL == pAction)
+        return FAILED;
+    
+    switch(type)
+    {
+        case RTL8306_IGMP:
+            rtl8306e_regbit_get(2, 21, 14, 3, &regval);
+            *pAction = regval ? RTL8306_ACT_TRAPCPU : RTL8306_ACT_PERMIT;
+            break;            
+        case RTL8306_MLD:
+            rtl8306e_regbit_get(2, 21, 13, 3, &regval);
+            *pAction = regval ? RTL8306_ACT_TRAPCPU : RTL8306_ACT_PERMIT;            
+            break;
+         case RTL8306_PPPOE_IGMPMLD:
+            rtl8306e_regbit_get(2, 22, 4, 3, &regval);
+            *pAction = regval ?  RTL8306_ACT_PERMIT : RTL8306_ACT_TRAPCPU;
+            break;            
+         default:
+            return FAILED;           
+    }
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_trap_unknownIPMcastPktAction_set
+ * Description:
+ *      Set unknown ip multicast drop or normal forward
+ * Input:
+ *      type         -  Specify ipv4 or ipv6 unkown multicast
+ *      action       -  drop or normal forward
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_IPV4_MULTICAST - ipv4 unknown multicast
+ *          RTL8306_IPV6_MULTICAST - ipv6 unknown multicast
+ *      action could be:
+ *          RTL8306_ACT_DROP      - drop 
+ *          RTL8306_ACT_PERMIT   - normal forward
+ */  
+int32 rtl8306e_trap_unknownIPMcastPktAction_set(uint32 type, uint32 action)
+{    
+    switch(type)
+    {
+        case RTL8306_IPV4_MULTICAST:
+            if(RTL8306_ACT_DROP == action)
+                rtl8306e_regbit_set(4, 21, 9, 0, 1);
+            else if (RTL8306_ACT_PERMIT == action)
+                rtl8306e_regbit_set(4, 21, 9, 0, 0);
+            break;
+            
+        case RTL8306_IPV6_MULTICAST:
+            if(RTL8306_ACT_DROP == action)
+                rtl8306e_regbit_set(4, 21, 8, 0, 1);
+            else if (RTL8306_ACT_PERMIT == action)
+                rtl8306e_regbit_set(4, 21, 8, 0, 0);                                                
+            break;
+            
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_trap_unknownIPMcastPktAction_get
+ * Description:
+ *      Get unknown ip multicast drop or normal forward
+ * Input:
+ *      type         -  Specify ipv4 or ipv6 unkown multicast
+ * Output:
+ *      pAction     -  the pointer of drop or normal forward
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_IPV4_MULTICAST - ipv4 unknown multicast
+ *          RTL8306_IPV6_MULTICAST - ipv6 unknown multicast
+ *      action could be:
+ *          RTL8306_ACT_DROP      - drop
+ *          RTL8306_ACT_PERMIT   - normal forward
+ */ 
+
+int32 rtl8306e_trap_unknownIPMcastPktAction_get(uint32 type, uint32 *pAction)
+{
+    uint32 regval;
+    
+    if (NULL == pAction)
+        return FAILED;
+
+    switch(type)
+    {
+        case RTL8306_IPV4_MULTICAST:
+            rtl8306e_regbit_get(4, 21, 9, 0, &regval);
+            *pAction = regval ? RTL8306_ACT_DROP: RTL8306_ACT_PERMIT;
+            break;
+        case RTL8306_IPV6_MULTICAST:
+            rtl8306e_regbit_get(4, 21, 8, 0, &regval);
+            *pAction = regval ? RTL8306_ACT_DROP: RTL8306_ACT_PERMIT;            
+            break;
+         default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_trap_abnormalPktAction_set
+ * Description:
+ *      set abnormal packet action 
+ * Input:
+ *      type         -  abnormal packet type
+ *      action       -  drop or trap to cpu
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_UNMATCHVID   - vlan-tagged packet, vid dismatch vlan table 
+ *          RTL8306_DOT1XUNAUTH - 802.1x authentication fail packet
+ *      action could be:
+ *          RTL8306_ACT_DROP       - drop 
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+
+int32 rtl8306e_trap_abnormalPktAction_set(uint32 type,  uint32 action)
+{
+    switch(type)
+    {
+        case RTL8306_UNMATCHVID:            
+            if(RTL8306_ACT_DROP == action)
+                rtl8306e_regbit_set(2, 22, 6, 3, 1);
+            else if (RTL8306_ACT_TRAPCPU == action)
+                rtl8306e_regbit_set(2, 22, 6, 3, 0);            
+            break;
+            
+        case RTL8306_DOT1XUNAUTH:
+            if(RTL8306_ACT_DROP == action)
+                rtl8306e_regbit_set(2, 22, 5, 3, 0);
+            else if (RTL8306_ACT_TRAPCPU == action)
+                rtl8306e_regbit_set(2, 22, 5, 3, 1);                        
+            break;
+        default:
+            return FAILED;
+    }
+    
+    return SUCCESS;
+}
+
+
+/* Function Name:
+ *      rtl8306e_trap_abnormalPktAction_get
+ * Description:
+ *      get abnormal packet action 
+ * Input:
+ *      type         -  abnormal packet type
+ * Output:
+ *      pAction     -  the pointer of action
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_UNMATCHVID   - vlan-tagged packet, vid dismatch vlan table 
+ *          RTL8306_DOT1XUNAUTH - 802.1x authentication fail packet
+ *      action could be:
+ *          RTL8306_ACT_DROP       - drop 
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+
+int32 rtl8306e_trap_abnormalPktAction_get(uint32 type,  uint32 *pAction)
+{
+    uint32 regval;
+
+    if (NULL ==pAction)
+        return FAILED;
+    
+    switch(type)
+    {
+        case RTL8306_UNMATCHVID:
+            rtl8306e_regbit_get(2, 22, 6, 3, &regval);
+            *pAction = regval ? RTL8306_ACT_DROP: RTL8306_ACT_TRAPCPU;
+            break;
+        case RTL8306_DOT1XUNAUTH:
+            rtl8306e_regbit_get(2, 22, 5, 3, &regval);
+            *pAction = regval ? RTL8306_ACT_TRAPCPU : RTL8306_ACT_DROP;
+            break;
+        default:
+            return FAILED;
+    }
+
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_trap_rmaAction_set
+ * Description:
+ *      Set reserved multicast Mac address forwarding behavior
+ * Input:
+ *      type         -  reserved Mac address type
+ *      action       -  forwarding behavior for the specified mac address
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are eight types  reserved addresses which user can set asic to determine 
+ *       how to forwarding them:
+ *            RTL8306_RESADDRXX   - reserved address 01-80-c2-00-00-xx 
+ *                                              (exclude 00, 01, 02, 03, 10, 20, 21)
+ *            RTL8306_RESADDR21   -  reserved address 01-80-c2-00-00-21(GVRP address)
+ *            RTL8306_RESADDR20   -  reserved address 01-80-c2-00-00-20(GMRP Address)
+ *            RTL8306_RESADDR10   -  reserved address 01-80-c2-00-00-10(All LANs Bridge Management Group Address)
+ *            RTL8306_RESADDR03   -  reserved address 01-80-c2-00-00-03(IEEE Std 802.1X PAE address)
+ *            RTL8306_RESADDR02   -  reserved address 01-80-c2-00-00-02(IEEE Std 802.3ad Slow_Protocols-Multicast address)
+ *            RTL8306_RESADDR00   -  reserved address 01-80-c2-00-00-00(Bridge Group Address)
+ *            RTL8306_RESADDR01   -  reserved address 01-80-c2-00-00-01(Pause frame)
+ *       Actions are :
+ *            TL8306_ACT_DROP      - Drop the packet
+ *            TL8306_ACT_TRAPCPU - Trap the packet to cpu
+ *            RTL8306_ACT_FLOOD   - Flood the packet
+ */ 
+
+int32 rtl8306e_trap_rmaAction_set(uint32 type, uint32 action)
+{
+    if ((type > RTL8306_RESADDR01) || (action > RTL8306_ACT_FLOOD)) 
+        return FAILED;
+    
+    switch (type) 
+    {
+        case RTL8306_RESADDR21:
+        case RTL8306_RESADDR20:
+        case RTL8306_RESADDR10:
+        case RTL8306_RESADDR03:
+        case RTL8306_RESADDR00: 
+            
+            /*Above cases have same action*/
+            if (RTL8306_ACT_FLOOD == action) 
+                rtl8306e_regbit_set(2, 21, type, 3, 0);
+            else if (RTL8306_ACT_TRAPCPU == action)
+                rtl8306e_regbit_set(2, 21, type, 3, 1);
+            else 
+                return FAILED;
+            break;
+            
+        case RTL8306_RESADDR02:
+            if (RTL8306_ACT_FLOOD == action) 
+            {
+                rtl8306e_regbit_set(1, 23, 4, 0, 0); 
+                rtl8306e_regbit_set(2, 21, type, 3, 0);
+            }
+            else if (RTL8306_ACT_TRAPCPU == action) 
+            {
+                rtl8306e_regbit_set(1, 23, 4, 0, 0);
+                rtl8306e_regbit_set(2, 21, type, 3, 1);
+            }
+            else if (RTL8306_ACT_DROP == action) 
+                rtl8306e_regbit_set(1, 23, 4, 0, 1); 
+            else 
+                return FAILED;
+            break;
+        
+        case RTL8306_RESADDRXX:
+            if (RTL8306_ACT_FLOOD == action) 
+            {
+                rtl8306e_regbit_set(0, 18, 12, 0, 1); 
+                rtl8306e_regbit_set(2, 21, type, 3, 0);
+            } 
+            else if (RTL8306_ACT_TRAPCPU == action) 
+            {
+                rtl8306e_regbit_set(0, 18, 12, 0, 1);
+                rtl8306e_regbit_set(2, 21, type, 3, 1);
+            }
+            else if (RTL8306_ACT_DROP == action) 
+                rtl8306e_regbit_set(0, 18, 12, 0, 0);
+            else 
+                return FAILED;
+            break;
+        
+        case RTL8306_RESADDR01:
+            if (RTL8306_ACT_FLOOD == action) 
+                rtl8306e_regbit_set(0, 22, 14, 0, 1); 
+            else if (RTL8306_ACT_DROP == action)
+                rtl8306e_regbit_set(0, 22, 14, 0, 0);
+            else 
+                return FAILED;
+            break;
+        default :
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_trap_rmaAction_get
+ * Description:
+ *      Get reserved multicast Mac address forwarding behavior
+ * Input:
+ *      type         -  reserved Mac address type
+ * Output:
+ *      pAction     -  the pointer of action
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are eight types  reserved addresses which user can set asic to determine 
+ *       how to forwarding them:
+ *            RTL8306_RESADDRXX   - reserved address 01-80-c2-00-00-xx 
+ *                                              (exclude 00, 01, 02, 03, 10, 20, 21)
+ *            RTL8306_RESADDR21   -  reserved address 01-80-c2-00-00-21(GVRP address)
+ *            RTL8306_RESADDR20   -  reserved address 01-80-c2-00-00-20(GMRP Address)
+ *            RTL8306_RESADDR10   -  reserved address 01-80-c2-00-00-10(All LANs Bridge Management Group Address)
+ *            RTL8306_RESADDR03   -  reserved address 01-80-c2-00-00-03(IEEE Std 802.1X PAE address)
+ *            RTL8306_RESADDR02   -  reserved address 01-80-c2-00-00-02(IEEE Std 802.3ad Slow_Protocols-Multicast address)
+ *            RTL8306_RESADDR00   -  reserved address 01-80-c2-00-00-00(Bridge Group Address)
+ *            RTL8306_RESADDR01   -  reserved address 01-80-c2-00-00-01(Pause frame)
+ *       Actions are :
+ *            TL8306_ACT_DROP      - Drop the packet
+ *            TL8306_ACT_TRAPCPU - Trap the packet to cpu
+ *            RTL8306_ACT_FLOOD   - Flood the packet
+ */ 
+
+int32 rtl8306e_trap_rmaAction_get(uint32 type, uint32 *pAction)
+{
+    uint32 bitValue1, bitValue2;
+
+    if ((type > RTL8306_RESADDR01) || (NULL == pAction )) 
+        return FAILED;
+
+    switch (type)
+    {
+        case RTL8306_RESADDR21:
+        case RTL8306_RESADDR20:
+        case RTL8306_RESADDR10:
+        case RTL8306_RESADDR03:
+        case RTL8306_RESADDR00: 
+            /*Above cases have same action*/
+            rtl8306e_regbit_get(2, 21, type, 3, &bitValue1);
+            if (bitValue1) 
+                *pAction = RTL8306_ACT_TRAPCPU; 
+            else
+                *pAction = RTL8306_ACT_FLOOD; 
+            break;
+        case RTL8306_RESADDR02:
+            rtl8306e_regbit_get(1, 23, 4, 0, &bitValue1);  
+            rtl8306e_regbit_get(2, 21, type, 3, &bitValue2);
+            if (bitValue1)
+                *pAction = RTL8306_ACT_DROP;
+            else if (bitValue2)
+                *pAction = RTL8306_ACT_TRAPCPU;
+            else
+                *pAction = RTL8306_ACT_FLOOD;
+            break;
+        case RTL8306_RESADDRXX:
+            rtl8306e_regbit_get(0, 18, 12, 0, &bitValue1); 
+            rtl8306e_regbit_get(2, 21, type, 3, &bitValue2);
+            if (!bitValue1)
+                *pAction = RTL8306_ACT_DROP;
+            else if (bitValue2)
+                *pAction = RTL8306_ACT_TRAPCPU;
+            else
+                *pAction = RTL8306_ACT_FLOOD;
+            break;
+        case RTL8306_RESADDR01:
+            rtl8306e_regbit_get(0, 22, 14, 0, &bitValue1); 
+            if (bitValue1)
+                *pAction = RTL8306_ACT_FLOOD;
+            else
+                *pAction = RTL8306_ACT_DROP;
+            break;
+       default :
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_int_control_set
+ * Description:
+ *      Set asic interrupt 
+ * Input:
+ *      enInt        -  Enable interrupt cpu
+ *      intmask     -  interrupt event  mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      enInt is global setting and  intmask  has 12 bits totally, each bit 
+ *      represents one interrupt event, 
+ *      - bit0 ~bit4 represent port 0 ~ port 4 link change, 
+ *      - bit 5 represents port 4 MAC link change
+ *      - bit 6 represents port 5 link change, 
+ *      - bit 7 represents storm filter interrupt,
+ *      - bit 8 represents loop event 
+ *      - bit 9 represents wake up frame interrupt
+ *      - bit 10 represents unmatched SA interrupt
+ *      - bit 11 represents Tx meter interrupt
+ *      write 1 to the bit to enable the interrupt and 0 will disable the interrupt. 
+ *
+ */ 
+int32 rtl8306e_int_control_set(uint32 enInt, uint32 intmask)
+{
+    uint32 regValue;
+
+    if (intmask > 0xFFF)
+        return FAILED;
+
+    if (!enInt) 
+    {
+        /*CPU interrupt disable, do not change interrupt port mask*/
+        rtl8306e_regbit_set(2, 22, 15, 3, 1);
+        return SUCCESS;
+    } 
+    
+    /*CPU interrupt enable*/
+    rtl8306e_regbit_set(2, 22, 15, 3, 0);
+    
+    /*Set link change interrupt mask*/
+    rtl8306e_reg_get(4, 23, 3, &regValue);
+    regValue = (regValue & 0xF000) | (intmask & 0xFFF);
+    rtl8306e_reg_set(4, 23, 3, regValue);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_int_control_get
+ * Description:
+ *      Get Asic interrupt
+ * Input:
+ *      none 
+ * Output:
+ *      pEnInt       -  the pointer of  interrupt global enable bit
+ *      pIntmask    -  the pointer of interrupt event  mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      enInt is global setting and  intmask  has 12 bits totally, each bit 
+ *      represents one interrupt event, 
+ *      - bit0 ~bit4 represent port 0 ~ port 4 link change, 
+ *      - bit 5 represents port 4 MAC link change
+ *      - bit 6 represents port 5 link change, 
+ *      - bit 7 represents storm filter interrupt,
+ *      - bit 8 represents loop event 
+ *      - bit 9 represents wake up frame interrupt
+ *      - bit 10 represents unmatched SA interrupt
+ *      - bit 11 represents Tx meter interrupt
+ *      write 1 to the bit to enable the interrupt and 0 will disable the interrupt. 
+ *
+ */ 
+int32 rtl8306e_int_control_get(uint32 *pEnInt, uint32 *pIntmask) 
+{
+    uint32 regValue;
+    uint32 bitValue;
+
+    if ((NULL == pEnInt) || (NULL == pIntmask))
+        return FAILED;
+    
+    rtl8306e_regbit_get(2, 22, 15, 3, &bitValue);
+    *pEnInt = (bitValue ? FALSE : TRUE);
+    rtl8306e_reg_get(4, 23, 3, &regValue);
+    *pIntmask = regValue & 0xFFF;
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_int_control_get
+ * Description:
+ *      Get Asic interrupt
+ * Input:
+ *      none 
+ * Output:
+ *      pEnInt       -  the pointer of  interrupt global enable bit
+ *      pIntmask    -  the pointer of interrupt event  mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      enInt is global setting and  intmask  has 12 bits totally, each bit 
+ *      represents one interrupt event, 
+ *      - bit0 ~bit4 represent port 0 ~ port 4 link change, 
+ *      - bit 5 represents port 4 MAC link change
+ *      - bit 6 represents port 5 link change, 
+ *      - bit 7 represents storm filter interrupt,
+ *      - bit 8 represents loop event 
+ *      - bit 9 represents wake up frame interrupt
+ *      - bit 10 represents unmatched SA interrupt
+ *      - bit 11 represents Tx meter interrupt
+ *      write 1 to the bit to enable the interrupt and 0 will disable the interrupt. 
+ *
+ */ 
+int32 rtl8306e_int_status_get(uint32 *pStatusMask) 
+{
+    uint32 regValue;
+
+    if (NULL == pStatusMask)
+        return FAILED;
+    
+    rtl8306e_reg_get(4, 22, 3, &regValue);
+    *pStatusMask = regValue & 0xFFF;
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_storm_filterEnable_set
+ * Description:
+ *      Enable Asic storm filter 
+ * Input:
+ *      type      -  specify storm filter type
+ *      enabled  -  TRUE or FALSE
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 3 kinds of storm filter:
+ *      (1) RTL8306_BROADCASTPKT - storm filter for broadcast packet
+ *      (2) RTL8306_MULTICASTPKT - storm filter for multicast packet
+ *      (3) RTL8306_UDAPKT           - storm filter for unknown DA packet
+ */ 
+int32 rtl8306e_storm_filterEnable_set(uint32 type, uint32 enabled) 
+{
+
+   /*enable new storm filter*/
+   rtl8306e_regbit_set(6, 17, 1, 1, enabled ? 1:0);
+   
+    switch(type) 
+    {
+        case RTL8306_BROADCASTPKT:
+            rtl8306e_regbit_set(0, 18, 2, 0, enabled ? 0:1);
+            break;
+        case RTL8306_MULTICASTPKT:
+            rtl8306e_regbit_set(2, 23, 9, 3, enabled ? 0:1);
+            break;
+        case RTL8306_UDAPKT:
+            rtl8306e_regbit_set(2, 23, 8, 3, enabled ? 0:1);
+            break;
+        default:
+            return FAILED;
+    }
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_storm_filterEnable_get
+ * Description:
+ *      Get Asic storm filter enabled or disabled 
+ * Input:
+ *      type        -  specify storm filter type
+ * Output:
+ *      pEnabled  -  the pointer of enabled or disabled
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 3 kinds of storm filter:
+ *      (1) RTL8306_BROADCASTPKT - storm filter for broadcast packet
+ *      (2) RTL8306_MULTICASTPKT - storm filter for multicast packet
+ *      (3) RTL8306_UDAPKT           - storm filter for unknown DA packet
+ */ 
+
+int32 rtl8306e_storm_filterEnable_get(uint32 type, uint32 *pEnabled) 
+{
+    uint32 bitValue;
+
+    if (pEnabled == NULL)
+        return FAILED;
+    
+    switch(type) 
+   {
+        case RTL8306_BROADCASTPKT:
+            rtl8306e_regbit_get(0, 18, 2, 0, &bitValue);
+            break;
+        case RTL8306_MULTICASTPKT:
+            rtl8306e_regbit_get(2, 23, 9, 3, &bitValue);
+            break;
+        case RTL8306_UDAPKT:
+            rtl8306e_regbit_get(2, 23, 8, 3, &bitValue);
+            break;
+        default:
+            return FAILED;
+
+    }
+
+    *pEnabled = (bitValue ? FALSE : TRUE);
+    return SUCCESS;
+}
+
+/* Function Name:
+ *      rtl8306e_storm_filter_set
+ * Description:
+ *      Set storm filter parameter
+ * Input:
+ *      trigNum        -  set packet threshold which trigger storm filter
+ *      filTime         -   set time window 
+ *      enStmInt     -   enable storm filter to interrupt cpu
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      there are 6 value for trigNum:
+ *      - RTL8306_STM_FILNUM64, 64 pkts
+ *      - RTL8306_STM_FILNUM32, 32 pkts           
+ *      - RTL8306_STM_FILNUM16, 16 pkts           
+ *      - RTL8306_STM_FILNUM8,   8 pkts              
+ *      - RTL8306_STM_FILNUM128, 128 pkts          
+ *      - RTL8306_STM_FILNUM256, 256 pkts     
+ *      there are 4 value for filTime:
+ *      - RTL8306_STM_FIL800MS,  800ms 
+ *      - RTL8306_STM_FIL400MS,  400ms 
+ *      - RTL8306_STM_FIL200MS,  200ms
+ *      - RTL8306_STM_FIL100MS,  100ms
+ */ 
+
+int32 rtl8306e_storm_filter_set(uint32 trigNum, uint32 filTime, uint32 enStmInt) 
+{
+    uint32 regval;
+    
+    if ( (trigNum >= RTL8306_STM_FILNUM_END) || (filTime >= RTL8306_STM_FILTIM_END))
+        return FAILED;
+    
+    if(RTL8306_STM_FILNUM128 == trigNum)
+    {
+        rtl8306e_reg_get(6, 25, 0, &regval);
+        regval &= 0xFC1F;
+        regval |= (filTime << 5); 
+        rtl8306e_reg_set(6, 25, 0 , regval);        
+        rtl8306e_regbit_set(6, 17, 0, 1, 1);
+    }
+    else if(RTL8306_STM_FILNUM256 == trigNum)
+    {
+        rtl8306e_reg_get(6, 25, 0, &regval);
+        regval &= 0xFC1F;
+        regval |= (0x1 << 8) | (filTime << 5); 
+        rtl8306e_reg_set(6, 25, 0 , regval);        
+        rtl8306e_regbit_set(6, 17, 0, 1, 1);
+    }
+    else
+    {
+        rtl8306e_reg_get(6, 25, 0, &regval);
+        regval &= 0xFC1F;
+        regval |= (trigNum << 8) | (filTime << 5);
+        rtl8306e_reg_set(6, 25, 0 , regval);
+        rtl8306e_regbit_set(6, 17, 0, 1, 0);        
+    }
+        
+    /*Set whether storm filter interrupt cpu*/
+    rtl8306e_regbit_set(4, 23, 7, 3, enStmInt ? 1:0);
+    
+    /*CPU interrupt enable when enable storm filter interrupt*/
+    rtl8306e_regbit_set(2, 22, 15, 3, enStmInt ? 0:1);
+
+    return SUCCESS;
+
+}
+
+
+/* Function Name:
+ *      rtl8306e_storm_filter_get
+ * Description:
+ *      Get storm filter parameter
+ * Input:
+ *      none 
+ * Output:
+ *      pTrigNum        -  the pointer of packet threshold which trigger storm filter
+ *      pFilTime          -  the pointer of filter time window 
+ *      pEnStmInt       -  the pointer of enable storm filter to interrupt cpu
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      there are 6 value for trigNum:
+ *      - RTL8306_STM_FILNUM64, 64 pkts
+ *      - RTL8306_STM_FILNUM32, 32 pkts           
+ *      - RTL8306_STM_FILNUM16, 16 pkts           
+ *      - RTL8306_STM_FILNUM8,   8 pkts              
+ *      - RTL8306_STM_FILNUM128, 128 pkts          
+ *      - RTL8306_STM_FILNUM256, 256 pkts     
+ *      there are 4 value for filTime:
+ *      - RTL8306_STM_FIL800MS,  800ms 
+ *      - RTL8306_STM_FIL400MS,  400ms 
+ *      - RTL8306_STM_FIL200MS,  200ms
+ *      - RTL8306_STM_FIL100MS,  100ms
+ */ 
+
+int32 rtl8306e_storm_filter_get(uint32 *pTrigNum, uint32 *pFilTime, uint32 *pEnStmInt) 
+{
+    uint32 bitval, regval;
+    
+    if ((NULL == pTrigNum) || (NULL == pFilTime) || (NULL == pEnStmInt))
+        return FAILED;
+
+    rtl8306e_regbit_get(6, 17, 0, 1, &bitval);
+
+    if(bitval)
+    {
+        rtl8306e_reg_get(6, 25, 0, &regval);
+        *pTrigNum = ((regval >> 8) & 0x3) ? RTL8306_STM_FILNUM256 : RTL8306_STM_FILNUM128;
+        *pFilTime = (regval >> 5) & 0x3;
+    }
+    else
+    {
+        rtl8306e_reg_get(6, 25, 0, &regval);
+        *pTrigNum = (regval >> 8) & 0x3;
+        *pFilTime = (regval >> 5) & 0x3;
+    }
+    rtl8306e_regbit_get(4, 23, 7, 3, pEnStmInt);
+    
+    return SUCCESS;
+}
+
+
+
+
+int32 rtl8306e_vlan_portBase_set()
+{
+    uint32 i;
+    uint32 vid;
+    rtk_vlan_t pPvid;
+    rtk_pri_t pPriority;
+    rtk_portmask_t pMbrmsk;
+    rtk_portmask_t pUntagmsk;
+    rtk_portmask_t pMbrmsk2;
+    rtk_portmask_t pUntagmsk2;
+    rtk_fid_t pFid;
+    rtk_portmask_t mbrmsk;
+	rtk_portmask_t mbrmsk2;
+    rtk_portmask_t untagmsk;
+	rtk_portmask_t untagmsk2;
+	rtk_portmask_t portmask;
+    spinlock_t lock;
+    spin_lock_init(&lock);
+	
+  spin_lock_irq(&lock);
+	
+	//init vlan
+    rtk_vlan_init();
+    rtl8306e_vlan_IgrFilterEnable_set(TRUE);
+    
+	//delet default vlan 1,
+    rtk_vlan_destroy(1);
+	
+	//creat vlan 1
+    vid = 100; 
+    mbrmsk.bits[0] =  (0x1 << RTL8306_PORT0) | (0x1 << RTL8306_PORT1) |(0x1 << RTL8306_PORT2)|(0x1 << RTL8306_PORT3)| (0x1 << RTL8306_PORT5);                                 
+    untagmsk.bits[0] = (0x1 << RTL8306_PORT0) | (0x1 << RTL8306_PORT1) | (0x1 << RTL8306_PORT2)| (0x1 << RTL8306_PORT3);                                 
+    rtk_vlan_set(vid, mbrmsk, untagmsk, 0);  
+    //rtk_vlan_get(100, &pMbrmsk, &pUntagmsk, &pFid);	
+    //for(i=0;i<10;i++)
+	//printk("the value of pMbrmsk is %x\n", pMbrmsk.bits[0]);
+	
+	//creat vlan 2
+  
+    vid = 200; 
+    mbrmsk2.bits[0] =  (0x1 << RTL8306_PORT4)| (0x1 << RTL8306_PORT5); 
+    untagmsk2.bits[0] = (0x1 << RTL8306_PORT4); 
+    rtk_vlan_set(vid, mbrmsk2, untagmsk2, 0);
+    //rtk_vlan_get(200, &pMbrmsk2, &pUntagmsk2, &pFid);
+	
+	//for(i=0;i<10;i++)
+	//printk("the value of pMbrmsk2 is %x\n", pMbrmsk2.bits[0]);
+	
+	//set pvid
+    //spin_lock_irq(&lock);
+    rtk_vlan_portPvid_set(RTL8306_PORT0, 100, 0);
+	rtk_vlan_portPvid_set(RTL8306_PORT1, 100, 0); 	
+    rtk_vlan_portPvid_set(RTL8306_PORT2, 100, 0);
+	rtk_vlan_portPvid_set(RTL8306_PORT3, 100, 0);    
+    rtk_vlan_portPvid_set(RTL8306_PORT4, 200, 0);
+	rtk_vlan_portPvid_set(RTL8306_PORT5, 200, 0);
+    rtk_vlan_portPvid_get(RTL8306_PORT5, &pPvid, &pPriority);
+	//spin_unlock_irq(&lock);
+    
+	//set AcceptFrameType
+	rtk_vlan_portAcceptFrameType_set(RTL8306_PORT0, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT1, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT2, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT3, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT4, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+	    
+   //set CPU port insert tag based on ingress port 
+   rtl8306e_vlan_tagInsertRemove_set(RTL8306_PORT5, RTL8306_VLAN_ITAG); 
+   rtl8306e_vlan_leaky_set(RTL8306_VALN_LEAKY_ARP,0);//EC 616000558230
+     spin_unlock_irq(&lock);
+	return SUCCESS;
+}
+
+int32 set()
+{
+    uint32 i;
+    uint32 vid;
+    rtk_vlan_t pPvid;
+    rtk_pri_t pPriority;
+    rtk_portmask_t pMbrmsk;
+    rtk_portmask_t pUntagmsk;
+    rtk_portmask_t pMbrmsk2;
+    rtk_portmask_t pUntagmsk2;
+    rtk_fid_t pFid;
+    rtk_portmask_t mbrmsk;
+	rtk_portmask_t mbrmsk2;
+    rtk_portmask_t untagmsk;
+	rtk_portmask_t untagmsk2;
+	rtk_portmask_t portmask;
+    spinlock_t lock;
+    spin_lock_init(&lock);
+	
+  spin_lock_irq(&lock);
+	
+	//init vlan
+    rtk_vlan_init();
+    rtl8306e_vlan_IgrFilterEnable_set(TRUE);
+    
+	//delet default vlan 1,
+    rtk_vlan_destroy(1);
+	
+	//creat vlan 1
+    vid = 100; 
+    mbrmsk.bits[0] =  (0x1 << RTL8306_PORT0) | (0x1 << RTL8306_PORT1) |(0x1 << RTL8306_PORT2)|(0x1 << RTL8306_PORT3);//| (0x1 << RTL8306_PORT5);                                 
+    untagmsk.bits[0] = (0x1 << RTL8306_PORT0) | (0x1 << RTL8306_PORT1) | (0x1 << RTL8306_PORT2)| (0x1 << RTL8306_PORT3);                                 
+    rtk_vlan_set(vid, mbrmsk, untagmsk, 0);  
+   // rtk_vlan_get(100, &pMbrmsk, &pUntagmsk, &pFid);	
+   // for(i=0;i<10;i++)
+	//printk("the value of pMbrmsk is %x\n", pMbrmsk.bits[0]);
+	
+	//creat vlan 2
+  
+    vid = 200; 
+    mbrmsk2.bits[0] =  (0x1 << RTL8306_PORT4);//| (0x1 << RTL8306_PORT5); 
+    untagmsk2.bits[0] = (0x1 << RTL8306_PORT4); 
+    rtk_vlan_set(vid, mbrmsk2, untagmsk2, 0);
+  //  rtk_vlan_get(200, &pMbrmsk2, &pUntagmsk2, &pFid);
+	
+	//for(i=0;i<10;i++)
+	//printk("the value of pMbrmsk2 is %x\n", pMbrmsk2.bits[0]);
+	
+	//set pvid
+    //spin_lock_irq(&lock);
+    rtk_vlan_portPvid_set(RTL8306_PORT0, 100, 0);
+	rtk_vlan_portPvid_set(RTL8306_PORT1, 100, 0); 	
+    rtk_vlan_portPvid_set(RTL8306_PORT2, 100, 0);
+	rtk_vlan_portPvid_set(RTL8306_PORT3, 100, 0);    
+    rtk_vlan_portPvid_set(RTL8306_PORT4, 200, 0);
+	//rtk_vlan_portPvid_set(RTL8306_PORT5, 200, 0);
+    //rtk_vlan_portPvid_get(RTL8306_PORT5, &pPvid, &pPriority);
+	//spin_unlock_irq(&lock);
+    
+	//set AcceptFrameType
+	rtk_vlan_portAcceptFrameType_set(RTL8306_PORT0, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT1, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT2, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT3, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+    rtk_vlan_portAcceptFrameType_set(RTL8306_PORT4, ACCEPT_FRAME_TYPE_UNTAG_ONLY);
+	    
+   //set CPU port insert tag based on ingress port 
+  // rtl8306e_vlan_tagInsertRemove_set(RTL8306_PORT5, RTL8306_VLAN_ITAG); 
+
+     spin_unlock_irq(&lock);
+	return SUCCESS;
+}
+
+void port_isalation()
+{
+rtk_portmask_t portmask22222;
+//第一次是这样弄的:
+	//port isolation
+	portmask22222.bits[0] = (0x1 << RTL8306_PORT5);
+	rtk_port_isolation_set(RTL8306_PORT4,portmask22222);
+    //rtk_port_isolation_set(rtk_port_t port, portmask22222);
+//第二次这样弄:
+	//rtl8306e_port_isolation_set(0x2888);
+	rtk_cpu_enable_set(ENABLED); 
+    rtk_cpu_tagPort_set(RTL8306_PORT5, CPU_INSERT_TO_ALL); 
+}
+
+ void readreg()
+{
+int i;
+rtk_port_phy_data_t pData;
+    spinlock_t lock;
+    spin_lock_init(&lock);
+	
+  spin_lock_irq(&lock);
+//rtk_port_phyReg_get(rtk_port_t phy, rtk_port_phy_reg_t reg, rtk_port_phy_data_t *pData) 
+rtk_port_phyReg_get(0, 24, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY0 Register 24 is %x\n\n", pData);
+rtk_port_phyReg_get(0, 25, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY0 Register 25 is %x\n\n", pData);
+rtk_port_phyReg_get(1, 24, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY1 Register 24 is %x\n\n", pData);
+rtk_port_phyReg_get(1, 25, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY1 Register 25 is %x\n\n", pData);
+rtk_port_phyReg_get(2, 24, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY2 Register 24 is %x\n\n", pData);
+rtk_port_phyReg_get(2, 25, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY2 Register 25 is %x\n\n", pData);
+rtk_port_phyReg_get(3, 24, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY3 Register 24 is %x\n\n", pData);
+rtk_port_phyReg_get(3, 25, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY3 Register 25 is %x\n\n", pData);
+rtk_port_phyReg_get(4, 24, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY4 Register 24 is %x\n\n", pData);
+rtk_port_phyReg_get(4, 25, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY4 Register 25 is %x\n\n", pData);
+rtk_port_phyReg_get(0, 26, &pData);
+    for(i=0;i<10;i++)
+	printk("the value of PHY0 Register 26 is %x\n\n", pData);	
+	     spin_unlock_irq(&lock);
+}
+
+int switch_open(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+ int switch_ioctl (struct inode *node, struct file *filp, unsigned int cmd, unsigned long arg)
+{	
+	return 0;
+}
+/*4实现操作硬件的方法*/
+static struct file_operations switch_fops = {
+ .owner  = THIS_MODULE,
+ .open   = switch_open,
+ .unlocked_ioctl  = switch_ioctl,
+};
+
+/*3。实现probe函数*/
+static int switch_probe(struct platform_device *dev)
+{	
+	int i;
+	int32 flag;
+	uint32 value1;
+	uint32 *pVid;
+	uint32 *pMbrmsk;
+	uint32 *pUntagmsk;
+	rtk_mode_ext_t *Mode;
+    rtk_port_mac_ability_t portAbility;
+	#if 0
+    /*时钟设置*/
+    virt =(unsigned long)ioremap(0x13B000, 0x11C);
+    unsigned int value;
+	value = ioread32(virt+0x11C);
+	value   = 0x00000005;
+	iowrite32(value,virt+0x11C);
+	mdelay(10);
+
+    /*MAC5 force link up*/
+	 *Mode = MODE_EXT_RMII;
+  	 portAbility.forcemode = 1;
+	 portAbility.nway = 0;
+	 portAbility.speed = PORT_SPEED_100M;
+	 portAbility.link = 1;
+	 portAbility.duplex = PORT_FULL_DUPLEX;
+	 portAbility.rxpause = 1;
+	 portAbility.txpause = 1;
+
+	rtk_port_macForceLinkExt0_set(*Mode,&portAbility);
+#endif
+    switch_major =register_chrdev(0,"switch",&switch_fops);
+	switch_class = class_create(THIS_MODULE, "switch");
+	device_create(switch_class, NULL,MKDEV(switch_major,0),NULL,"switch" );
+	//rtl8306e_asic_init();
+	//rtl8306e_vlan_portBase_set();	
+    //port_isalation();
+    /*****test reg
+	flag == SUCCESS;
+	flag = rtl8306e_reg_get(6, 22, 0, &value1);
+
+	if (flag == SUCCESS)
+		{
+		for(i=0;i<100;i++)
+		{
+		printk("value1 value1value1value1value1value1 is%x", value1);
+	  }
+			}
+			else
+				{			
+					for(i=0;i<100;i++)
+		{		
+					printk("getfaultttttttttttttttttttttttttttttttttttttt");				
+					
+					}
+					}
+		***/			
+readreg();
+	 return 0;
+}
+
+int switch_remove(struct platform_device *dev)
+{
+     unregister_chrdev(switch_major, "switch");
+	 device_destroy(switch_class,MKDEV(switch_major,0));   
+	 class_destroy(switch_class);	 
+	 return 0;
+}
+
+
+static struct platform_driver switch_driver = {
+  .probe  = switch_probe,     
+  .remove  = switch_remove,   
+  .driver  = {
+	  .name = "switch",       
+	  .owner = THIS_MODULE,
+ },
+};
+
+static int switch_drv_init(void)
+{
+	 
+	 platform_driver_register(&switch_driver);
+	 return 0;
+}
+
+static int switch_drv_exit(void)
+{
+	 platform_driver_unregister(&switch_driver);
+	 return 0;
+}
+
+//module_init(switch_drv_init);
+//module_exit(switch_drv_exit);
+
+MODULE_LICENSE("GPL"); 
+ 
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asicdrv.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asicdrv.h
new file mode 100644
index 0000000..406df1e
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asicdrv.h
@@ -0,0 +1,3233 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 26889 $ 
+* $Date: 2012-02-28 21:08:47 +0800 (星期二, 2012-02-28) $
+*
+* Purpose : asic-level driver implementation for RTL8306E switch
+*
+*  Feature :  This file consists of following modules:
+*                1) 
+*
+*/
+
+
+#ifndef __RTL8306E_ASICDRV_H__
+#define __RTL8306E_ASICDRV_H__
+
+/*save time of reading LUT*/
+/*#define RTL8306_LUT_CACHE */
+
+/*if you need backup asic info in cpu memroy in order to 
+ *accellerate CPU process, please define this macro. If 
+ *support IGMP snooping, this macro is required.
+ */
+#define RTL8306_TBLBAK   
+//#define RTK_X86_ASICDRV  
+#define RTL8306_PHY_NUMBER        7
+#define RTL8306_PAGE_NUMBER      5
+#define RTL8306_PORT_NUMBER      6
+#define RTL8306_VLAN_ENTRYS      16            /*Vlan entry number*/ 
+#define RTL8306_ACL_ENTRYNUM    16           /*ACL entry number*/
+
+#define RTL8306_IDLE_TIMEOUT   100
+#define RTL8306_QOS_RATE_INPUT_MAX 0x5F6
+#define RTL8306_VIDMAX                       0XFFF
+#define RTL8306_MAX_PORTMASK           0X3F
+
+
+enum RTL8306E_REGPAGE
+{
+    RTL8306_REGPAGE0 = 0,
+    RTL8306_REGPAGE1,
+    RTL8306_REGPAGE2,
+    RTL8306_REGPAGE3,
+    RTL8306_REGPAGE4,    
+    RTL8306_REGPAGE_END
+    
+};
+
+enum RTL8306E_PORTNUM
+{
+    RTL8306_PORT0 = 0,
+    RTL8306_PORT1,        
+    RTL8306_PORT2,
+    RTL8306_PORT3,  
+    RTL8306_PORT4,
+    RTL8306_PORT5,
+    RTL8306_NOCPUPORT = 7    
+};
+
+enum RTL8306E_PHYMODE
+{
+    RTL8306_ETHER_AUTO_100FULL = 1,
+    RTL8306_ETHER_AUTO_100HALF,
+    RTL8306_ETHER_AUTO_10FULL,
+    RTL8306_ETHER_AUTO_10HALF
+};
+
+enum RTL8306E_PHYSPD
+{
+    RTL8306_ETHER_SPEED_100 = 100,
+    RTL8306_ETHER_SPEED_10 = 10        
+};
+
+enum RTL8306E_TAGMOD
+{
+    RTL8306_VLAN_IRTAG = 0,             /*The switch will remove VLAN tags and add new tags */
+    RTL8306_VLAN_RTAG,                   /*The switch will remove VLAN tags */
+    RTL8306_VLAN_ITAG,                   /*The switch will  add new VLANtag */
+    RTL8306_VLAN_UNDOTAG            /*Do not insert or remove  VLAN tag */
+};
+
+enum RTL8306E_LEAKYVLAN
+{
+    RTL8306_VALN_LEAKY_UNICAST = 0,
+    RTL8306_VALN_LEAKY_MULTICAST,
+    RTL8306_VALN_LEAKY_ARP,
+    RTL8306_VALN_LEAKY_MIRROR,
+    RTL8306_VALN_LEAKY_END
+};
+
+/*ACL Packet processing method*/
+enum RTL8306E_ACTION
+{
+    RTL8306_ACT_DROP = 0,    /*drop the packet*/    
+    RTL8306_ACT_PERMIT,      /*permit the packet*/        
+    RTL8306_ACT_TRAPCPU,   /*trap the packet to cpu*/
+    RTL8306_ACT_MIRROR,     /*mirror the packet */
+    RTL8306_ACT_FLOOD      /*flood the packet  */    
+};
+
+/*
+  * PHY control register field definitions 
+  */
+#define RTL8306_SPEED_SELECT_100M                       (1 << 13)  
+#define RTL8306_ENABLE_AUTONEGO                         (1 << 12)
+#define RTL8306_RESTART_AUTONEGO                        (1 << 9)
+#define RTL8306_SELECT_FULL_DUPLEX                      (1 << 8)
+
+/* 
+  *PHY auto-negotiation advertisement and link partner 
+  *ability registers field definitions
+  */
+#define RTL8306_NEXT_PAGE_ENABLED                       (1 << 15)
+#define RTL8306_ACKNOWLEDGE                                 (1 << 14)
+#define RTL8306_REMOTE_FAULT                                 (1 << 13)
+#define RTL8306_CAPABLE_PAUSE                               (1 << 10)
+#define RTL8306_CAPABLE_100BASE_T4                      (1 << 9)
+#define RTL8306_CAPABLE_100BASE_TX_FD                (1 << 8)
+#define RTL8306_CAPABLE_100BASE_TX_HD                (1 << 7)
+#define RTL8306_CAPABLE_10BASE_TX_FD                  (1 << 6)
+#define RTL8306_CAPABLE_10BASE_TX_HD                  (1 << 5)
+#define RTL8306_SELECTOR_MASK                               0x1F
+#define RTL8306_SELECTOR_OFFSET                             0
+
+enum RTL8306E_IGMPCTL
+{
+    RTL8306_IGMP = 0,
+    RTL8306_MLD, 
+    RTL8306_PPPOE_IGMPMLD
+};
+
+enum RTL8306E_IPMULTICAST
+{
+    RTL8306_IPV4_MULTICAST = 0,
+    RTL8306_IPV6_MULTICAST
+};
+
+#define RTL8306_PORT_RX  0
+#define RTL8306_PORT_TX  1
+
+enum RTL8306E_QUENUM
+{
+    RTL8306_QUEUE0 = 0,
+    RTL8306_QUEUE1,
+    RTL8306_QUEUE2,
+    RTL8306_QUEUE3
+};
+
+enum RTL8306E_PRISRC
+{
+    RTL8306_ACL_PRIO = 0,           /*ACL-based priority*/
+    RTL8306_DSCP_PRIO,              /*DSCP-based priority*/
+    RTL8306_1QBP_PRIO,              /*802.1Q-based priority*/ 
+    RTL8306_PBP_PRIO,                /*port- based priority */
+    RTL8306_CPUTAG_PRIO,          /*cpu tag priority*/
+    RTL8306_IP_PRIO,                  /* ip address priority*/
+    RTL8306_1QTAG_PRIO,           /* VLAN tag priority */
+    RTL8306_PRI_1QDEFAULT      /* 802.1Q priority for untagged packet*/     
+};
+
+
+enum RTL8306E_1QPRI
+{
+    RTL8306_1QTAG_PRIO0 = 0,
+    RTL8306_1QTAG_PRIO1,
+    RTL8306_1QTAG_PRIO2,
+    RTL8306_1QTAG_PRIO3,
+    RTL8306_1QTAG_PRIO4,
+    RTL8306_1QTAG_PRIO5,
+    RTL8306_1QTAG_PRIO6,
+    RTL8306_1QTAG_PRIO7,
+    RTL8306_1QTAG_END
+};
+
+enum RTL8306E_PRI
+{
+    RTL8306_PRIO0 = 0,
+    RTL8306_PRIO1,
+    RTL8306_PRIO2,
+    RTL8306_PRIO3,    
+    RTL8306_PRI_END
+};
+
+enum RTL8306E_SCHSET
+{
+    RTL8306_QOS_SET0 = 0, 
+    RTL8306_QOS_SET1        
+};
+
+enum RTL8306E_DSCPCODE
+{
+    RTL8306_DSCP_EF = 0,
+    RTL8306_DSCP_AFL1,
+    RTL8306_DSCP_AFM1,    
+    RTL8306_DSCP_AFH1,
+    RTL8306_DSCP_AFL2,
+    RTL8306_DSCP_AFM2,
+    RTL8306_DSCP_AFH2,
+    RTL8306_DSCP_AFL3,
+    RTL8306_DSCP_AFM3,
+    RTL8306_DSCP_AFH3,
+    RTL8306_DSCP_AFL4,
+    RTL8306_DSCP_AFM4,
+    RTL8306_DSCP_AFH4,
+    RTL8306_DSCP_NC,
+    RTL8306_DSCP_REG_PRI,
+    RTL8306_DSCP_BF       
+};
+
+#define RTL8306_DSCP_USERA        0
+#define RTL8306_DSCP_USERB        1
+#define RTL8306_IPADD_A 0
+#define RTL8306_IPADD_B 1
+
+#define RTL8306_FCO_SET0            0x0
+#define RTL8306_FCO_SET1            0x1
+#define RTL8306_FCOFF                 0x0
+#define RTL8306_FCON                   0x1
+#define RTL8306_FCO_DSC             0x0
+#define RTL8306_FCO_QLEN           0x1
+#define RTL8306_FCO_FULLTHR      0x0
+#define RTL8306_FCO_OVERTHR     0x1
+
+
+#define RTL8306_ACL_INVALID       0x6
+#define RTL8306_ACL_ANYPORT     0x7
+
+enum RTL8306E_ACLPRO
+{
+    RTL8306_ACL_ETHER = 0,
+    RTL8306_ACL_TCP,
+    RTL8306_ACL_UDP,
+    RTL8306_ACL_TCPUDP    
+};
+
+enum RTL8306E_MIBCNT
+{
+    RTL8306_MIB_CNT1 = 0,
+    RTL8306_MIB_CNT2,
+    RTL8306_MIB_CNT3,
+    RTL8306_MIB_CNT4,
+    RTL8306_MIB_CNT5 
+};
+
+enum RTL8306E_MIBOP
+{
+    RTL8306_MIB_RESET = 0, 
+    RTL8306_MIB_START        
+};
+
+#define RTL8306_MIB_BYTE            0
+#define RTL8306_MIB_PKT              1
+
+#define RTL8306_MIR_INVALID       0x6
+
+enum RTL8306E_LUT4WAY
+{
+    RTL8306_LUT_ENTRY0 = 0,
+    RTL8306_LUT_ENTRY1,
+    RTL8306_LUT_ENTRY2,
+    RTL8306_LUT_ENTRY3    
+};    
+
+#define RTL8306_LUT_FULL            -2  /*Four way of the same entry are all written by cpu*/
+#define RTL8306_LUT_NOTEXIST     -3
+
+enum RTL8306E_LUTAGE
+{
+    RTL8306_LUT_AGEOUT = 0,
+    RTL8306_LUT_AGE100 = 100,
+    RTL8306_LUT_AGE200 = 200,
+    RTL8306_LUT_AGE300 = 300   
+};
+
+#define RTL8306_LUT_DYNAMIC      0
+#define RTL8306_LUT_STATIC         1
+#define RTL8306_LUT_UNAUTH       0
+#define RTL8306_LUT_AUTH           1
+
+enum RTL8306E_SPAN_STATE
+{
+    RTL8306_SPAN_DISABLE = 0,
+    RTL8306_SPAN_BLOCK,
+    RTL8306_SPAN_LEARN,
+    RTL8306_SPAN_FORWARD  
+};
+
+enum RTL8306E_DOT1X_STATE
+{
+    RTL8306_PORT_UNAUTH = 0, 
+    RTL8306_PORT_AUTH
+};
+
+enum RTL8306E_DOT1X_PORT_DIR
+{
+    RTL8306_PORT_BOTHDIR = 0,
+    RTL8306_PORT_INDIR      
+};
+
+enum RTL8306E_DOT1X_MAC_DIR
+{
+    RTL8306_MAC_BOTHDIR = 0,
+    RTL8306_MAC_INDIR      
+};
+
+enum RTL8306E_ABNORMAL_PKT
+{
+    RTL8306_UNMATCHVID =0,
+    RTL8306_DOT1XUNAUTH
+};
+
+enum RTL8306E_RMA
+{
+    RTL8306_RESADDRXX = 0, /*reserved address 01-80-c2-00-00-xx (exclude 00, 01, 02, 03, 10, 20, 21) */
+    RTL8306_RESADDR21,       /*reserved address 01-80-c2-00-00-21*/        
+    RTL8306_RESADDR20,       /*reserved address 01-80-c2-00-00-20*/
+    RTL8306_RESADDR10,       /*reserved address 01-80-c2-00-00-10*/
+    RTL8306_RESADDR03,      /*reserved address 01-80-c2-00-00-03*/
+    RTL8306_RESADDR02,      /*reserved address 01-80-c2-00-00-02*/
+    RTL8306_RESADDR00,      /*reserved address 01-80-c2-00-00-00*/
+    RTL8306_RESADDR01     /*reserved address 01-80-c2-00-00-01*/
+};
+
+enum RTL8306E_PKT_TYPE
+{
+    RTL8306_UNICASTPKT = 0,  /*Unicast packet, but not include unknown DA unicast packet*/
+    RTL8306_BROADCASTPKT,   /*Broadcast packet*/
+    RTL8306_MULTICASTPKT,    /*Multicast packet*/
+    RTL8306_UDAPKT             /*Unknown DA unicast packet*/
+};
+
+
+/*Max packet length*/
+enum RTL8306E_PKT_LEN
+{
+    RTL8306_MAX_PKT_LEN_1518 = 0,  /*1518 bytes without any tag; 1522 bytes: with VLAN tag or CPU tag*/
+    RTL8306_MAX_PKT_LEN_1536,       /*1536 bytes*/
+    RTL8306_MAX_PKT_LEN_1552,       /*1552 bytes*/
+    RTL8306_MAX_PKT_LEN_2000       /*1552 bytes*/
+};
+
+enum RTL8306E_STORM_THR
+{
+    RTL8306_STM_FILNUM64  =  0,     /*64 pkts will trigger storm fileter*/
+    RTL8306_STM_FILNUM32,            /*32 pkts will trigger storm fileter*/
+    RTL8306_STM_FILNUM16,            /*16 pkts will trigger storm fileter*/
+    RTL8306_STM_FILNUM8,              /*8 pkts will trigger storm fileter*/
+    RTL8306_STM_FILNUM128,          /*128 pkts will trigger storm fileter*/
+    RTL8306_STM_FILNUM256,          /*256 pkts will trigger storm fileter*/
+    RTL8306_STM_FILNUM_END    
+};
+
+enum RTL8306E_STORM_TIMEWIN
+{
+    RTL8306_STM_FIL800MS = 0,       /*filter 800ms after trigger storm filter*/
+    RTL8306_STM_FIL400MS,            /*filter 400ms after trigger storm filter*/
+    RTL8306_STM_FIL200MS,            /*filter 200ms after trigger storm filter*/
+    RTL8306_STM_FIL100MS,            /*filter 100ms after trigger storm filter*/
+    RTL8306_STM_FILTIM_END
+};
+
+typedef enum rtl8306e_acceptFrameType_e
+{
+    RTL8306E_ACCEPT_ALL = 0,                   /* untagged, priority-tagged and tagged */
+    RTL8306E_ACCEPT_TAG_ONLY = 2,         /* tagged */
+    RTL8306E_ACCEPT_UNTAG_ONLY = 3 ,    /* untagged and priority-tagged */
+    RTL8306E_ACCEPT_TYPE_END
+} rtl8306e_acceptFrameType_t;
+
+typedef enum rtl8306e_vidSrc_e
+{
+    RTL8306E_VIDSRC_POVID = 0,              /*port-based outer tag vid*/
+    RTL8306E_VIDSRC_NVID,                     /* new vid translated*/
+    RTL8306E_VIDSRC_END    
+
+} rtl8306e_vidSrc_t;
+
+typedef enum rtl8306e_priSrc_e
+{
+    RTL8306E_PRISRC_PPRI = 0,              /*port-based outer tag priority*/
+    RTL8306E_PRISRC_1PRMK,                /* 1p remarking priority*/
+    RTL8306E_PRISRC_END
+} rtl8306e_priSrc_t;
+
+
+typedef struct rtl8306e_qosPriArbitPara_s 
+{
+    uint32 acl_pri_lev;
+    uint32 dscp_pri_lev;
+    uint32 dot1q_pri_lev;
+    uint32 port_pri_lev;
+    uint32 vid_pri_lev;
+} rtl8306e_qosPriArbitPara_t;
+
+typedef struct rtl8306e_qosSchPara_s
+{
+    uint8   q0_wt;
+    uint8   q1_wt;
+    uint8   q2_wt;
+    uint8   q3_wt;
+    uint16 q2_n64Kbps;
+    uint16 q3_n64Kbps;    
+
+} rtl8306e_qosSchPara_t;
+
+#ifdef RTL8306_LUT_CACHE
+#define RTL8306_MAX_LUT_NUM    2048
+typedef struct RTL8306_LUT_s
+{
+    uint8   mac[6];
+    union
+    {
+        struct 
+        {
+            uint8 auth;
+            uint8 isStatic;
+            uint8 spa;
+            uint8 age;
+            uint8 reserved;
+        } unicast;
+        struct 
+        {
+            uint8 auth;
+            uint8 portMask;
+            uint8 reserved;
+        } multicast;
+    }un;
+}RTL8306_LUT;
+#endif
+
+#ifdef RTL8306_TBLBAK
+typedef struct rtl8306_vlanConfigBakPara_s 
+{
+    uint8 enVlan;
+    uint8 enArpVlan;
+    uint8 enLeakVlan;
+    uint8 enVlanTagOnly;
+    uint8 enIngress;
+    uint8 enTagAware;
+    uint8 enIPMleaky;
+    uint8 enMirLeaky;
+} rtl8306_vlanConfigBakPara_t;
+
+typedef struct rtl8306_vlanConfigPerPortBakPara_s 
+{
+    uint8 vlantagInserRm;
+    uint8 en1PRemark;
+    uint8 enNulPvidRep;         
+} rtl8306_vlanConfigPerPortBakPara_t;
+
+typedef struct  rtl8306_vlanTblBakPara_s 
+{
+    uint16 vid;
+    uint8 memberPortMask;        
+} rtl8306_vlanTblBakPara_t;
+
+typedef struct rtl8306_aclTblBakPara_s 
+{
+    uint8 phy_port;
+    uint8 proto;
+    uint16 data;
+    uint8 action;
+    uint8 pri;
+} rtl8306_aclTblBakPara_t;
+
+typedef struct rtl8306_mirConfigBakPara_s
+{
+    uint8 mirPort;
+    uint8 mirRxPortMask;
+    uint8 mirTxPortMask;
+    uint8 enMirself;
+    uint8 enMirMac;
+    uint8 mir_mac[6];
+} rtl8306_mirConfigBakPara_t;
+    
+
+typedef struct rtl8306_ConfigBakPara_s  
+{
+    rtl8306_vlanConfigBakPara_t vlanConfig;                    /*VLAN global configuration*/
+    rtl8306_vlanConfigPerPortBakPara_t vlanConfig_perport[6];   /*VLAN per-port configuration*/
+    rtl8306_vlanTblBakPara_t vlanTable[16]; /*It backups VLAN table in cpu memory*/
+    uint8 vlanPvidIdx[6];   /*per-port PVID index*/                  
+    uint8 En1PremarkPortMask; /*Enable/disable 802.1P remarking  port mask */
+    uint8 dot1PremarkCtl[4]; /*802.1p remarking table*/
+    uint8 dot1DportCtl[6]; /*Spanning tree port state*/
+    rtl8306_aclTblBakPara_t aclTbl[16];         /*ACL table*/
+    rtl8306_mirConfigBakPara_t mir; /*mirror configuration*/                                                                         
+} rtl8306_ConfigBakPara_t;
+
+extern rtl8306_ConfigBakPara_t rtl8306_TblBak; 
+
+#endif
+
+
+#define RTL8306_GET_REG_ADDR(x, page, phy, reg) \
+    do { (page) = ((x) & 0xFF0000) >> 16; (phy) = ((x) & 0x00FF00) >> 8; (reg) = ((x) & 0x0000FF);\
+    } while(0) \
+
+/*compute look up table index of a mac addrees, LUT index : MAC[13:15] + MAC[0:5]*/
+#define RTL8306_MAC_INDEX(mac, index)    rtl8306e_l2_MacToIdx_get(mac, &index)
+
+
+/* Function Name:
+ *      rtl8306e_reg_set
+ * Description:
+ *      Write Asic Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      npage   - Specify page number (0 ~3)
+ *      value    - Value to be write into the register
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could write all configurable registers of RTL8306, 
+ *      it is realized by calling functions smiRead and smiWrite which are switch
+ *      MDC/MDIO interface access functions. Those two functions use two GPIO 
+ *      pins to simulate MDC/MDIO timing,  and they are based on rtl8651b platform,
+ *      to modify them,  you can port all asic API to other platform.
+ */
+extern int32 rtl8306e_reg_set(uint32 phyad, uint32 regad, uint32 npage, uint32 value) ;
+
+/* Function Name:
+ *      rtl8306e_reg_get
+ * Description:
+ *      Read Asic Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      npage   - Specify page number (0 ~3)
+ * Output:
+ *      pvalue    - The pointer of value read back from register
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could write all configurable registers of RTL8306, 
+ *      it is realized by calling functions smiRead and smiWrite which are switch
+ *      MDC/MDIO interface access functions. Those two functions use two GPIO 
+ *      pins to simulate MDC/MDIO timing,  and they are based on rtl8651b platform,
+ *      to modify them,  you can port all asic API to other platform.
+ */
+extern int32 rtl8306e_reg_get(uint32 phyad, uint32 regad, uint32 npage, uint32 *pvalue);
+
+/* Function Name:
+ *      rtl8306e_regbit_set
+ * Description:
+ *      Write one bit of Asic Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      bit        - Specify bit position(0 ~ 15)
+ *      npage   - Specify page number (0 ~3)
+ *      value    - Value to be write(0, 1)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function  you could write each bit of  all configurable registers of RTL8306.
+ */
+extern int32 rtl8306e_regbit_set(uint32 phyad, uint32 regad, uint32 bit, uint32 npage,  uint32 value);
+
+/* Function Name:
+ *      rtl8306e_regbit_get
+ * Description:
+ *      Read one bit of Asic  PHY Register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      bit        - Specify bit position(0 ~ 15)
+ *      npage   - Specify page number (0 ~3)
+ * Output:
+ *      pvalue  - The pointer of value read back
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could read each bit of  all configurable registers of RTL8306
+ */
+extern int32 rtl8306e_regbit_get(uint32 phyad, uint32 regad, uint32 bit, uint32 npage,  uint32 * pvalue) ;
+
+/* Function Name:
+ *      rtl8306e_phyReg_set
+ * Description:
+ *      Write PCS page register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      npage   - Specify page number (0 ~5)
+ *      value    - Value to be write into the register
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could write all configurable pcs registers of RTL8306, 
+ *      it is realized by calling functions smiRead and smiWrite which are switch
+ *      MDC/MDIO interface access functions. Those two functions use two GPIO 
+ *      pins to simulate MDC/MDIO timing,  and they are based on rtl8651b platform,
+ *      to modify them,  you can port all asic API to other platform.
+ */
+extern int32 rtl8306e_phyReg_set(uint32 phyad, uint32 regad, uint32 npage, uint32 value);
+
+/* Function Name:
+ *      rtl8306e_phyReg_get
+ * Description:
+ *      Read PCS page register
+ * Input:
+ *      phyad   - Specify Phy address (0 ~6)
+ *      regad    - Specify register address (0 ~31)
+ *      npage   - Specify page number (0 ~5)
+ * Output:
+ *      pvalue    - The pointer of value read back from register
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function you could write all configurable pcs registers of RTL8306, 
+ *      it is realized by calling functions smiRead and smiWrite which are switch
+ *      MDC/MDIO interface access functions. Those two functions use two GPIO 
+ *      pins to simulate MDC/MDIO timing,  and they are based on rtl8651b platform,
+ *      to modify them,  you can port all asic API to other platform.
+ */
+extern int32 rtl8306e_phyReg_get(uint32 phyad, uint32 regad, uint32 npage, uint32 *pvalue);
+
+extern int32 rtl8306e_asic_init(void);
+
+/* Function Name:
+ *      rtl8306e_phy_reset
+ * Description:
+ *      Reset the phy
+ * Input:
+ *      phy   - Specify Phy address (0 ~6)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+extern int32 rtl8306e_phy_reset(uint32 phy);
+
+/* Function Name:
+ *      rtl8306e_switch_maxPktLen_set
+ * Description:
+ *      set Max packet length which could be forwarded by
+ * Input:
+ *      maxLen         -  max packet length
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      maxLen could be set : 
+ *      RTL8306_MAX_PKT_LEN_1518 -1518 bytes without any tag; 1522 bytes: 
+ *              with VLAN tag or CPU tag, 1526 bytes with CPU and VLAN tag;
+ *      RTL8306_MAX_PKT_LEN_1536 - 1536 bytes (all tags counted);
+ *      RTL8306_MAX_PKT_LEN_1552 - 1552 bytes (all tags counted); 
+ *      RTL8306_MAX_PKT_LEN_2000 - 2000 bytes (all tags counted) 
+ *              
+ */ 
+extern int32 rtl8306e_switch_maxPktLen_set(uint32 maxLen);
+
+/* Function Name:
+ *      rtl8306e_switch_maxPktLen_get
+ * Description:
+ *      set Max packet length which could be forwarded by
+ * Input:
+ *      none
+ * Output:
+ *      maxLen         -  max packet length
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      maxLen could be set : 
+ *      RTL8306_MAX_PKT_LEN_1518 -1518 bytes without any tag; 1522 bytes: 
+ *              with VLAN tag or CPU tag, 1526 bytes with CPU and VLAN tag;
+ *      RTL8306_MAX_PKT_LEN_1536 - 1536 bytes (all tags counted);
+ *      RTL8306_MAX_PKT_LEN_1552 - 1552 bytes (all tags counted); 
+ *      RTL8306_MAX_PKT_LEN_2000 - 2000 bytes (all tags counted) 
+ *              
+ */ 
+extern int32 rtl8306e_switch_maxPktLen_get(uint32 *pMaxLen);
+
+/*
+  *  physical port function
+  */
+
+/* Function Name:
+ *      rtl8306e_port_etherPhy_set
+ * Description:
+ *      Configure PHY setting
+ * Input:
+ *      phy                    - Specify the phy to configure
+ *      autoNegotiation    - Specify whether enable auto-negotiation
+ *      advCapability       - When auto-negotiation is enabled, specify the advertised capability
+ *      speed                 - When auto-negotiation is disabled, specify the force mode speed
+ *      fullDuplex            - When auto-negotiatoin is disabled, specify the force mode duplex mode
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      When auto-negotiation is enabled, the advertisement capability is used to handshaking with link partner.
+ *      When auto-negotiation is disabled, the phy is configured into force mode and the speed and duplex mode 
+ *      setting is based on speed and fullDuplex setting.Port number should be smaller than RTL8306_PHY_NUMBER.
+ *      AdverCapability should be ranged between RTL8306_ETHER_AUTO_100FULL and RTL8306_ETHER_AUTO_10HALF.
+ *      Speed should be either RTL8306_ETHER_SPEED_100 or RTL8306_ETHER_SPEED_10.
+ */
+
+extern int32 rtl8306e_port_etherPhy_set(uint32 phy, uint32 autoNegotiation, uint32 advCapability, uint32 speed, uint32 fullDuplex) ;
+
+/* Function Name:
+ *      rtl8306e_port_etherPhy_get
+ * Description:
+ *       Get PHY setting
+ * Input:
+ *      phy                    - Specify the phy to configure
+ * Output:
+ *      pAutoNegotiation    - Get whether auto-negotiation is enabled
+ *      pAdvCapability       - When auto-negotiation is enabled, Get the advertised capability
+ *      pSpeed                 - When auto-negotiation is disabled, Get the force mode speed
+ *      pFullDuplex            - When auto-negotiatoin is disabled, Get the force mode duplex mode
+
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      When auto-negotiation is enabled, the advertisement capability is used to handshaking with link partner.
+ *      When auto-negotiation is disabled, the phy is configured into force mode and the speed and duplex mode 
+ *      setting is based on speed and fullDuplex setting.Port number should be smaller than RTL8306_PHY_NUMBER.
+ *      AdverCapability should be ranged between RTL8306_ETHER_AUTO_100FULL and RTL8306_ETHER_AUTO_10HALF.
+ *      Speed should be either RTL8306_ETHER_SPEED_100 or RTL8306_ETHER_SPEED_10.
+ */
+extern int32 rtl8306e_port_etherPhy_get(uint32 phy, uint32 *pAutoNegotiation, uint32 *pAdvCapability, uint32 *pSpeed, uint32 *pFullDuplex);
+
+/* Function Name:
+ *      rtl8306e_port_port5LinkStatus_set
+ * Description:
+ *      Force port 5 link up or link down
+ * Input:
+ *      enabled   - true or false
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Port 5 should be manully enable / disable
+ */
+extern int32 rtl8306e_port_port5LinkStatus_set(uint32 enabled) ;
+
+/* Function Name:
+ *      rtl8306e_port_port5LinkStatus_get
+ * Description:
+ *      get port 5 link status
+ * Input:
+ *      none
+ * Output:
+*      enabled   - true or false
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Port 5 should be manully enable / disable
+ */
+extern int32 rtl8306e_port_port5LinkStatus_get(uint32 *pEnabled);
+
+/* Function Name:
+ *      rtl8306e_port_phyLinkStatus_get
+ * Description:
+ *      Get PHY Link Status
+ * Input:
+*      phy        - Specify the phy 
+ * Output:
+*      plinkUp   - Describe whether link status is up or not
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       Read the link status of PHY register 1
+ */
+extern int32 rtl8306e_port_phyLinkStatus_get(uint32 phy, uint32 *plinkUp);
+
+/* Function Name:
+ *      rtl8306e_port_phyAutoNegotiationDone_get
+ * Description:
+ *      Get PHY auto-negotiation result status
+ * Input:
+ *      phy      - Specify the phy to get status
+ * Output:
+*      pDone   -  Describe whether auto-negotiation is done or not
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Read the auto-negotiation complete of PHY register 1.
+ */
+
+extern int32 rtl8306e_port_phyAutoNegotiationDone_get(uint32 phy, uint32 *pDone) ;
+
+/* Function Name:
+ *      rtl8306e_port_phyLoopback_set
+ * Description:
+ *       Set PHY loopback
+ * Input:
+ *      phy         - Specify the phy to configure
+ *      enabled   - Enable phy loopback
+ * Output:
+ *      none      
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Only phy 0~4 could be configured the phy loopback
+ */
+extern int32 rtl8306e_port_phyLoopback_set(uint32 phy, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_port_phyLoopback_get
+ * Description:
+ *      Get PHY loopback setting
+ * Input:
+ *      phy         - Specify the phy to get status
+ * Output:
+ *      pEnabled  -  phy loopback setting
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+extern int32 rtl8306e_port_phyLoopback_get(uint32 phy, uint32 *pEnabled) ;
+
+/* Function Name:
+ *      rtl8306e_portLearningAbility_set
+ * Description:
+ *      Enable/disable physical port learning ability
+ * Input:
+ *      port        - Specify port number (0 ~ 5)
+ * Output:
+ *      enabled -  TRUE or FALSE
+ * Return:
+ *      SUCCESS
+ * Note:
+ *
+ */
+extern int32 rtl8306e_portLearningAbility_set(uint32 port, uint32 enabled);
+
+
+/* Function Name:
+ *      rtl8306e_port_isolation_set
+ * Description:
+ *      set port isolation 
+ * Input:
+ *      isomsk    - port isolation port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each bit of isomsk determine two port's isolation,
+ *      1 means two port could not forward packet between
+ *      each other.
+ *      bit 0  - Port0 & Port1 
+ *      bit 1  - Port0 & Port2 
+ *      bit 2  - Port0 & Port3
+ *      bit 3  - Port0 & Port4
+ *      bit 4  - Port0 & Port5
+ *      bit 5  - Port1 & Port2
+ *      bit 6  - Port1 & Port3
+ *      bit 7  - Port1 & Port4
+ *      bit 8  - Port1 & Port5
+ *      bit 9  - Port2 & Port3
+ *      bit 10 - Port2 & Port4
+ *      bit 11 - Port2 & Port5
+ *      bit 12 - Port3 & Port4
+ *      bit 13 - Port3 & Port5
+ *      bit 14 - Port4 & Port5
+ */
+extern int32 rtl8306e_port_isolation_set(uint32 isomsk);
+
+/* Function Name:
+ *      rtl8306e_port_isolation_set
+ * Description:
+ *      set port isolation 
+ * Input:
+ *      none
+ * Output:
+ *      pIsomsk    -  the pointer of port isolation port mask
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each bit of isomsk determine two port's isolation,
+ *      1 means two port could not forward packet between
+ *      each other.
+ *      bit 0  - Port0 & Port1 
+ *      bit 1  - Port0 & Port2 
+ *      bit 2  - Port0 & Port3
+ *      bit 3  - Port0 & Port4
+ *      bit 4  - Port0 & Port5
+ *      bit 5  - Port1 & Port2
+ *      bit 6  - Port1 & Port3
+ *      bit 7  - Port1 & Port4
+ *      bit 8  - Port1 & Port5
+ *      bit 9  - Port2 & Port3
+ *      bit 10 - Port2 & Port4
+ *      bit 11 - Port2 & Port5
+ *      bit 12 - Port3 & Port4
+ *      bit 13 - Port3 & Port5
+ *      bit 14 - Port4 & Port5
+ */
+extern int32 rtl8306e_port_isolation_get(uint32 *pIsomsk);
+
+/*
+  *  VLAN function
+  */
+
+/* Function Name:
+ *      rtl8306e_vlan_tagAware_set
+ * Description:
+ *      Configure switch to be VLAN tag awared
+ * Input:
+ *      enabled  - Configure RTL8306 VLAN tag awared
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If switch is unawared VLAN tag, packet with vlan tag is treated as untagged pkt
+ *      and assigned PVID as VID.
+ */
+extern int32 rtl8306e_vlan_tagAware_set(uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_vlan_tagAware_set
+ * Description:
+ *      Get switch to be VLAN tag awared  or not
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled  - the pointer of RTL8306 VLAN tag awared status
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If switch is unawared VLAN tag, packet with vlan tag is treated as untagged pkt
+ *      and assigned PVID as VID.
+ */
+extern int32 rtl8306e_vlan_tagAware_get(uint32 * pEnabled);
+
+/* Function Name:
+ *      rtl8306e_vlan_IgrFilterEnable_set
+ * Description:
+ *      Configure VLAN ingress filter
+ * Input:
+ *      enabled  - enable or disable
+ * Output:
+ *      none 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+extern int32 rtl8306e_vlan_IgrFilterEnable_set(uint32 enabled); 
+
+/* Function Name:
+ *      rtl8306e_vlan_IgrFilterEnable_get
+ * Description:
+ *      Get VLAN ingress filter enabled or disabled
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled  - enable or disable
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *
+ */
+extern int32 rtl8306e_vlan_IgrFilterEnable_get(uint32 *pEnabled); 
+
+/* Function Name:
+ *      rtl8306e_vlan_leaky_set
+ * Description:
+ *      Configure switch to forward frames to other VLANs ignoring the egress rule.
+ * Input:
+ *      type   -  vlan leaky type
+ *      enabled  - enable or disable
+ * Output:
+ *      none 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_VALN_LEAKY_UNICAST - Vlan leaky for unicast pkt
+ *          RTL8306_VALN_LEAKY_MULTICAST - Vlan leaky for multicast pkt
+ *          RTL8306_VALN_LEAKY_ARP - Vlan leaky for ARP brodcast pkt 
+ *          RTL8306_VALN_LEAKY_MIRROR - Vlan leaky for mirror function
+ *    1.When the Vlan leaky for unicast pkt is enabled, it enables the inter-VLANs unicast packet forwarding. 
+ *    That is, if the L2 look up MAC table search hit, then the unicast packet will be forwarded
+ *    to the egress port ignoring the egress rule.
+ *    2.When Vlan leaky for multicast pkt is enabled, multicast packet may be flood to all multicast address
+ *    group member set, ignoring the VLAN member set domain limitation.
+ *    3.When Vlan leaky for ARP pkt is enabled, the ARP broadcast packets will be forward to all the other
+ *    ports ignoring the egress rule.
+ *    4.When Vlan leaky for mirror function is enabled, it enables the inter-VLANs mirror function, 
+ *    ignoring the VLAN member set domain limitation.
+ */
+extern int32 rtl8306e_vlan_leaky_set(uint32 type, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_vlan_leaky_get
+ * Description:
+ *      Get switch whether forwards unicast frames to other VLANs
+ * Input:
+ *      type   -  vlan leaky type
+ * Output:
+ *      pEnabled  - the pointer of Vlan Leaky status(Dsiabled or Enabled) 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *   type coulde be:
+ *          RTL8306_VALN_LEAKY_UNICAST - Vlan leaky for unicast pkt
+ *          RTL8306_VALN_LEAKY_MULTICAST - Vlan leaky for multicast pkt
+ *          RTL8306_VALN_LEAKY_ARP - Vlan leaky for ARP brodcast pkt 
+ *    1.When the Vlan leaky for unicast pkt is enabled, it enables the inter-VLANs unicast packet forwarding. 
+ *    That is, if the L2 look up MAC table search hit, then the unicast packet will be forwarded
+ *    to the egress port ignoring the egress rule.
+ *    2.When Vlan leaky for multicast pkt is enabled, multicast packet may be flood to all multicast address
+ *    group member set, ignoring the VLAN member set domain limitation.
+ *    3.When Vlan leaky for ARP pkt is enabled, the ARP broadcast packets will be forward to all the other
+ *    ports ignoring the egress rule.
+ *    4.When Vlan leaky for mirror function is enabled, it enables the inter-VLANs mirror function, 
+ *    ignoring the VLAN member set domain limitation.
+ */
+extern int32 rtl8306e_vlan_leaky_get(uint32 type, uint32 *pEnabled);
+
+/* Function Name:
+ *      rtl8306e_vlan_nullVidReplace_set
+ * Description:
+ *      Configure switch to replace Null VID tagged frame by PVID if it is tag aware
+ * Input:
+ *      port   -  port number
+ *      enabled  - enable or disable
+ * Output:
+ *      none 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.When Null VID replacement is enabled, 8306E only captures tagged packet with VID=0,
+ *      then replace VID with input port's PVID. If switch received a packet that is not tagged, 
+ *      it will not insert a tag with PVID to this packet.
+ *      2. When Null VID replacement is disabled, switch will drop or deal the null VID tagged 
+ *      frame depends on the configuration.
+ */
+extern int32 rtl8306e_vlan_nullVidReplace_set(uint32 port, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_vlan_nullVidReplace_get
+ * Description:
+ *      Configure switch to forward frames to other VLANs ignoring the egress rule.
+ * Input:
+ *      port   -  port number
+ * Output:
+ *      pEnabled  - the pointer of Null VID replacement ability(Dsiabled or Enabled) 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.When Null VID replacement is enabled, 8306E only captures tagged packet with VID=0,
+ *      then replace VID with input port's PVID. If switch received a packet that is not tagged, 
+ *      it will not insert a tag with PVID to this packet.
+ *      2. When Null VID replacement is disabled, switch will drop or deal the null VID tagged 
+ *      frame depends on the configuration.
+ */
+extern int32 rtl8306e_vlan_nullVidReplace_get(uint32 port, uint32 *pEnabled);
+
+/* Function Name:
+ *      rtl8306e_vlan_portPvidIndex_set
+ * Description:
+ *      Configure switch port PVID index 
+ * Input:
+ *      port           -   Specify the port(port 0 ~ port 5) to configure VLAN index
+ *      vlanIndex    -   Specify the VLAN index
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 16 vlan entry, VID of vlan entry pointed by PVID index  is the PVID 
+ */
+
+extern int32 rtl8306e_vlan_portPvidIndex_set(uint32 port, uint32 vlanIndex);
+
+/* Function Name:
+ *      rtl8306e_vlan_portPvidIndex_get
+ * Description:
+ *      Get switch port PVID index 
+ * Input:
+ *      port            -   Specify the port(port 0 ~ port 5) to configure VLAN index
+ * Output:
+ *      pVlanIndex   -   pointer of VLAN index number
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 16 vlan entry, VID of vlan entry pointed by PVID index  is the PVID 
+ */
+
+extern int32 rtl8306e_vlan_portPvidIndex_get(uint32 port, uint32 *pVlanIndex);
+
+/* Function Name:
+ *      rtl8306e_vlan_portAcceptFrameType_set
+ * Description:
+ *      Set VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ *      accept_frame_type             - accept frame type
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *    The API is used for checking 802.1Q tagged frames.
+ *    The accept frame type as following:
+ *    RTL8306E_ACCEPT_ALL
+ *    RTL8306E_ACCEPT_TAG_ONLY
+ *    RTL8306E_ACCEPT_UNTAG_ONLY
+ */
+extern int32 rtl8306e_vlan_portAcceptFrameType_set(uint32 port, rtl8306e_acceptFrameType_t accept_frame_type);
+
+/* Function Name:
+ *      rtl8306e_vlan_portAcceptFrameType_get
+ * Description:
+ *      Get VLAN support frame type
+ * Input:
+ *      port                                 - Port id
+ * Output:
+ *      pAccept_frame_type             - accept frame type pointer
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *    The API is used for checking 802.1Q tagged frames.
+ *    The accept frame type as following:
+ *    RTL8306E_ACCEPT_ALL
+ *    RTL8306E_ACCEPT_TAG_ONLY
+ *    RTL8306E_ACCEPT_UNTAG_ONLY
+ */
+extern int32 rtl8306e_vlan_portAcceptFrameType_get(uint32 port, rtl8306e_acceptFrameType_t *pAccept_frame_type);
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsert_set
+ * Description:
+ *      Insert VLAN tag by ingress port
+ * Input:
+ *      egPort               - egress port number 0~5
+ *      igPortMsk           - ingress port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      egPort is packet egress port, if the packet is untagged and its igress port
+ *      is in the igPortMsk, it will be inserted with an VLAN tag.
+ */
+extern int32 rtl8306e_vlan_tagInsert_set(uint32 egPort, uint32 igPortMsk);
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsert_get
+ * Description:
+ *      get  ingress port mask of VLAN tag insertion for untagged packet
+ * Input:
+ *      egPort               - egress port number 0~5
+ *      igPortMsk           - ingress port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      egPort is packet egress port, if the packet is untagged and its igress port
+ *      is in the igPortMsk, it will be inserted with an VLAN tag.
+ */
+extern int32 rtl8306e_vlan_tagInsert_get(uint32 egPort, uint32 * pIgPortMsk);
+
+/*added by Fan Kaixi, 2012-01-18*/
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsertRemove_set
+ * Description:
+ *      set per port vlan tag action
+ * Input:
+ *      Port               - egress port number 0~5
+ *      option              - action options, insert/remove/replace/untouch
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      port is egress port number from 0 to 5. option is the action the egress
+ *      port will take on packets tx from itself.
+ *      option have values as follows:
+ *          RTL8306_VLAN_IRTAG = 0  ---  insert tag for untagged packets, remove tag from tagged packets and add new tag to it
+ *          RTL8306_VLAN_RTAG,      ---  remove tag from tagged packets, don't touch untagged packets                 
+ *          RTL8306_VLAN_ITAG,      ---  insert tag for untagged packets, don't touch tagged packets       
+ *          RTL8306_VLAN_UNDOTAG    ---  don't touch tag for packets 
+ *      when egress port decide to insert tag for untagged packets, the tag vid is derived from packets'
+ *      ingress port pvid.
+*/
+extern int32 rtl8306e_vlan_tagInsertRemove_set(uint32 egport, uint32 option);
+
+/* Function Name:
+ *      rtl8306e_vlan_tagInsertRemove_get
+ * Description:
+ *      get per port vlan tag action
+ * Input:
+ *      Port               - egress port number 0~5
+ * Output:
+ *      pOption              - action options, insert/remove/replace/untouch
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      port is egress port number from 0 to 5. option is the action the egress
+ *      port will take on packets tx from itself.
+ *      option have values as follows:
+ *          RTL8306_VLAN_IRTAG = 0  ---  insert tag for untagged packets, remove tag from tagged packets and add new tag to it
+ *          RTL8306_VLAN_RTAG,      ---  remove tag from tagged packets, don't touch untagged packets                 
+ *          RTL8306_VLAN_ITAG,      ---  insert tag for untagged packets, don't touch tagged packets       
+ *          RTL8306_VLAN_UNDOTAG    ---  don't touch tag for packets 
+ *      when egress port decide to insert tag for untagged packets, the tag vid is derived from packets'
+ *      ingress port pvid.
+*/
+extern int32 rtl8306e_vlan_tagInsertRemove_get(uint32 egport, uint32 *pOption);
+
+/* Function Name:
+ *      rtk_vlan_set
+ * Description:
+ *      Set a VLAN entry
+ * Input:
+ *      vlanIndex  - VLAN entry index
+ *      vid           - VLAN ID to configure
+ *      mbrmsk     - VLAN member set portmask
+ *      untagmsk  - VLAN untag set portmask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ */
+extern int32 rtl8306e_vlan_entry_set(uint32 vlanIndex, uint32 vid, uint32 mbrmsk, uint32 untagmsk );
+
+/* Function Name:
+ *      rtl8306e_vlan_entry_get
+ * Description:
+ *      Get a VLAN entry
+ * Input:
+ *      vlanIndex  - VLAN entry index
+ * Output:
+ *      pVid           -  the pointer of VLAN ID 
+ *      pMbrmsk     -  the pointer of VLAN member set portmask
+ *      pUntagmsk  -  the pointer of VLAN untag set portmask
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 16 VLAN entry supported. User could configure the member set and untag set
+ *     for specified vid through this API. The portmask's bit N means port N.
+ *     For example, mbrmask 23=0x17=010111 means port 0,1,2,4 in the member set.
+ */
+extern int32 rtl8306e_vlan_entry_get(uint32 vlanIndex, uint32 *pVid, uint32 *pMbrmsk, uint32 *pUntagmsk);
+
+/* Function Name:
+ *      rtl8306e_vlan_vlanBasedPriority_set
+ * Description:
+ *       Set VID based priority
+ * Input:
+ *      vlanIndex   -   Specify VLAN entry index
+ *      pri            -   the specified VLAN priority  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each VLAN could be assigned an priority. if vlanIndex > 15, it means the VID
+ *      is not in VLAN entries, unmatched VID could also be assigned an priority.
+ *       
+ */
+extern int32 rtl8306e_vlan_vlanBasedPriority_set(uint32 vlanIndex, uint32 pri);
+
+/* Function Name:
+ *      rtl8306e_vlan_vlanBasedPriority_get
+ * Description:
+ *       Get VID based priority
+ * Input:
+ *      vlanIndex   -   Specify VLAN entry index
+ * Output:
+ *      pPri           -   the pointer of specified VLAN priority  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      each VLAN could be assigned an priority. if vlanIndex > 15, it means the VID
+ *      is not in VLAN entries, unmatched VID could also be assigned an priority.
+ *       
+ */
+extern int32 rtl8306e_vlan_vlanBasedPriority_get(uint32 vlanIndex, uint32 *pPri);
+
+/* Function Name:
+ *      rtl8306e_vlan_transEnable_set
+ * Description:
+ *      Enable VLAN translation 
+ * Input:
+ *      enable       -   enable or disable VLAN translation
+ *      portmask    -   NNI port is set 1 and UNI port is set 0
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Only the traffic between NNI port and UNI port will be change with VID,
+ *      the VLAN tranlation function and Q-in-Q(SVLAN) could not be enabled  
+ *      at the same time, user should choose one of them. 
+ */
+extern int32 rtl8306e_vlan_transEnable_set(uint32 enable, uint32 portmask);
+
+/* Function Name:
+ *      rtl8306e_vlan_transEnable_get
+ * Description:
+ *      Get VLAN translation setting
+ * Input:
+ *      none
+ * Output:
+ *      pEnable       -   the pointer of enable or disable VLAN translation
+ *      pPortMask    -   the pointer of VLAN translation port mask
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Only the traffic between NNI port and UNI port will be change with VID,
+ *      the VLAN tranlation function and Q-in-Q(SVLAN) could not be enabled  
+ *      at the same time, user should choose one of them. 
+ */
+extern int32 rtl8306e_vlan_transEnable_get(uint32 *pEnable, uint32 *pPortMask);
+
+/* Function Name:
+ *      rtl8306e_vlan_transparentEnable_set
+ * Description:
+ *      Enable VLAN transparent 
+ * Input:
+ *      enable       -   enable or disable VLAN transparent
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+extern int32 rtl8306e_vlan_transparentEnable_set(uint32 enable);
+
+/* Function Name:
+ *      rtl8306e_vlan_transVid_set
+ * Description:
+ *      Set the translated VID
+ * Input:
+ *      vlanIndex   -   the VLAN entry index
+ *      transVid     -   the new VID
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      The VID in the entry indexed by vlanIndex will be replaced with
+ *      new VID.
+ */ 
+extern int32 rtl8306e_vlan_transVid_set(uint32 vlanIndex, uint32 transVid);
+
+
+/* Function Name:
+ *      rtl8306e_vlan_transVid_get
+ * Description:
+ *      Get the translated VID
+ * Input:
+ *      vlanIndex   -   the VLAN entry index
+ * Output:
+ *      pTransVid   -   the pointer of the new VID
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      The VID in the entry indexed by vlanIndex will be replaced with
+ *      new VID.
+ */ 
+extern int32 rtl8306e_vlan_transVid_get(uint32 vlanIndex, uint32 *pTransVid);
+
+
+/* Function Name:
+ *      rtl8306e_svlan_tagAdmit_set
+ * Description:
+ *      Set Q-in-Q tag admit control
+ * Input:
+ *      port          -   port id
+ *      enable       -   enable tag admit control 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       
+ */
+extern int32 rtl8306e_svlan_tagAdmit_set(uint32 port, uint32 enable);
+
+/* Function Name:
+ *      rtl8306e_svlan_tagAdmit_get
+ * Description:
+ *      Get Q-in-Q tag admit control
+ * Input:
+ *      port          -   port id
+ * Output:
+ *      pEnable     -   the pointer of enable tag admit control 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       
+ */
+extern int32 rtl8306e_svlan_tagAdmit_get(uint32 port, uint32 *pEnable);
+
+/* Function Name:
+ *      rtl8306e_svlan_otagSrc_set
+ * Description:
+ *      Set how to decide outer tag vid and priority 
+ * Input:
+ *      port          -   port id
+ *      ovidSrc      -   ovid comes from
+ *      opriSrc      -    opri comes from 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       ovidSrc RTL8306E_VIDSRC_POVID : ovid is port-based ovid,    RTL8306E_VIDSRC_NVID:ovid is new vid(translated vid)
+ *       opriSrc  RTL8306E_PRISRC_PPRI   : opri is port-based priority, RTL8306E_PRISRC_1PRMK: opri is 1p remarking value
+ */
+extern int32 rtl8306e_svlan_otagSrc_set(uint32 port, uint32 ovidSrc, uint32 opriSrc);
+
+/* Function Name:
+ *      rtl8306e_svlan_otagSrc_get
+ * Description:
+ *      Get how to decide outer tag vid and priority 
+ * Input:
+ *      port            -   port id
+ * Output:
+ *      pOvidsrc      -   the pointer of ovid comes from
+ *      pOpriSrc      -   the pointer of opri comes from 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *       ovidSrc RTL8306E_VIDSRC_POVID : ovid is port-based ovid,    RTL8306E_VIDSRC_NVID:ovid is new vid(translated vid)
+ *       opriSrc  RTL8306E_PRISRC_PPRI   : opri is port-based priority, RTL8306E_PRISRC_1PRMK: opri is 1p remarking value
+ */
+extern int32 rtl8306e_svlan_otagSrc_get(uint32 port, uint32 *pOvidsrc, uint32 *pOpriSrc);
+
+/* Function Name:
+ *      rtl8306e_cpu_set
+ * Description:
+ *       Specify Asic CPU port 
+ * Input:
+ *      port       -   Specify the port
+ *      enTag    -    CPU tag insert or not
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If the port is specified RTL8306_NOCPUPORT, it means
+ *      that no port is assigned as cpu port
+ */
+extern int32 rtl8306e_cpu_set(uint32 port, uint32 enTag) ;
+
+/* Function Name:
+ *      rtl8306e_cpu_set
+ * Description:
+ *       Get Asic CPU port number
+ * Input:
+ *      none
+ * Output:
+ *      pPort     - the pointer of CPU port number
+ *      pEnTag  - the pointer of CPU tag insert or not
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      If the port is specified RTL8306_NOCPUPORT, it means
+ *      that no port is assigned as cpu port
+ */
+
+extern int32 rtl8306e_cpu_get(uint32 *pPort, uint32 *pEnTag) ;
+
+/* Function Name:
+ *      rtl8306e_cpu_doubleTagInsert_set
+ * Description:
+ *      Enable synchronously insertting cpu tag and vlan tag ability
+ * Input:
+ *      enabled     -   enable or disable
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      This API can be called to enable synchronously insertting cpu tag and vlan tag ability.
+*/
+extern int32 rtl8306e_cpu_doubleTagInsert_set(uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_cpu_doubleTagInsert_get
+ * Description:
+ *      Get Enabled status of synchronously insertting cpu tag and vlan tag ability
+ * Input:
+ *      none
+ * Output:
+ *      pEnabled    -   enable or disable
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      This API can be called to enable synchronously insertting cpu tag and vlan tag ability.
+*/
+extern int32 rtl8306e_cpu_doubleTagInsert_get(uint32 *pEnabled);
+
+/*
+  *  QOS  function
+  */
+
+/* Function Name:
+ *      rtl8306e_qos_softReset_set
+ * Description:
+ *      Software reset the asic
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      reset packet buffer.
+ */
+extern int32 rtl8306e_qos_softReset_set(void) ;
+
+/* Function Name:
+ *      rtl8306e_qos_queueNum_set
+ * Description:
+ *      Set egress port queue number (1 ~4)
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Queue number is global configuration for switch.
+ */
+extern int32 rtl8306e_qos_queueNum_set(uint32 num);
+
+/* Function Name:
+ *      rtl8306e_qos_queueNum_set
+ * Description:
+ *      Set egress port queue number (1 ~4)
+ * Input:
+ *      none
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Queue number is global configuration for switch.
+ */
+extern int32 rtl8306e_qos_queueNum_get(uint32 *pNum) ;
+
+/* Function Name:
+ *      rtl8306e_qos_priToQueMap_set
+ * Description:
+ *     Set priority to Queue ID mapping
+ * Input:
+ *      priority   -  priority value (0 ~ 3)
+ *      qid        -  Queue id (0~3)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Packets could be classified into specified queue through their priority. 
+ *      we can use this function to set pkt priority with queue id mapping
+ */
+extern int32 rtl8306e_qos_priToQueMap_set(uint32 priority, uint32 qid) ;
+
+/* Function Name:
+ *      rtl8306e_qos_priToQueMap_get
+ * Description:
+ *      Get priority to Queue ID mapping
+ * Input:
+ *      priority   -  priority value (0 ~ 3)
+ * Output:
+ *      pQid      -  pointer of Queue id (0~3)
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Packets could be classified into specified queue through their priority. 
+ *      we can use this function to set pkt priority with queue id mapping
+ */
+extern int32 rtl8306e_qos_priToQueMap_get(uint32 priority, uint32 *pQid) ;
+
+/* Function Name:
+ *      rtl8306e_qos_portRate_set
+ * Description:
+ *      Set port bandwidth control
+ * Input:
+ *      port            -  port number (0~5)
+ *      n64Kbps       -  Port rate (0~1526), unit 64Kbps
+ *      direction      -  Ingress or Egress bandwidth control
+ *      enabled       -  enable bandwidth control
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      For each port, both input and output bandwidth could be configured, 
+ *      RTL8306_PORT_RX represents port input bandwidth control, 
+ *      RTL8306_PORT_TX represents port output bandwidth control.
+ *      port rate unit is 64Kbps. For output rate control, enable/disable 
+ *      is configured per port, but for input rate control, it is for all port.
+ */
+extern int32 rtl8306e_qos_portRate_set(uint32 port, uint32 n64Kbps, uint32 direction, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_qos_portRate_get
+ * Description:
+ *      Get port bandwidth control rate
+ * Input:
+ *      port                 -  Port number (0~5)
+ * Output:
+ *      *pN64Kbps        -  Port rate (0~1526), unit 64Kbps
+ *      direction           -  Input or output bandwidth control
+ *      *enabled           -  enabled or disabled bandwidth control
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      For each port, both input and output bandwidth could be configured, 
+ *      RTL8306_PORT_RX represents port input bandwidth control, 
+ *      RTL8306_PORT_TX represents port output bandwidth control.
+ *      port rate unit is 64Kbps. For output rate control, enable/disable 
+ *      is configured per port, but for input rate control, it is for all port.
+ */
+extern int32 rtl8306e_qos_portRate_get(uint32 port, uint32 *pN64Kbps, uint32 direction, uint32 *pEnabled);
+
+/* Function Name:
+ *      rtl8306e_qos_1pRemarkEnable_set
+ * Description:
+ *      Set 802.1P remarking ability
+ * Input:
+ *      port       -  port number (0~5)
+ *      enabled  -  TRUE or FALSE
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      
+ */
+extern int32 rtl8306e_qos_1pRemarkEnable_set(uint32 port, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_qos_1pRemarkEnable_set
+ * Description:
+ *      Get 802.1P remarking ability
+ * Input:
+ *      port        -  port number (0~5)
+ * Output:
+ *      pEnabled  -  pointer of the ability status
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      
+ */
+extern int32 rtl8306e_qos_1pRemarkEnable_get(uint32 port, uint32 *pEnabled) ;
+
+/* Function Name:
+ *      rtl8306e_qos_1pRemark_set
+ * Description:
+ *      Set 802.1P remarking priority
+ * Input:
+ *      priority       -  Packet priority(0~4)
+ *      priority1p    -  802.1P priority(0~7)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+extern int32 rtl8306e_qos_1pRemark_set(uint32 priority, uint32 priority1p);
+
+/* Function Name:
+ *      rtl8306_getAsic1pRemarkingPriority
+ * Description:
+ *      Get 802.1P remarking priority
+ * Input:
+ *      priority       -  Packet priority(0~4)
+ * Output:
+ *      pPriority1p  -  the pointer of 802.1P priority(0~7)
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch determines packet priority, the priority souce could
+ *      be port-based, 1Q-based, dscp-based, vid-based, ip address,
+ *      cpu tag.
+ */
+extern int32 rtl8306e_qos_1pRemark_get(uint32 priority, uint32 *pPriority1p);
+
+/* Function Name:
+ *      rtl8306e_qos_portPri_set
+ * Description:
+ *      Set port-based priority
+ * Input:
+ *      port          -  port number (0~5)
+ *      priority      -  Packet port-based priority(0~4)
+ * Output:
+*       none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      packet will be assigned a port-based priority correspond to the ingress port.
+ */
+extern int32 rtl8306e_qos_portPri_set(uint32 port, uint32 priority);
+
+/* Function Name:
+ *      rtl8306e_qos_portPri_get
+ * Description:
+ *      Get port-based priority
+ * Input:
+ *      port          -  port number (0~5)
+ * Output:
+ *      pPriority    -   pointer of packet port-based priority(0~4)
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      packet will be assigned a port-based priority correspond to the ingress port.
+ */ 
+extern int32 rtl8306e_qos_portPri_get(uint32 port, uint32 *pPriority);
+
+/* Function Name:
+ *      rtl8306e_qos_1pPriRemap_set
+ * Description:
+ *      Set Asic 1Q-tag priority mapping to 2-bit priority
+ * Input:
+ *      tagprio  -  1Q-tag proirty (0~7, 3 bit value)
+ *      prio      -   internal use 2-bit priority
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch internal use 2-bit priority, so it should map 3-bit 1Q-tag priority
+ *      to 2-bit priority
+ */ 
+extern int32 rtl8306e_qos_1pPriRemap_set(uint32 tagprio, uint32 prio) ;
+
+/* Function Name:
+ *      rtl8306e_qos_1pPriRemap_get
+ * Description:
+ *      Get Asic 1Q-tag priority mapping to 2-bit priority
+ * Input:
+ *      tagprio  -  1Q-tag proirty (0~7, 3 bit value)
+ * Output:
+ *      pPrio     -  pointer of  internal use 2-bit priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch internal use 2-bit priority, so it should map 3-bit 1Q-tag priority
+ *      to 2-bit priority
+ */ 
+extern int32 rtl8306e_qos_1pPriRemap_get(uint32 tagprio, uint32 *pPrio);
+
+/* Function Name:
+ *      rtl8306e_dscpPriRemap_set
+ * Description:
+ *      Set DSCP-based priority
+ * Input:
+ *      code      -  dscp code
+ *      priority   -  dscp-based priority
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *     
+ */ 
+extern int32 rtl8306e_qos_dscpPriRemap_set(uint32 code, uint32 priority) ;
+
+/* Function Name:
+ *      rtl8306e_dscpPriRemap_set
+ * Description:
+ *      Get DSCP-based priority
+ * Input:
+ *      code      -  dscp code
+ * Output:
+ *      pPriority  -  the pointer of dscp-based priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch support 16 kinds of dscp code:
+ *          RTL8306_DSCP_EF          
+ *                 - DSCP for the Expedited forwarding PHB, 101110   
+ *          RTL8306_DSCP_AFL1         
+ *                 - DSCP for AF PHB Class 1 low drop, 001010
+ *          RTL8306_DSCP_AFM1     
+ *                 - DSCP for AF PHB Class 1 medium drop, 001100
+ *          RTL8306_DSCP_AFH1      
+ *                 - DSCP for AF PHB Class 1 high drop, 001110
+ *          RTL8306_DSCP_AFL2       
+ *                 - DSCP for AF PHB Class 2 low drop, 01001
+ *          RTL8306_DSCP_AFM2       
+ *                 - DSCP for AF PHB Class 2 medium drop, 010100
+ *          RTL8306_DSCP_AFH2   
+ *                 - DSCP for AF PHB Class 2 high drop, 010110
+ *          RTL8306_DSCP_AFL3    
+ *                 - DSCP for AF PHB Class 3 low drop, 011010
+ *          RTL8306_DSCP_AFM3      
+ *                 - DSCP for AF PHB Class 3 medium drop, 011100
+ *          RTL8306_DSCP_AFH3    
+ *                 - DSCP for AF PHB Class 3 high drop, 0111
+ *          RTL8306_DSCP_AFL4     
+ *                 - DSCP for AF PHB Class 4 low drop, 100010
+ *          RTL8306_DSCP_AFM4    
+ *                 - DSCP for AF PHB Class 4 medium drop, 100100
+ *          RTL8306_DSCP_AFH4     
+ *                 - DSCP for AF PHB Class 4 high drop, 100110
+ *          RTL8306_DSCP_NC        
+ *                 - DSCP for network control, 110000 or 111000
+ *          RTL8306_DSCP_REG_PRI 
+ *                 - DSCP Register match priority, user could define two dscp code
+ *          RTL8306_DSCP_BF        
+ *                 - DSCP Default PHB
+ *     
+ */ 
+extern int32 rtl8306e_qos_dscpPriRemap_get(uint32 code, uint32 *pPriority);
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcArbit_set
+ * Description:
+ *      Set priority source arbitration level
+ * Input:
+ *      priArbit  - The structure describe levels of 5 kinds of priority 
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch could recognize 7 types of priority source at most, 
+ *      and a packet properly has all of them. among them, there 
+ *      are 5 type priorities could be set priority level, they are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority,
+ *      Port-based priority, VID- based priority.each one could be 
+ *      set level from 0 to 5, arbitration module will decide their sequece 
+ *      to take, the highest level priority will be adopted at first, 
+ *      then  priority type of the sencond highest level. priority with level 0
+ *      will not be recognized any more. 
+ */
+extern int32 rtl8306e_qos_priSrcArbit_set(rtl8306e_qosPriArbitPara_t priArbit);
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcArbit_get
+ * Description:
+ *      Get priority source arbitration level
+ * Input:
+ *      none 
+ * Output:
+ *      pPriArbit  - The structure describe levels of 5 kinds of priority 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch could recognize 7 types of priority source at most, 
+ *      and a packet properly has all of them. among them, there 
+ *      are 5 type priorities could be set priority level, they are 
+ *      ACL-based  priority, DSCP-based priority, 1Q-based priority,
+ *      Port-based priority, VID- based priority.each one could be 
+ *      set level from 0 to 5, arbitration module will decide their sequece 
+ *      to take, the highest level priority will be adopted at first, 
+ *      then  priority type of the sencond highest level. priority with level 0
+ *      will not be recognized any more. 
+ */
+extern int32 rtl8306e_qos_priSrcArbit_get(rtl8306e_qosPriArbitPara_t *pPriArbit);
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcEnable_set
+ * Description:
+ *      enable/disable Qos priority source for  ingress port
+ * Input:
+ *      port      -  Specify port number (0 ~5)
+ *      priSrc    -  Specify priority source  
+ *      enabled -   TRUE of FALSE  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 kind of priority source for each port which could
+ *     be enabled ordisabled:
+ *          RTL8306_DSCP_PRIO     - DSCP-based priority
+ *          RTL8306_1QBP_PRIO     - 1Q-based priority
+ *          RTL8306_PBP_PRIO        - port-based priority
+ *          RTL8306_CPUTAG_PRIO  - cpu tag priority
+ */
+extern int32 rtl8306e_qos_priSrcEnable_set(uint32 port, uint32 priSrc, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_qos_priSrcEnable_set
+ * Description:
+ *      enable/disable Qos priority source for  ingress port
+ * Input:
+ *      port       -  Specify port number (0 ~5)
+ *      priSrc     -  Specify priority source  
+ * Output:
+ *      pEnabled -  the pointer of priority source status  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 kind of priority source for each port which could
+ *     be enabled ordisabled:
+ *          RTL8306_DSCP_PRIO     - DSCP-based priority
+ *          RTL8306_1QBP_PRIO     - 1Q-based priority
+ *          RTL8306_PBP_PRIO        - port-based priority
+ *          RTL8306_CPUTAG_PRIO  - cpu tag priority
+ */
+extern int32 rtl8306e_qos_priSrcEnable_get(uint32 port, uint32 priSrc, uint32 *pEnabled);
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddrPri_set
+ * Description:
+ *      Set IP address priority
+ * Input:
+ *      priority  -  internal use 2-bit priority value (0~3)  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+extern int32 rtl8306e_qos_ipAddrPri_set(uint32 priority); 
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddrPri_get
+ * Description:
+ *      Get IP address priority
+ * Input:
+ *      priority  -  internal use 2-bit priority value (0~3)  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+extern int32 rtl8306e_qos_ipAddrPri_get(uint32 *priority);
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddr_set
+ * Description:
+ *      Set IP address
+ * Input:
+ *      entry        -   specify entry
+         ip            -   ip address
+         mask        -  ip mask
+         enabled    -   enable the entry
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are two entries RTL8306_IPADD_A and RTL8306_IPADD_B
+ *      for user setting ip address, if ip address of packet matches
+ *      the entry, the packet will be assign the priority of ip address
+ *      priority which is configured by rtl8306e_qos_ipAddrPri_set.
+ */
+extern int32 rtl8306e_qos_ipAddr_set(uint32 entry, uint32 ip, uint32 mask, uint32 enabled);
+
+/* Function Name:
+ *      rtl8306e_qos_ipAddr_get
+ * Description:
+ *      Get IP address user seting
+ * Input:
+ *      entry       -   specify entry
+ * Output:
+ *      pIp            -   ip address
+         pMask        -   ip mask
+         pEnabled    -  enabled or disabled the entry for IP Priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+extern int32 rtl8306e_qos_ipAddr_get(uint32 entry, uint32 *pIp, uint32 *pMask , uint32 *pEnabled); 
+
+/* Function Name:
+ *      rtl8306e_qos_schedulingPara_set
+ * Description:
+ *      Set qos scheduling parameter
+ * Input:
+ *      set          -  RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ *      sch_para  -  The structure describe schedule parameter
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch supports 4 queue per egress port, scheduling algorithm could be WRR(Weight Round Robin) or 
+ *      SP(Strict Priority). Only high queue Q3 and Q2 could be set as strict priority queue. There two set of 
+ *      scheduling parameter in whole system(RTL8306_QOS_SET0/RTL8306_QOS_SET1), each egress port select
+ *      one of them. The parameter defined by rtl8306e_qosSchPara_t, q0_wt and q1_wt should between 1~127,
+ *      that means Q0 and Q1 WRR weight, q2_wt and  q3_wt could be 0~127, 0 means strict priority. q2_n64Kbps 
+ *      and q3_n64Kbps means Q2/Q3 queue bandwidth control, unit is 64Kbps.
+ */
+extern int32 rtl8306e_qos_schedulingPara_set(uint32 set, rtl8306e_qosSchPara_t sch_para);
+
+/* Function Name:
+ *      rtl8306e_qos_schedulingPara_get
+ * Description:
+ *      Set qos scheduling parameter
+ * Input:
+ *      set           -  RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ * Output:
+ *      pSch_para  - the pointer of schedule parameter
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      switch supports 4 queue per egress port, scheduling algorithm could be WRR(Weight Round Robin) or 
+ *      SP(Strict Priority). Only high queue Q3 and Q3 could be set as strict priority queue. There two set of 
+ *      scheduling parameter in whole system(RTL8306_QOS_SET0/RTL8306_QOS_SET1), each egress port select
+ *      one of them. The parameter defined by rtl8306e_qosSchPara_t, q0_wt and q1_wt should between 1~127,
+ *      that means Q0 and Q1 WRR weight, q2_wt and  q3_wt could be 0~127, 0 means strict priority. q2_n64Kbps 
+ *      and q3_n64Kbps means Q2/Q3 queue bandwidth control, unit is 64Kbps.
+ */
+extern int32 rtl8306e_qos_schedulingPara_get(uint32 set, rtl8306e_qosSchPara_t *pSch_para);
+
+/* Function Name:
+ *      rtl8306e_qos_portSchedulingMode_set
+ * Description:
+ *      Select port schedule algorithm  from two sets.
+ * Input:
+ *      port    -   port number (0 ~ 5)
+ *      set     -   RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ *      lbmsk  -   Queue mask for enable queue leaky buckt
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are two sets configuration for schedule mode including strict priority 
+ *      enable/disable, queue weight and queue leaky bucket, every port could select
+ *      one of them. Queue leaky bucket of each port could be enable separately, so 
+ *      you can set queue mask to enable/disable them, because only queue 3 and queue 2
+ *      have leaky bucket, only bit 3 and bit 2 of quemask have effect, bit 3 represents
+ *      queue 3 and set 1 to enable it.
+ */
+extern int32 rtl8306e_qos_portSchedulingMode_set(uint32 port, uint32 set, uint32 lbmsk);
+
+/* Function Name:
+ *      rtl8306e_qos_portSchedulingMode_get
+ * Description:
+ *      Get which set of schedule algorithm  for the specified port 
+ * Input:
+ *      port    -   port number (0 ~ 5)
+ *      set     -   RTL8306_QOS_SET0 or RTL8306_QOS_SET1
+ *      lbmsk  -   Queue mask for enable queue leaky buckt
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are two sets configuration for schedule mode including strict priority 
+ *      enable/disable, queue weight and queue leaky bucket, every port could select
+ *      one of them. Queue leaky bucket of each port could be enable separately, so 
+ *      you can set queue mask to enable/disable them, because only queue 3 and queue 2
+ *      have leaky bucket, only bit 3 and bit 2 of quemask have effect, bit 3 represents
+ *      queue 3 and set 1 to enable it.
+ */
+extern int32 rtl8306e_qos_portSchedulingMode_get(uint32 port, uint32 *pSet, uint32 *pLbmsk);
+extern int32 rtl8306e_qos_queFlcThr_set(uint32 queue, uint32 type, uint32 onoff, uint32 set, uint32 value);
+extern int32 rtl8306e_qos_queFlcThr_get(uint32 queue, uint32 type, uint32 onoff, uint32 set, uint32* pValue);
+extern int32 rtl8306e_qos_portFlcThr_set(uint32 port, uint32 onthr, uint32 offthr, uint32 direction );
+extern int32 rtl8306e_qos_portFlcThr_get(uint32 port, uint32 *pOnthr, uint32 *pOffthr, uint32 direction);
+extern int32 rtl8306e_qos_queFlcEnable_set( uint32 port, uint32 queue, uint32 enabled);
+extern int32 rtl8306e_qos_queFlcEnable_get(uint32 port, uint32 queue, uint32 *pEnabled);
+
+
+/*
+  *  ACL  function
+  */
+
+/* Function Name:
+ *      rtl8306e_acl_entry_set
+ * Description:
+ *      Set Asic ACL table
+ * Input:
+ *      entryadd   - Acl entry address (0~15)
+ *      phyport    -  Acl physical port
+ *      action      -  Acl action 
+ *      protocol   -  Acl protocol
+ *      data        -  ether type value or TCP/UDP port
+ *      priority     -  Acl priority
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      phyport could be 
+ *            0~5:       port number, 
+ *            RTL8306_ACL_INVALID: invalid entry,
+ *            RTL8306_ACL_ANYPORT: any port.
+ *      Acl action could be
+ *          RTL8306_ACT_DROP,
+ *          RTL8306_ACT_PERMIT, 
+ *          RTL8306_ACT_TRAPCPU, 
+ *          RTL8306_ACT_MIRROR
+ *      Acl protocol could be
+ *          RTL8306_ACL_ETHER(ether type), 
+ *          RTL8306_ACL_TCP(TCP), 
+ *          RTL8306_ACL_UDP(UDP),
+ *          RTL8306_ACL_TCPUDP(TCP or UDP)
+ *
+ *      Acl priority:
+ *          RTL8306_PRIO0~RTL8306_PRIO3
+ *       
+ */
+extern int32 rtl8306e_acl_entry_set(uint32 entryadd, uint32 phyport, uint32 action, uint32 protocol, uint32 data, uint32 priority) ;
+
+/* Function Name:
+ *      rtl8306e_acl_entry_get
+ * Description:
+ *      Get Asic ACL entry
+ * Input:
+ *      entryadd   - Acl entry address (0~15)
+ * Output:
+ *      pPhyport    -  Acl physical port 
+ *      pAction      -  Acl action 
+ *      pProtocol   -  Acl protocol
+ *      pData        -  ether type value or TCP/UDP port
+ *      pPriority     -  Acl priority
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      phyport could be 
+ *            0~5:       port number, 
+ *            RTL8306_ACL_INVALID: invalid entry,
+ *            RTL8306_ACL_ANYPORT: any port.
+ *      Acl action could be
+ *          RTL8306_ACT_DROP,
+ *          RTL8306_ACT_PERMIT, 
+ *          RTL8306_ACT_TRAPCPU, 
+ *          RTL8306_ACT_MIRROR
+ *      Acl protocol could be
+ *          RTL8306_ACL_ETHER(ether type), 
+ *          RTL8306_ACL_TCP(TCP), 
+ *          RTL8306_ACL_UDP(UDP),
+ *          RTL8306_ACL_TCPUDP(TCP or UDP)
+ *
+ *      Acl priority:
+ *          RTL8306_PRIO0~RTL8306_PRIO3
+ *       
+ */
+extern int32 rtl8306e_acl_entry_get(uint32 entryadd, uint32 *pPhyport, uint32 *pAction, uint32 *pProtocol, uint32  *pData, uint32 *pPriority);
+
+/*
+  *  Mib  function
+  */
+
+/* Function Name:
+ *      rtl8306e_mib_get
+ * Description:
+ *      enable/disable Qos priority source for  ingress port
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ *      counter    -  Specify counter type  
+ * Output:
+ *      pEnabled -  the pointer of priority source status  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are five MIB counter for each port, they are:
+ *      RTL8306_MIB_CNT1 - TX count
+ *      RTL8306_MIB_CNT2 - RX count
+ *      RTL8306_MIB_CNT3 - RX Drop Count<nl>
+ *      RTL8306_MIB_CNT4 - RX CRC error Count
+ *      RTL8306_MIB_CNT5 - RX Fragment Count<nl>
+ */
+extern int32 rtl8306e_mib_get(uint32 port, uint32 counter, uint32 *pValue); 
+
+/* Function Name:
+ *      rtl8306e_mibUnit_set
+ * Description:
+ *      Set RX/Tx Mib counting unit: byte or packet
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ *      counter    -  Specify counter type  
+ *      uint         -  Specify counting unit
+ * Output:
+ *      none  
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.There are five MIB counter for each port, they are:
+ *      RTL8306_MIB_CNT1 - TX count
+ *      RTL8306_MIB_CNT2 - RX count
+ *      RTL8306_MIB_CNT3 - RX Drop Count<nl>
+ *      RTL8306_MIB_CNT4 - RX CRC error Count
+ *      RTL8306_MIB_CNT5 - RX Fragment Count<nl>
+ *      2.Only RTL8306_MIB_CNT1 and RTL8306_MIB_CNT2 could set counting unit  
+ *      RTL8306_MIB_PKT or RTL8306_MIB_BYTE, default is RTL8306_MIB_PKT.
+ *      the other counters' counting uint is RTL8306_MIB_PKT
+ */
+extern int32 rtl8306e_mibUnit_set(uint32 port, uint32 counter, uint32 unit);
+
+/* Function Name:
+ *      rtl8306e_mibUnit_get
+ * Description:
+ *      Get Rx/Tx Mib counting unit
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ *      counter    -  Specify counter type  
+ * Output:
+ *      pUnit         -  the pointer of counting unit
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      1.There are five MIB counter for each port, they are:
+ *      RTL8306_MIB_CNT1 - TX count
+ *      RTL8306_MIB_CNT2 - RX count
+ *      RTL8306_MIB_CNT3 - RX Drop Count<nl>
+ *      RTL8306_MIB_CNT4 - RX CRC error Count
+ *      RTL8306_MIB_CNT5 - RX Fragment Count<nl>
+ *      2.Only RTL8306_MIB_CNT1 and RTL8306_MIB_CNT2 could set counting unit  
+ *      RTL8306_MIB_PKT or RTL8306_MIB_BYTE, default is RTL8306_MIB_PKT.
+ *      the other counters' counting uint is RTL8306_MIB_PKT
+ */
+extern int32 rtl8306e_mibUnit_get(uint32 port, uint32 counter, uint32 *pUnit);
+
+/* Function Name:
+ *      rtl8306e_mib_reset
+ * Description:
+ *      reset MIB counter
+ * Input:
+ *      port         -  port number (0 ~ 5)
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ */
+extern int32 rtl8306e_mib_reset(uint32 port);
+
+/*
+  *  mirror  function
+  */
+
+/* Function Name:
+ *      rtl8306e_mirror_portBased_set
+ * Description:
+ *      Set asic Mirror port
+ * Input:
+ *      mirport         -  Specify mirror port 
+ *      rxmbr           -  Specify Rx mirror port mask
+ *      txmbr           -  Specify Tx mirror port mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      mirport could be 0 ~ 5, represent physical port number, 
+ *      7 means that no port has mirror ability. rxmbr and txmbr
+ *      is 6 bit value, each bit corresponds one port. ingress packet
+ *      of port in rxmbr will be mirrored to mirport, egress packet 
+ *      of port in txmbr will be mirrored to mirport.
+ */
+extern int32 rtl8306e_mirror_portBased_set(uint32 mirport, uint32 rxmbr, uint32 txmbr) ;
+
+/* Function Name:
+ *      rtl8306e_mirror_portBased_get
+ * Description:
+ *      Get asic Mirror port
+ * Input:
+ *      none 
+ * Output:
+ *      pMirport     -  the pointer of mirror port
+ *      pRxmbr       -  the pointer of  Rx mirror port mask
+ *      pTxmbr       -  the pointer of Tx mirror port mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      mirport could be 0 ~ 5, represent physical port number, 
+ *      7 means that no port has mirror ability. rxmbr and txmbr
+ *      is 6 bit value, each bit corresponds one port. ingress packet
+ *      of port in rxmbr will be mirrored to mirport, egress packet 
+ *      of port in txmbr will be mirrored to mirport.
+ */
+
+extern int32 rtl8306e_mirror_portBased_get(uint32 *pMirport, uint32 *pRxmbr, uint32* pTxmbr);
+
+/*
+  *  L2 table  function
+  */
+
+/* Function Name:
+ *      rtl8306e_l2_MacToIdx_get
+ * Description:
+ *      get L2 table hash value from mac address
+ * Input:
+ *      macAddr        -  mac address
+ * Output:
+ *      pIndex           -  mac address table index   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      when a mac address is learned into mac address table, 
+ *      9 bit index value is got from the mac address by hashing 
+ *      algorithm, each index corresponds to 4 entry, it means
+ *      the table could save 4 mac addresses at the same time
+ *      whose index value is equal, so switch mac address table 
+ *      has 2048 entry. the API could get hash index from 
+ *      a specified mac address.
+ */
+extern int32 rtl8306e_l2_MacToIdx_get(uint8 *macAddr, uint32* pIndex);
+
+/* Function Name:
+ *      rtl8306e_l2_unicastEntry_set
+ * Description:
+ *      write an unicast mac address into L2 table
+ * Input:
+ *      macAddress        -  Specify the unicast Mac address(6 bytes) to be written into LUT
+ *      entry                 -  Specify the 4-way entry to be written (0~3)
+ *      age                   -  Specify age time
+ *      isStatic              -  TRUE(static entry), FALSE(dynamic entry)
+ *      isAuth                -  Whether the mac address is authorized by IEEE 802.1x
+ *      port                  -   Specify the port number to be forwarded to  
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :
+ *          RTL8306_LUT_AGEOUT, 
+ *          RTL8306_LUT_AGE100(100s)
+ *          RTL8306_LUT_AGE200(200s)
+ *          RTL8306_LUT_AGE300(300s)
+ */ 
+extern int32 rtl8306e_l2_unicastEntry_set(uint8 *macAddress, uint32 entry, uint32 age, uint32 isStatic, uint32 isAuth, uint32 port); 
+
+/* Function Name:
+ *      rtl8306e_l2_unicastEntry_get
+ * Description:
+ *      read an unicast mac address into L2 table
+ * Input:
+ *      entry               -  Specify the entry address to be read (0 ~ 2047), not four-way entry
+ * Output:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      pAge               -  the pointer of the age time
+ *      pIsStatic         -   the pointer of static or dynamic entry
+ *      pIsAuth           -   the pointer of IEEE 802.1x authorized status
+ *      pPort              -   the pointer of the port the mac belongs to   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :
+ *          RTL8306_LUT_AGEOUT
+ *          RTL8306_LUT_AGE100(100s)
+ *          RTL8306_LUT_AGE200(200s)
+ *          RTL8306_LUT_AGE300(300s)
+ */ 
+extern int32 rtl8306e_l2_unicastEntry_get(uint8 *macAddress, uint32 entryAddr, uint32 *pAge, uint32 *pIsStatic, uint32 *pIsAuth, uint32 *pPort) ;
+
+/* Function Name:
+ *      rtl8306e_l2_multicastEntry_set
+ * Description:
+ *      write an multicast mac address into L2 table
+ * Input:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      entry               -  Specify the 4-way entry to be written (0~3)
+ *      isAuth              -  IEEE 802.1x authorized status
+ *      portMask          -  switch received thepacket with the specified macAddress, 
+ *                                and forward it to the member port of portMask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      get 9-bit as index value of lookup table by hashing the mac address , for each index value, 
+ *      there are 4-entry to save hash collision mac address, thus there are 2048 entries all together.
+ *      the entry could save both unicast multicast mac address.  multicast entry has no age time and
+ *      static bit, which has been set by software, unicast entry could be both auto learned and set by 
+ *      software. you had better set isAuth TRUE for general application because  IEEE 802.1x is usually
+ *      for unicast packet.portMask is 6-bit value, each bit represents one port, bit 0 corresponds to port 0
+ *      and bit 5 corresponds port 5.
+ */ 
+
+extern int32 rtl8306e_l2_multicastEntry_set(uint8 *macAddress, uint32 entry, uint32 isAuth, uint32 portMask);
+
+/* Function Name:
+ *      rtl8306_getAsicLUTMulticastEntry
+ * Description:
+ *      Get LUT multicast entry
+ * Input:
+ *      entryAddr         -  Specify the LUT entry address(0~2047)
+
+ * Output:
+ *      macAddress      -  The read out multicast Mac address  
+ *      pIsAuth            -  the pointer of IEEE 802.1x authorized status
+ *      portMask          -  port mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Get multicast entry
+ */ 
+extern int32 rtl8306e_l2_multicastEntry_get(uint8 *macAddress, uint32 entryAddr, uint32 *pIsAuth, uint32 *pPortMask);
+
+/* Function Name:
+ *      rtl8306e_l2_unicastMac_add
+ * Description:
+ *     Add an unicast mac address, software will detect empty entry
+ * Input:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      age                 -  Specify age time
+ *      isStatic            -  TRUE(static entry), FALSE(dynamic entry)
+ *      isAuth              -  IEEE 802.1x authorized status
+ *      port                 -  the port which the mac address belongs to  
+ * Output:
+ *      pEntryaddr        -   the entry address (0 ~2047) which the unicast mac address is written into
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :RTL8306_LUT_AGEOUT, RTL8306_LUT_AGE100(100s), 
+ *      RTL8306_LUT_AGE200(200s), RTL8306_LUT_AGE300(300s)
+ *      The lut has a 4-way entry of an index. If the macAddress has existed in the lut, it will update the entry,
+ *      otherwise the function will find an empty entry to put it.
+ *      When the index is full, it will find a dynamic & unauth unicast macAddress entry to replace with it. 
+ *      If the mac address has been written into LUT, function return value is SUCCESS,  *pEntryaddr is recorded the 
+ *      entry address of the Mac address stored.
+ *      If all the four entries can not be replaced, it will return a  RTL8306_LUT_FULL error, you can delete one of them 
+ *      and rewrite the unicast address.  
+ */ 
+extern int32 rtl8306e_l2_unicastMac_add(uint8 *macAddress, uint32 age, uint32 isStatic, uint32 isAuth, uint32 port, uint32 *pEntryaddr);
+
+/* Function Name:
+ *      rtl8306e_l2_multicastMac_add
+ * Description:
+ *     Add an multicast mac address, software will detect empty entry
+ * Input:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      isAuth              -  IEEE 802.1x authorized status
+ *      portMask          -  switch received thepacket with the specified macAddress, 
+ *                                and forward it to the member port of portMask
+ * Output:
+ *      pEntryaddr        -   the entry address (0 ~2047) which the multicast mac address is written into
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      add an multicast entry, it need not specify the 4-way like function rtl8306e_l2_multicastEntry_set,
+ *      if the mac address has written into LUT, function return value is SUCCESS,  *pEntryaddr is recorded the 
+ *      entry address of the Mac address stored, if  4-way entries are all written by cpu, this mac address could 
+ *      not written into LUT and the function return value is  RTL8306_LUT_FULL, but if the Mac address has exist, 
+ *      the port mask will be updated. When function return value is RTL8306_LUT_FULL, you can delete one of them 
+ *      and rewrite the multicast address. 
+ */ 
+extern int32 rtl8306e_l2_multicastMac_add(uint8 *macAddr,uint32 isAuth, uint32 portMask, uint32 *pEntryaddr);
+
+/* Function Name:
+ *      rtl8306e_l2_mac_get
+ * Description:
+ *      Get an mac address information
+ * Input:
+ *      macAddress         -   the mac to be find in LUT  
+ * Output:
+ *      pIsStatic             -   the pointer of static or dynamic entry, for unicast mac address
+ *      pIsAuth               -   the pointer of IEEE 802.1x authorized status
+ *      pPortInfo             -   for unicast mac, it is the pointer of the port the mac belongs to;
+ *                                    for multicast mac, it is the pointer of portmask the mac forwarded to;
+ *      pEntryaddr           -   the entry address (0 ~2047) which the mac address is written into
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ *      RTL8306_LUT_NOTEXIST
+ * Note:
+ *      use this API to get a mac address information in LUT.
+ */ 
+extern int32 rtl8306e_l2_mac_get(uint8 *macAddr, uint32 *pIsStatic, uint32 *pIsAuth, uint32 *pPortInfo, uint32 *pEntryaddr); 
+
+/* Function Name:
+ *      rtl8306e_l2_mac_del
+ * Description:
+ *     Delete the specified Mac address, could be both unicast and multicast 
+ * Input:
+ *      macAddress      -  the Mac address(unicast or multicast) to be delete  
+ *                                and forward it to the member port of portMask
+ * Output:
+ *      pEntryaddr        -  entry address from which the Mac address is deleted
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Use this function to delete a Mac address, it does not require to specify the 
+ *      entry address, if the Mac has existed in the LUT, it will be deleted and function
+ *      return value is SUCCESS, *pEntryaddr is recorded the entry address of the Mac 
+ *      address stored. if the Mac does not existed in the LUT, function return value is
+ *      RTL8306_LUT_NOTEXIST, and *pEntryaddr equals 10000.
+ */ 
+
+extern int32 rtl8306e_l2_mac_del(uint8 *macAddr, uint32 *pEntryaddr);
+extern int32 rtl8306e_l2_portMacLimit_set(uint32 port, uint32 enabled, uint32 macCnt) ;
+extern int32 rtl8306e_l2_portMacLimit_get(uint32 port, uint32 *pEnabled, uint32 *pMacCnt);
+extern int32 rtl8306e_l2_systemMacLimit_set(uint32 enabled, uint32 macCnt, uint32 mergMask);
+extern int32 rtl8306e_l2_systemMacLimit_get(uint32 *pEnabled, uint32 *pMacCnt, uint32 *pMergMask); 
+extern int32 rtl8306e_l2_macLimitAction_set(uint32 action); 
+extern int32 rtl8306e_l2_macLimitAction_get(uint32 *pAction);
+
+#ifdef RTL8306_LUT_CACHE
+/* Function Name:
+ *      rtl8306e_l2_unicastEntry_get
+ * Description:
+ *      Get LUT unicast entry from software
+ * Input:
+ *      entryAddr         -  Specify the entry address to be read (0 ~ 2047), not four-way entry
+ * Output:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      pAge               -  the pointer of the age time
+ *      pIsStatic         -   the pointer of static or dynamic entry
+ *      pIsAuth           -   the pointer of IEEE 802.1x authorized status
+ *      pPort              -   the pointer of the port the mac belongs to   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      Age time has 4 value :
+ *          RTL8306_LUT_AGEOUT
+ *          RTL8306_LUT_AGE100(100s)
+ *          RTL8306_LUT_AGE200(200s)
+ *          RTL8306_LUT_AGE300(300s)
+ */ 
+extern int32 rtl8306e_fastGetAsicLUTUnicastEntry(uint8 *macAddress, uint32 entryAddr, uint32 *age, uint32 *isStatic, uint32 *isAuth, uint32 *port);
+
+/* Function Name:
+ *      rtl8306e_fastGetAsicLUTMulticastEntry
+ * Description:
+ *      Get LUT multicast entry from software
+ * Input:
+ *      entryAddr         -  Specify the entry address to be read (0 ~ 2047), not four-way entry
+ * Output:
+ *      macAddress      -  the mac to be saved in the entry  
+ *      pIsAuth           -   the pointer of IEEE 802.1x authorized status
+ *      pPort              -   the pointer of the port the mac belongs to   
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      portMask is 6-bit value, each bit represents one port, bit 0 corresponds to port 0 
+ *      and bit 5 corresponds port 5.    
+ */ 
+extern int32 rtl8306e_fastGetAsicLUTMulticastEntry(uint8 *macAddress, uint32 entryAddr, uint32 *isAuth, uint32 *portMask);
+
+#endif
+/*
+  *  Spanning Tree  function
+  */
+
+/* Function Name:
+ *      rtl8306e_stp_set
+ * Description:
+ *      Set IEEE 802.1d port state
+ * Input:
+ *      port   -  Specify port number (0 ~ 5)
+ *      state -   Specify port state
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 port state:
+ *         RTL8306_SPAN_DISABLE   - Disable state
+ *         RTL8306_SPAN_BLOCK      - Blocking state
+ *         RTL8306_SPAN_LEARN      - Learning state
+ *         RTL8306_SPAN_FORWARD - Forwarding state
+ */ 
+extern int32 rtl8306e_stp_set(uint32 port, uint32 state) ;
+
+/* Function Name:
+ *      rtl8306e_stp_get
+ * Description:
+ *      Get IEEE 802.1d port state
+ * Input:
+ *      port    -  Specify port number (0 ~ 5)
+ * Output:
+ *      pState -  get port state
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are 4 port state:
+ *         RTL8306_SPAN_DISABLE   - Disable state
+ *         RTL8306_SPAN_BLOCK      - Blocking state
+ *         RTL8306_SPAN_LEARN      - Learning state
+ *         RTL8306_SPAN_FORWARD - Forwarding state
+ */ 
+extern int32 rtl8306e_stp_get(uint32 port, uint32 *pState) ;
+
+/*
+  *  802.1x  function
+  */
+
+/* Function Name:
+ *      rtl8306e_dot1x_portBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ *      enabled    -   enable port-based access control
+ *      isAuth      -   Authorized or unauthorized state 
+ *      direction   -    set IEEE802.1x port-based control direction
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are two IEEE802.1x port state:
+ *         RTL8306_PORT_AUTH      - authorized
+ *         RTL8306_PORT_UNAUTH  - unauthorized
+ *
+ *     There are also two 802.1x port-based control direction:
+ *         RTL8306_PORT_BOTHDIR - if port-base access control is enabled, 
+ *                                              forbid forwarding this port's traffic to unauthorized port
+ *         RTL8306_PORT_INDIR     - if port-base access control is enabled, permit forwarding this
+ *                                              port's traffic to unauthorized port
+ */ 
+extern int32 rtl8306e_dot1x_portBased_set(uint32 port, uint32 enabled, uint32 isAuth, uint32 direction);
+
+/* Function Name:
+ *      rtl8306e_dot1x_portBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ * Output:
+ *      pEnabled    - the pointer of port-based access control status
+ *      pIsAuth      - the pointer of authorized or unauthorized state 
+ *      pDirection   - the pointer of IEEE802.1x port-based control direction
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     There are two IEEE802.1x port state:
+ *         RTL8306_PORT_AUTH      - authorized
+ *         RTL8306_PORT_UNAUTH  - unauthorized
+ *
+ *     There are also two 802.1x port-based control direction:
+ *         RTL8306_PORT_BOTHDIR - if port-base access control is enabled, 
+ *                                              forbid forwarding this port's traffic to unauthorized port
+ *         RTL8306_PORT_INDIR     - if port-base access control is enabled, permit forwarding this
+ *                                              port's traffic to unauthorized port
+ */ 
+extern int32 rtl8306e_dot1x_portBased_get(uint32 port, uint32 *pEnabled, uint32 *pIsAuth, uint32 *pDirection) ;
+
+/* Function Name:
+ *      rtl8306e_dot1x_macBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ * Output:
+ *      enabled    - Enable the port Mac-based access control ability
+ *      direction   -  IEEE802.1x mac-based access control direction
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      the mac address authentication status is saved in L2 table entry,
+ *      it should be set by software.
+ *      there are also two mac-based control directions which are not per 
+ *      port but global configurtion:
+ *      RTL8306_MAC_BOTHDIR - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will be dropped.
+ *      RTL8306_MAC_INDIR   - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will pass mac-based access control igress rule.
+ */ 
+
+extern int32 rtl8306e_dot1x_macBased_set(uint32 port, uint32 enabled, uint32 direction);
+
+/* Function Name:
+ *      rtl8306e_dot1x_macBased_set
+ * Description:
+ *      Set IEEE802.1x port-based access control
+ * Input:
+ *      port         -  Specify port number (0 ~ 5)
+ * Output:
+ *      enabled    - Enable the port Mac-based access control ability
+ *      direction   -  IEEE802.1x mac-based access control direction
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      the mac address authentication status is saved in L2 table entry,
+ *      it should be set by software.
+ *      there are also two mac-based control directions which are not per 
+ *      port but global configurtion:
+ *      RTL8306_MAC_BOTHDIR - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will be dropped.
+ *      RTL8306_MAC_INDIR   - if Mac-based access control is enabled, packet with 
+ *      unauthorized DA will pass mac-based access control igress rule.
+ */ 
+extern int32 rtl8306e_dot1x_macBased_get(uint32 port, uint32 *pEnabled, uint32 *pDirection); 
+
+/* Function Name:
+ *      rtl8306e_trap_igmpCtrlPktAction_set
+ * Description:
+ *      Set IGMP/MLD trap function
+ * Input:
+ *      type         -  Specify IGMP/MLD or PPPOE
+ *      action       -  Action could be normal forward or trap
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     type could be:
+ *          RTL8306_IGMP   - igmp packet without pppoe header 
+ *          RTL8306_MLD    - mld packet  without pppoe header
+ *          RTL8306_PPPOE_IGMPMLD - pppoe packet if enable trap RTL8306_IGMP 
+ *                                   or RTL8306_MLD whether pppoe packet 
+ *                                   should be trapped. In some application,
+ *                                   igmp and mld message is encapsulated in pppoed
+ *                                   packet.
+ *         
+ *      action could be:
+ *          RTL8306_ACT_PERMIT    - normal forward
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+extern int32 rtl8306e_trap_igmpCtrlPktAction_set(uint32 type, uint32 action);
+
+/* Function Name:
+ *      rtl8306e_trap_igmpCtrlPktAction_get
+ * Description:
+ *      Get IGMP/MLD trap setting
+ * Input:
+ *      type         -  Specify IGMP/MLD or PPPOE
+ * Output:
+ *      pAction     -  the pointer of action could be normal forward or trap
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *     type could be:
+ *          RTL8306_IGMP   - igmp packet without pppoe header 
+ *          RTL8306_MLD    - mld packet  without pppoe header
+ *          RTL8306_PPPOE_IGMPMLD - pppoe packet if enable trap RTL8306_IGMP 
+ *                                   or RTL8306_MLD whether pppoe packet 
+ *                                   should be trapped. In some application,
+ *                                   igmp and mld message is encapsulated in pppoed
+ *                                   packet.
+ *      action could be:
+ *          RTL8306_ACT_PERMIT    - normal forward
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+extern int32 rtl8306e_trap_igmpCtrlPktAction_get(uint32 type, uint32 *pAction);
+
+/* Function Name:
+ *      rtl8306e_trap_unknownIPMcastPktAction_set
+ * Description:
+ *      Set unknown ip multicast drop or normal forward
+ * Input:
+ *      type         -  Specify ipv4 or ipv6 unkown multicast
+ *      action       -  drop or normal forward
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_IPV4_MULTICAST - ipv4 unknown multicast
+ *          RTL8306_IPV6_MULTICAST - ipv6 unknown multicast
+ *      action could be:
+ *          RTL8306_ACT_DROP      - trap to cpu 
+ *          RTL8306_ACT_PERMIT   - normal forward
+ */  
+extern int32 rtl8306e_trap_unknownIPMcastPktAction_set(uint32 type, uint32 action);
+
+/* Function Name:
+ *      rtl8306e_trap_unknownIPMcastPktAction_get
+ * Description:
+ *      Get unknown ip multicast drop or normal forward
+ * Input:
+ *      type         -  Specify ipv4 or ipv6 unkown multicast
+ * Output:
+ *      pAction     -  the pointer of drop or normal forward
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_IPV4_MULTICAST - ipv4 unknown multicast
+ *          RTL8306_IPV6_MULTICAST - ipv6 unknown multicast
+ *      action could be:
+ *          RTL8306_ACT_DROP      - trap to cpu 
+ *          RTL8306_ACT_PERMIT   - normal forward
+ */ 
+extern int32 rtl8306e_trap_unknownIPMcastPktAction_get(uint32 type, uint32 *pAction);
+
+/* Function Name:
+ *      rtl8306e_trap_abnormalPktAction_set
+ * Description:
+ *      set abnormal packet action 
+ * Input:
+ *      type         -  abnormal packet type
+ *      action       -  drop or trap to cpu
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_UNMATCHVID   - vlan-tagged packet, vid dismatch vlan table 
+ *          RTL8306_DOT1XUNAUTH - 802.1x authentication fail packet
+ *      action could be:
+ *          RTL8306_ACT_DROP       - drop 
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+extern int32 rtl8306e_trap_abnormalPktAction_set(uint32 type,  uint32 action);
+
+/* Function Name:
+ *      rtl8306e_trap_abnormalPktAction_get
+ * Description:
+ *      get abnormal packet action 
+ * Input:
+ *      type         -  abnormal packet type
+ * Output:
+ *      pAction     -  the pointer of action
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      type coulde be:
+ *          RTL8306_UNMATCHVID   - vlan-tagged packet, vid dismatch vlan table 
+ *          RTL8306_DOT1XUNAUTH - 802.1x authentication fail packet
+ *      action could be:
+ *          RTL8306_ACT_DROP       - drop 
+ *          RTL8306_ACT_TRAPCPU  - trap to cpu
+ */ 
+
+extern int32 rtl8306e_trap_abnormalPktAction_get(uint32 type,  uint32 *pAction);
+
+/* Function Name:
+ *      rtl8306e_trap_rmaAction_set
+ * Description:
+ *      Set reserved multicast Mac address forwarding behavior
+ * Input:
+ *      type         -  reserved Mac address type
+ *      action       -  forwarding behavior for the specified mac address
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are eight types  reserved addresses which user can set asic to determine 
+ *       how to forwarding them:
+ *            RTL8306_RESADDRXX   - reserved address 01-80-c2-00-00-xx 
+ *                                              (exclude 00, 01, 02, 03, 10, 20, 21)
+ *            RTL8306_RESADDR21   -  reserved address 01-80-c2-00-00-21(GVRP address)
+ *            RTL8306_RESADDR20   -  reserved address 01-80-c2-00-00-20(GMRP Address)
+ *            RTL8306_RESADDR10   -  reserved address 01-80-c2-00-00-10(All LANs Bridge Management Group Address)
+ *            RTL8306_RESADDR03   -  reserved address 01-80-c2-00-00-03(IEEE Std 802.1X PAE address)
+ *            RTL8306_RESADDR02   -  reserved address 01-80-c2-00-00-02(IEEE Std 802.3ad Slow_Protocols-Multicast address)
+ *            RTL8306_RESADDR00   -  reserved address 01-80-c2-00-00-00(Bridge Group Address)
+ *            RTL8306_RESADDR01   -  reserved address 01-80-c2-00-00-01(Pause frame)
+ *       Actions are :
+ *            TL8306_ACT_DROP      - Drop the packet
+ *            TL8306_ACT_TRAPCPU - Trap the packet to cpu
+ *            RTL8306_ACT_FLOOD   - Flood the packet
+ */ 
+extern int32 rtl8306e_trap_rmaAction_set(uint32 type, uint32 action);
+
+/* Function Name:
+ *      rtl8306e_trap_rmaAction_get
+ * Description:
+ *      Get reserved multicast Mac address forwarding behavior
+ * Input:
+ *      type         -  reserved Mac address type
+ * Output:
+ *      pAction     -  the pointer of action
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are eight types  reserved addresses which user can set asic to determine 
+ *       how to forwarding them:
+ *            RTL8306_RESADDRXX   - reserved address 01-80-c2-00-00-xx 
+ *                                              (exclude 00, 01, 02, 03, 10, 20, 21)
+ *            RTL8306_RESADDR21   -  reserved address 01-80-c2-00-00-21(GVRP address)
+ *            RTL8306_RESADDR20   -  reserved address 01-80-c2-00-00-20(GMRP Address)
+ *            RTL8306_RESADDR10   -  reserved address 01-80-c2-00-00-10(All LANs Bridge Management Group Address)
+ *            RTL8306_RESADDR03   -  reserved address 01-80-c2-00-00-03(IEEE Std 802.1X PAE address)
+ *            RTL8306_RESADDR02   -  reserved address 01-80-c2-00-00-02(IEEE Std 802.3ad Slow_Protocols-Multicast address)
+ *            RTL8306_RESADDR00   -  reserved address 01-80-c2-00-00-00(Bridge Group Address)
+ *            RTL8306_RESADDR01   -  reserved address 01-80-c2-00-00-01(Pause frame)
+ *       Actions are :
+ *            TL8306_ACT_DROP      - Drop the packet
+ *            TL8306_ACT_TRAPCPU - Trap the packet to cpu
+ *            RTL8306_ACT_FLOOD   - Flood the packet
+ */ 
+extern int32 rtl8306e_trap_rmaAction_get(uint32 type, uint32 *pAction);
+
+
+/* Function Name:
+ *      rtl8306e_int_control_set
+ * Description:
+ *      Set asic interrupt 
+ * Input:
+ *      enInt        -  Enable interrupt cpu
+ *      intmask     -  interrupt event  mask
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      enInt is global setting and  intmask  has 12 bits totally, each bit 
+ *      represents one interrupt event, 
+ *      - bit0 ~bit4 represent port 0 ~ port 4 link change, 
+ *      - bit 5 represents port 4 MAC link change
+ *      - bit 6 represents port 5 link change, 
+ *      - bit 7 represents storm filter interrupt,
+ *      - bit 8 represents loop event 
+ *      - bit 9 represents wake up frame interrupt
+ *      - bit 10 represents unmatched SA interrupt
+ *      - bit 11 represents Tx meter interrupt
+ *      write 1 to the bit to enable the interrupt and 0 will disable the interrupt. 
+ *
+ */ 
+extern int32 rtl8306e_int_control_set(uint32 enInt, uint32 intmask);
+
+/* Function Name:
+ *      rtl8306e_int_control_get
+ * Description:
+ *      Get Asic interrupt
+ * Input:
+ *      none 
+ * Output:
+ *      pEnInt       -  the pointer of  interrupt global enable bit
+ *      pIntmask    -  the pointer of interrupt event  mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      enInt is global setting and  intmask  has 12 bits totally, each bit 
+ *      represents one interrupt event, 
+ *      - bit0 ~bit4 represent port 0 ~ port 4 link change, 
+ *      - bit 5 represents port 4 MAC link change
+ *      - bit 6 represents port 5 link change, 
+ *      - bit 7 represents storm filter interrupt,
+ *      - bit 8 represents loop event 
+ *      - bit 9 represents wake up frame interrupt
+ *      - bit 10 represents unmatched SA interrupt
+ *      - bit 11 represents Tx meter interrupt
+ *      write 1 to the bit to enable the interrupt and 0 will disable the interrupt. 
+ *
+ */ 
+extern int32 rtl8306e_int_control_get(uint32 *pEnInt, uint32 *pIntmask);
+
+
+
+/* Function Name:
+ *      rtl8306e_int_control_get
+ * Description:
+ *      Get Asic interrupt
+ * Input:
+ *      none 
+ * Output:
+ *      pEnInt       -  the pointer of  interrupt global enable bit
+ *      pIntmask    -  the pointer of interrupt event  mask 
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      enInt is global setting and  intmask  has 12 bits totally, each bit 
+ *      represents one interrupt event, 
+ *      - bit0 ~bit4 represent port 0 ~ port 4 link change, 
+ *      - bit 5 represents port 4 MAC link change
+ *      - bit 6 represents port 5 link change, 
+ *      - bit 7 represents storm filter interrupt,
+ *      - bit 8 represents loop event 
+ *      - bit 9 represents wake up frame interrupt
+ *      - bit 10 represents unmatched SA interrupt
+ *      - bit 11 represents Tx meter interrupt
+ *      write 1 to the bit to enable the interrupt and 0 will disable the interrupt. 
+ *
+ */ 
+extern int32 rtl8306e_int_status_get(uint32 *pStatusMask);
+
+
+/* Function Name:
+ *      rtl8306e_storm_filterEnable_set
+ * Description:
+ *      Enable Asic storm filter 
+ * Input:
+ *      type      -  specify storm filter type
+ *      enabled  -  TRUE or FALSE
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 3 kinds of storm filter:
+ *      (1) RTL8306_BROADCASTPKT - storm filter for broadcast packet
+ *      (2) RTL8306_MULTICASTPKT - storm filter for multicast packet
+ *      (3) RTL8306_UDAPKT           - storm filter for unknown DA packet
+ */ 
+extern int32 rtl8306e_storm_filterEnable_set(uint32 type, uint32 enabled);
+
+
+/* Function Name:
+ *      rtl8306e_storm_filterEnable_get
+ * Description:
+ *      Get Asic storm filter enabled or disabled 
+ * Input:
+ *      type        -  specify storm filter type
+ * Output:
+ *      pEnabled  -  the pointer of enabled or disabled
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      There are 3 kinds of storm filter:
+ *      (1) RTL8306_BROADCASTPKT - storm filter for broadcast packet
+ *      (2) RTL8306_MULTICASTPKT - storm filter for multicast packet
+ *      (3) RTL8306_UDAPKT           - storm filter for unknown DA packet
+ */ 
+
+extern int32 rtl8306e_storm_filterEnable_get(uint32 type, uint32 *pEnabled);
+
+
+/* Function Name:
+ *      rtl8306e_storm_filter_set
+ * Description:
+ *      Set storm filter parameter
+ * Input:
+ *      trigNum        -  set packet threshold which trigger storm filter
+ *      filTime         -   set time window 
+ *      enStmInt     -   enable storm filter to interrupt cpu
+ * Output:
+ *      none
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      there are 6 value for trigNum:
+ *      - RTL8306_STM_FILNUM64, 64 pkts
+ *      - RTL8306_STM_FILNUM32, 32 pkts           
+ *      - RTL8306_STM_FILNUM16, 16 pkts           
+ *      - RTL8306_STM_FILNUM8,   8 pkts              
+ *      - RTL8306_STM_FILNUM128, 128 pkts          
+ *      - RTL8306_STM_FILNUM256, 256 pkts     
+ *      there are 4 value for filTime:
+ *      - RTL8306_STM_FIL800MS,  800ms 
+ *      - RTL8306_STM_FIL400MS,  400ms 
+ *      - RTL8306_STM_FIL200MS,  200ms
+ *      - RTL8306_STM_FIL100MS,  100ms
+ */ 
+
+extern int32 rtl8306e_storm_filter_set(uint32 trigNum, uint32 filTime, uint32 enStmInt);
+
+/* Function Name:
+ *      rtl8306e_storm_filter_get
+ * Description:
+ *      Get storm filter parameter
+ * Input:
+ *      none 
+ * Output:
+ *      pTrigNum        -  the pointer of packet threshold which trigger storm filter
+ *      pFilTime          -  the pointer of filter time window 
+ *      pEnStmInt       -  the pointer of enable storm filter to interrupt cpu
+ * Return:
+ *      SUCCESS
+ *      FAILED
+ * Note:
+ *      there are 6 value for trigNum:
+ *      - RTL8306_STM_FILNUM64, 64 pkts
+ *      - RTL8306_STM_FILNUM32, 32 pkts           
+ *      - RTL8306_STM_FILNUM16, 16 pkts           
+ *      - RTL8306_STM_FILNUM8,   8 pkts              
+ *      - RTL8306_STM_FILNUM128, 128 pkts          
+ *      - RTL8306_STM_FILNUM256, 256 pkts     
+ *      there are 4 value for filTime:
+ *      - RTL8306_STM_FIL800MS,  800ms 
+ *      - RTL8306_STM_FIL400MS,  400ms 
+ *      - RTL8306_STM_FIL200MS,  200ms
+ *      - RTL8306_STM_FIL100MS,  100ms
+ */ 
+
+extern int32 rtl8306e_storm_filter_get(uint32 *pTrigNum, uint32 *pFilTime, uint32 *pEnStmInt);
+
+#endif
+
+
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asictypes.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asictypes.h
new file mode 100644
index 0000000..1cbacb1
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_asictypes.h
@@ -0,0 +1,52 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+* This program is the proprietary software of Realtek Semiconductor
+* Corporation and/or its licensors, and only be used, duplicated,
+* modified or distributed under the authorized license from Realtek.
+*
+* ANY USE OF THE SOFTWARE OTEHR THAN AS AUTHORIZED UNDER 
+* THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
+* 
+* $Revision: 26453 $ 
+* $Date: 2012-01-30 15:52:42 +0800 (星期一, 2012-01-30) $
+*
+* Purpose : asic-level port mapping for RTL8306E/8306M/8304E
+*
+*  Feature :  This file consists of following modules:
+*                1) 
+*
+*/
+#ifndef RTL8306E_ASICTYPES_H
+#define RTL8306E_ASICTYPES_H
+
+#include <rtl8306e_asicdrv.h>
+
+#define CHIP_RTL8306E
+
+#ifdef CHIP_RTL8306E
+#define RTL8306E_PORT0 RTL8306_PORT0
+#define RTL8306E_PORT1 RTL8306_PORT1
+#define RTL8306E_PORT2 RTL8306_PORT2
+#define RTL8306E_PORT3 RTL8306_PORT3
+#define RTL8306E_PORT4 RTL8306_PORT4
+#define RTL8306E_PORT5 RTL8306_PORT5
+#endif
+#ifdef CHIP_RTL8306M
+#define RTL8306M_PORT0 RTL8306_PORT0
+#define RTL8306M_PORT1 RTL8306_PORT1
+#define RTL8306M_PORT2 RTL8306_PORT2
+#define RTL8306M_PORT3 RTL8306_PORT3
+#define RTL8306M_PORT4 RTL8306_PORT4
+#define RTL8306M_PORT5 RTL8306_PORT5
+#endif
+#ifdef CHIP_RTL8304E
+#define RTL8304E_PORT0 RTL8306_PORT0
+#define RTL8304E_PORT1 RTL8306_PORT1
+#define RTL8304E_PORT2 RTL8306_PORT4
+#define RTL8304E_PORT3 RTL8306_PORT5
+#define RTL8304E_PORTMASKIN(x)  (((((uint32)x)&0xC)<<2)|(((uint32)x)&0x3))
+#define RTL8304E_PORTMASKOUT(x) (((((uint32)x)&0x30)>>2)|(((uint32)x)&0x3))
+#endif
+#endif
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_types.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_types.h
new file mode 100644
index 0000000..fb25173
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl8306e_types.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2009 Realtek Semiconductor Corp. 
+ * All Rights Reserved.
+ *
+ * This program is the proprietary software of Realtek Semiconductor
+ * Corporation and/or its licensors, and only be used, duplicated, 
+ * modified or distributed under the authorized license from Realtek. 
+ *
+ * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER 
+ * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. 
+ *
+ * $Revision: 10083 $
+ * $Date: 2010-06-07 11:18:41 +0800 (星期一, 2010-06-07) $
+ *
+ * Purpose : RTL8306E switch API varable type declaration
+ * Feature : 
+ *
+ */
+ 
+ 
+#ifndef __RTL8306E_TYPES_H__
+#define __RTL8306E_TYPES_H__
+
+    
+#ifndef _RTL_TYPES_H
+typedef unsigned long long uint64;
+typedef long long int64;
+typedef unsigned int uint32;
+typedef int int32;
+typedef unsigned short uint16;
+typedef short int16;
+typedef unsigned char uint8;
+typedef char int8;
+#endif
+
+typedef int32                   rtk_api_ret_t;
+typedef int32                   ret_t;
+typedef uint64                  rtk_u_long_t;
+
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN 6
+#endif
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 0
+#endif
+#ifndef FAILED
+#define FAILED -1
+#endif
+
+#define rtlglue_printf printf
+
+#endif
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl_types.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl_types.h
new file mode 100644
index 0000000..ca670dc
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/rtl_types.h
@@ -0,0 +1,656 @@
+/*
+* Copyright c                  Realtek Semiconductor Corporation, 2002  
+* All rights reserved.                                                    
+* 
+* Program : The header file of realtek type definition
+* Abstract :                                                           
+* Author :              
+* $Id: rtl_types.h,v 1.2 2008-01-18 07:53:11 hyking_liu Exp $
+* $Log: not supported by cvs2svn $
+* Revision 1.1  2007/12/21 10:29:52  davidhsu
+* +: support nic driver
+*
+* Revision 1.27  2007/07/27 09:31:23  chenyl
+* +: Add macro for MIPS16-enabled function declaration.
+*
+* Revision 1.26  2007/07/24 08:37:02  chenyl
+* *: For MIPS16 related macros
+*
+* Revision 1.25  2007/06/25 13:08:43  alva_zhang
+* -: remove suitable header file rtl_config.h
+*
+* Revision 1.24  2007/06/25 05:42:30  alva_zhang
+* *: reopen including rtl_config.h
+*
+* Revision 1.23  2007/06/25 02:29:27  alva_zhang
+* -: diable include rtl_config.h temporarily
+*
+* Revision 1.22  2007/06/23 09:11:00  alva_zhang
+* +: add rtl_config.h which includes the MAcro indicate the usage of SDK
+*
+* Revision 1.21  2007/05/15 03:36:56  michaelhuang
+* *: fixed compatibility for Linux Kernel 2.6
+*
+* Revision 1.20  2007/04/04 15:48:54  chenyl
+* +: cleshell commend for asic register configuration : mmtu ( multicast mtu )
+*
+* Revision 1.19  2006/08/29 13:00:00  chenyl
+* *: New SWNIC driver for RTL865xC
+* *: some rearrange in re_core.c for Bootstrap sequence being more readable.
+*
+* Revision 1.18  2006/02/27 07:47:06  ympan
+* +: No change by ympan
+*
+* Revision 1.17  2005/09/27 05:59:44  chenyl
+* *: modify IRAM / DRAM layout:
+* 	IRAM/DRAM-FWD		: external used, swNic ... blahblah
+* 	IRAM/DRAM-L2-FWD	: fwdengine internal used, L2 and below (ex. preprocess, postprocess)
+* 	IRAM/DRAM-L34-FWD	: fwdengine internal used, L3/L4 process only (ex. Routing, decision table...etc).
+*
+* 	=> If L34 is used, we strongly suggest L2 must be used, too.
+*
+* Revision 1.16  2005/08/23 14:38:26  chenyl
+* +: apply prioirty IRAM/DRAM usage
+*
+* Revision 1.15  2005/08/22 07:33:55  chenyl
+* *: don't set DRAM/IRAM for other OSs yet.
+*
+* Revision 1.14  2005/08/18 09:14:08  chenyl
+* *: add code to porting to other OSs
+*
+* Revision 1.13  2005/08/18 06:29:29  chenyl
+* +: always define the rtlglue_printf in rtl_types.h
+*
+* Revision 1.12  2005/07/01 09:34:41  yjlou
+* *: porting swNic2.c into model code.
+*
+* Revision 1.11  2005/06/19 05:29:37  yjlou
+* *: use 'unsigned int' to replace 'size_t'
+* *: define spinlock_t when RTL865X_MODEL_USER defined.
+*
+* Revision 1.10  2005/06/10 05:32:22  yjlou
+* +: Porting CLE Shell to Linux user space for model test.
+*    See RTL865X_MODEL_USER compile flags.
+*
+* Revision 1.9  2005/01/10 03:21:43  yjlou
+* *: always define __IRAM and __DRAM
+*
+* Revision 1.8  2004/07/23 13:42:45  tony
+* *: remove all warning messages
+*
+* Revision 1.7  2004/07/05 08:25:32  chenyl
+* +: define __IRAM, __DRAM for module test
+*
+* Revision 1.6  2004/07/04 15:04:55  cfliu
+* +: add IRAM and DRAM
+*
+* Revision 1.5  2004/04/20 03:44:03  tony
+* if disable define "RTL865X_OVER_KERNEL" and "RTL865X_OVER_LINUX", __KERNEL__ and __linux__ will be undefined.
+*
+* Revision 1.4  2004/03/19 13:13:35  cfliu
+* Reorganize ROME driver local header files. Put all private data structures into different .h file corrsponding to its layering
+* Rename printf, printk, malloc, free with rtlglue_XXX prefix
+*
+* Revision 1.3  2004/03/05 07:44:27  cfliu
+* fix header file problem for ctype.h
+*
+* Revision 1.2  2004/03/03 10:40:38  yjlou
+* *: commit for mergence the difference in rtl86xx_tbl/ since 2004/02/26.
+*
+* Revision 1.1  2004/02/25 14:26:33  chhuang
+* *** empty log message ***
+*
+* Revision 1.3  2004/02/25 14:24:52  chhuang
+* *** empty log message ***
+*
+* Revision 1.8  2003/12/10 06:30:12  tony
+* add linux/config.h, disable define CONFIG_RTL865X_NICDRV2 in mbuf.c by default
+*
+* Revision 1.7  2003/12/03 14:25:43  cfliu
+* change SIZE_T to _SIZE_T. Linux kernel seems to recognize _SIZE_T
+*
+* Revision 1.6  2003/10/01 12:29:02  tony
+* #define DEBUG_P(args...) while(0);
+*
+* Revision 1.5  2003/10/01 10:31:47  tony
+* solve all the compiler warnning messages in the board.c
+*
+* Revision 1.4  2003/09/30 06:07:50  orlando
+* check in RTL8651BLDRV_V20_20030930
+*
+* Revision 1.30  2003/07/21 06:27:49  cfliu
+* no message
+*
+* Revision 1.29  2003/04/30 15:32:30  cfliu
+* move macros to types.h
+*
+* Revision 1.28  2003/03/13 10:29:22  cfliu
+* Remove unused symbols
+*
+* Revision 1.27  2003/03/06 05:00:04  cfliu
+* Move '#pragma ghs inlineprologue' to rtl_depend.h since it is compiler dependent
+*
+* Revision 1.26  2003/03/06 03:41:46  danwu
+* Prevent compiler from generating internal sub-routine call code at the
+*  function prologue and epilogue automatically
+*
+* Revision 1.25  2003/03/03 09:16:35  hiwu
+* remove ip4a
+*
+* Revision 1.24  2003/02/18 10:04:06  jzchen
+* Add ether_addr_t to compatable with protocol stack's ether_addr
+*
+* Revision 1.23  2003/01/21 05:59:51  cfliu
+* add min, max, SETBITS, CLEARBITS, etc.
+*
+* Revision 1.22  2002/11/25 07:31:30  cfliu
+* Remove _POSIX_SOURCE since it is cygwin specific
+*
+* Revision 1.21  2002/09/30 11:51:49  jzchen
+* Add ASSERT_ISR for not print inside ISR
+*
+* Revision 1.20  2002/09/18 01:43:24  jzchen
+* Add type limit definition
+*
+* Revision 1.19  2002/09/16 00:14:34  elvis
+* remove struct posix_handle_t (change the handle type from
+*  structure to uint32)
+*
+* Revision 1.18  2002/08/20 01:40:40  danwu
+* Add definitions of ipaddr_t & macaddr_t.
+*
+* Revision 1.17  2002/07/30 04:36:30  danwu
+* Add ASSERT_CSP.
+*
+* Revision 1.16  2002/07/19 06:47:30  cfliu
+* Add _POSIX_SOURCE symbol
+*
+* Revision 1.15  2002/07/05 02:10:39  elvis
+* Add new types for OSK
+*
+* Revision 1.14  2002/07/03 12:36:21  orlando
+* <rtl_depend.h> will use type definitions. Has to be moved to
+* be after the type declaration lines.
+*
+* Revision 1.13  2002/07/03 09:19:00  cfliu
+* Removed all standard header files from source code. They would be included by <core/types.h>-><rtl_depend.h>
+*
+* Revision 1.12  2002/07/03 09:16:48  cfliu
+* Removed all standard header files from source code. They would be included by <core/types.h>-><rtl_depend.h>
+*
+* Revision 1.11  2002/07/03 07:14:47  orlando
+* Add "struct posix_handle_t_", used by POSIX module.
+*
+* Revision 1.9  2002/06/21 03:15:36  cfliu
+* Add time.h for struct timeval
+*
+* Revision 1.8  2002/06/14 01:58:03  cfliu
+* Move sa_family_t to socket
+*
+* Revision 1.7  2002/06/13 09:37:42  cfliu
+* Move byte order conversion routines to socket
+*
+* Revision 1.6  2002/05/23 04:24:37  hiwu
+* change memaddr_t to calladdr_t
+*
+* Revision 1.5  2002/05/13 10:15:16  hiwu
+* add new type definition
+*
+* Revision 1.4  2002/05/09 05:21:51  cfliu
+* Add parenthesis around swaps16, swapl32
+*
+* Revision 1.3  2002/04/30 03:07:34  orlando
+* Remove UIxx_T definitions to conform with new
+* naming conventions.
+*
+* Revision 1.2  2002/04/29 10:10:32  hiwu
+* add NTOHS macro
+*
+* Revision 1.1.1.1  2002/04/26 08:53:53  orlando
+* Initial source tree creation.
+*
+* Revision 1.9  2002/04/25 03:59:05  cfliu
+* no message
+*
+* Revision 1.8  2002/04/08 08:08:04  hiwu
+* initial version
+*
+*/
+
+
+#ifndef _RTL_TYPES_H
+#define _RTL_TYPES_H
+
+#define RTL_LAYERED_DRIVER_DEBUG 0
+
+#if 0
+#ifndef RTL865X_OVER_KERNEL
+	#undef __KERNEL__
+#endif
+
+#ifndef RTL865X_OVER_LINUX
+	#undef __linux__
+#endif
+#endif
+
+/*
+ * Internal names for basic integral types.  Omit the typedef if
+ * not possible for a machine/compiler combination.
+ */
+#ifdef __linux__
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))
+#include <linux/config.h>
+#endif
+//#include <linux/ctype.h>
+#include <linux/module.h>
+//#include <linux/string.h>
+
+#endif /*__KERNEL__*/
+#endif /*__linux__*/
+
+/* ===============================================================================
+		IRAM / DRAM definition
+    =============================================================================== */
+#undef __DRAM_GEN
+#undef __DRAM_FWD
+#undef __DRAM_L2_FWD
+#undef __DRAM_L34_FWD
+#undef __DRAM_EXTDEV
+#undef __DRAM_AIRGO
+#undef __DRAM_RTKWLAN
+#undef __DRAM_CRYPTO
+#undef __DRAM_VOIP
+#undef __DRAM_TX
+#undef __DRAM
+
+#undef __IRAM_GEN
+#undef __IRAM_FWD
+#undef __IRAM_L2_FWD
+#undef __IRAM_L34_FWD
+#undef __IRAM_EXTDEV
+#undef __IRAM_AIRGO
+#undef __IRAM_RTKWLAN
+#undef __IRAM_CRYPTO
+#undef __IRAM_VOIP
+#undef __IRAM_TX
+#undef __IRAM
+
+#if defined(__linux__)&&defined(__KERNEL__)&&defined(CONFIG_RTL_819X)&&!defined(CONFIG_RTL_8198C)
+	#define __DRAM_GEN			__attribute__  ((section(".dram-gen")))
+	#define __DRAM_FWD			__attribute__  ((section(".dram-fwd")))
+	#define __DRAM_L2_FWD		__attribute__  ((section(".dram-l2-fwd")))
+	#define __DRAM_L34_FWD	__attribute__  ((section(".dram-l34-fwd")))
+	#define __DRAM_EXTDEV		__attribute__  ((section(".dram-extdev")))
+	#define __DRAM_AIRGO		__attribute__  ((section(".dram-airgo")))
+	#define __DRAM_RTKWLAN	__attribute__  ((section(".dram-rtkwlan")))
+	#define __DRAM_CRYPTO		__attribute__  ((section(".dram-crypto")))
+	#define __DRAM_VOIP			__attribute__  ((section(".dram-voip")))
+	#define __DRAM_TX			__attribute__  ((section(".dram-tx")))
+	#define __DRAM				__attribute__  ((section(".dram")))
+
+	#define __IRAM_GEN			__attribute__  ((section(".iram-gen")))
+	#define __IRAM_FWD			__attribute__  ((section(".iram-fwd")))
+	#define __IRAM_L2_FWD		__attribute__  ((section(".iram-l2-fwd")))
+	#define __IRAM_L34_FWD		__attribute__  ((section(".iram-l34-fwd")))
+	#define __IRAM_EXTDEV		__attribute__  ((section(".iram-extdev")))
+	#define __IRAM_AIRGO		__attribute__  ((section(".iram-airgo")))
+	#define __IRAM_RTKWLAN		__attribute__  ((section(".iram-rtkwlan")))
+	#define __IRAM_CRYPTO		__attribute__  ((section(".iram-crypto")))
+	#define __IRAM_VOIP			__attribute__  ((section(".iram-voip")))
+	#define __IRAM_TX			__attribute__  ((section(".iram-tx")))
+	#define __IRAM				__attribute__  ((section(".iram")))
+#else
+	#define __DRAM_GEN
+	#define __DRAM_FWD
+	#define __DRAM_L2_FWD
+	#define __DRAM_L34_FWD
+	#define __DRAM_EXTDEV
+	#define __DRAM_AIRGO
+	#define __DRAM_RTKWLAN
+	#define __DRAM_CRYPTO
+	#define __DRAM_VOIP
+	#define __DRAM_TX
+	#define __DRAM
+
+	#define __IRAM_GEN
+	#define __IRAM_FWD
+	#define __IRAM_L2_FWD
+	#define __IRAM_L34_FWD
+	#define __IRAM_EXTDEV
+	#define __IRAM_AIRGO
+	#define __IRAM_RTKWLAN
+	#define __IRAM_CRYPTO
+	#define __IRAM_VOIP
+	#define __IRAM_TX
+	#define __IRAM
+#endif
+
+#if defined(CONFIG_RTL_DYNAMIC_IRAM_MAPPING_FOR_WAPI) &&!defined(CONFIG_RTL_8198C)
+	#define __IRAM_GEN_WAPI			__attribute__  ((section(".iram-gen-wapi")))
+	#define __IRAM_FWD_WAPI			__attribute__  ((section(".iram-fwd-wapi")))
+	#define __IRAM_L2_FWD_WAPI		__attribute__  ((section(".iram-l2-fwd-wapi")))
+	#define __IRAM_L34_FWD_WAPI		__attribute__  ((section(".iram-l34-fwd-wapi")))
+	#define __IRAM_RTKWLAN_WAPI		__attribute__  ((section(".iram-rtkwlan-wapi")))
+	#define __IRAM_TX_WAPI			__attribute__  ((section(".iram-tx-wapi")))
+
+	#define FUNCTION_CHECK(x)	do \
+							{ \
+								if((x)==NULL) \
+									printk("---%s %s(%d) function is NULL!!\n",__FILE__,__FUNCTION__,__LINE__); \
+							} while(0)
+#endif
+
+
+/* ===============================================================================
+		Additional GCC attribute
+    =============================================================================== */
+
+#undef __NOMIPS16
+#undef __MIPS16
+
+#if defined(__linux__)&&defined(__KERNEL__)&&defined(CONFIG_RTL_819X) && !defined(CONFIG_RTL_8196C)
+#ifndef CONFIG_WIRELESS_LAN_MODULE  //mark_wrt eric-sync ??
+	#define __NOMIPS16			__attribute__((nomips16))	/* Inidcate to prevent from MIPS16 */
+	#define __MIPS16			__attribute__((mips16))		/* Inidcate to use MIPS16 */
+#else
+	#define __NOMIPS16
+	#define __MIPS16
+#endif
+#else
+	#define __NOMIPS16
+	#define __MIPS16
+#endif
+
+/* ===============================================================================
+		print macro
+    =============================================================================== */
+#if	defined(__linux__)&&defined(__KERNEL__)
+	
+	#define rtlglue_printf	panic_printk
+
+#else	/* defined(__linux__)&&defined(__KERNEL__) */
+
+#ifdef	RTL865X_TEST
+	#include <ctype.h>
+#endif	/* RTL865X_TEST */
+
+#define rtlglue_printf	printf
+
+#endif	/* defined(__linux__)&&defined(__KERNEL__) */
+
+/* ===============================================================================
+		Type definition
+    =============================================================================== */
+#if 1
+typedef unsigned long long	uint64;
+typedef signed long long	int64;
+typedef unsigned int	uint32;
+
+#ifdef int32
+#undef int32
+#endif
+typedef signed int		int32;
+
+typedef unsigned short	uint16;
+typedef signed short	int16;
+typedef unsigned char	uint8;
+typedef signed char		int8;
+
+#else
+typedef __u64 uint64;
+typedef __s64	int64;
+typedef __u32	uint32;
+#ifndef int32
+typedef __s32			int32;
+#endif
+typedef __u16	uint16;
+typedef __s16	int16;
+typedef __u8		uint8;
+typedef __s8			int8;
+#endif
+
+typedef uint32		memaddr;	
+typedef uint32          ipaddr_t;
+typedef struct {
+    uint16      mac47_32;
+    uint16      mac31_16;
+    uint16      mac15_0;
+} macaddr_t;
+
+#define ETHER_ADDR_LEN				6
+typedef struct ether_addr_s {
+	uint8 octet[ETHER_ADDR_LEN];
+} ether_addr_t;
+
+#define RX_OFFSET	2
+#define MBUF_LEN	1700
+#define CROSS_LAN_MBUF_LEN		(MBUF_LEN+RX_OFFSET+10)
+
+#if defined(CONFIG_RTL_819X)
+	#if defined(CONFIG_RTL_ETH_PRIV_SKB)
+	#define DELAY_REFILL_ETH_RX_BUF	1
+	#endif
+#endif
+
+/* 
+	CN SD6 Mantis issue #1085: NIC RX can't work correctly after runout.
+	this bug still happened in RTL8196B
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS 	0
+#endif
+#ifndef FAILED
+#define FAILED -1
+#endif
+
+
+
+#define DEBUG_P(args...) while(0);
+#ifndef OK
+#define OK		0
+#endif
+#ifndef NOT_OK
+#define NOT_OK  1
+#endif
+
+#ifndef CLEARBITS
+#define CLEARBITS(a,b)	((a) &= ~(b))
+#endif
+
+#ifndef SETBITS
+#define SETBITS(a,b)		((a) |= (b))
+#endif
+
+#ifndef ISSET
+#define ISSET(a,b)		(((a) & (b))!=0)
+#endif
+
+#ifndef ISCLEARED
+#define ISCLEARED(a,b)	(((a) & (b))==0)
+#endif
+
+#ifndef max
+#define max(a,b)  (((a) > (b)) ? (a) : (b))
+#endif			   /* max */
+
+#ifndef min
+#define min(a,b)  (((a) < (b)) ? (a) : (b))
+#endif			   /* min */
+
+//round down x to multiple of y.  Ex: ROUNDDOWN(20, 7)=14
+#ifndef ROUNDDOWN
+#define	ROUNDDOWN(x, y)	(((x)/(y))*(y))
+#endif
+
+//round up x to multiple of y. Ex: ROUNDUP(11, 7) = 14
+#ifndef ROUNDUP
+#define	ROUNDUP(x, y)	((((x)+((y)-1))/(y))*(y))  /* to any y */
+#endif
+
+#ifndef ROUNDUP2
+#define	ROUNDUP2(x, y)	(((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
+#endif
+
+#ifndef ROUNDUP4
+#define	ROUNDUP4(x)		((1+(((x)-1)>>2))<<2)
+#endif
+
+#ifndef IS4BYTEALIGNED
+#define IS4BYTEALIGNED(x)	 ((((x) & 0x3)==0)? 1 : 0)
+#endif
+
+#ifndef __offsetof
+#define __offsetof(type, field) ((unsigned long)(&((type *)0)->field))
+#endif
+
+#ifndef offsetof
+#define offsetof(type, field) __offsetof(type, field)
+#endif
+
+#ifndef RTL_PROC_CHECK
+#define RTL_PROC_CHECK(expr, success) \
+	do {\
+			int __retval; \
+			if ((__retval = (expr)) != (success))\
+			{\
+				rtlglue_printf("ERROR >>> [%s]:[%d] failed -- return value: %d\n", __FUNCTION__,__LINE__, __retval);\
+				return __retval; \
+			}\
+		}while(0)
+#endif
+
+#ifndef RTL_STREAM_SAME
+#define RTL_STREAM_SAME(s1, s2) \
+	((strlen(s1) == strlen(s2)) && (strcmp(s1, s2) == 0))
+#endif
+
+#define ASSERT_ISR(x) if(!(x)) {while(1);}
+#define RTL_STATIC_INLINE   static __inline__
+
+#define ASSERT_CSP(x) if (!(x)) {rtlglue_printf("\nAssert Fail: %s %d", __FILE__, __LINE__); while(1);}
+ 
+
+#if defined(RTL865X_TEST)||defined(RTL865X_MODEL_USER)
+#define UNCACHE_MASK		0
+#define UNCACHE(addr)		(addr)
+#define CACHED(addr)			((uint32)(addr))
+#else
+#define UNCACHE_MASK		0x20000000
+#define UNCACHE(addr)		((UNCACHE_MASK)|(uint32)(addr))
+#define CACHED(addr)			((uint32)(addr) & ~(UNCACHE_MASK))
+#endif
+
+/*	asic configuration	*/
+#define RTL8651_OUTPUTQUEUE_SIZE		6
+#define TOTAL_VLAN_PRIORITY_NUM	8
+#define RTL8651_RATELIMITTBL_SIZE			32
+
+#if defined(CONFIG_RTL_8196C)
+#define CONFIG_RTL8196C_ETH_IOT         1
+#ifdef CONFIG_MP_PSD_SUPPORT
+#undef CONFIG_RTL8196C_GREEN_ETHERNET
+#else
+//#define CONFIG_RTL_8196C_ESD            1 
+#endif
+#endif
+
+#if defined(CONFIG_RTL_8198) && !defined(CONFIG_RTL_819XD)
+#define CONFIG_RTL_8198_ESD        1
+#endif 
+
+#if defined(CONFIG_RTL_8198)
+#define RTL8198_EEE_MAC 	1
+#endif
+
+#if defined(CONFIG_RTL_819XD) || defined(CONFIG_RTL_8196E)
+#define CONFIG_RTL_8197D_DYN_THR		1
+#endif
+
+#define DYN_THR_LINK_UP_PORTS			3
+
+/* IC default value */
+#define DYN_THR_DEF_fcON				0xac
+#define DYN_THR_DEF_fcOFF				0xa0
+#define DYN_THR_DEF_sharedON			0x62
+#define DYN_THR_DEF_sharedOFF			0x4a
+
+/* aggressive value */
+#define DYN_THR_AGG_fcON				0xd0
+#define DYN_THR_AGG_fcOFF				0xc0
+#define DYN_THR_AGG_sharedON			0xc0
+#define DYN_THR_AGG_sharedOFF			0xa8
+
+#if defined(CONFIG_RTL_LOG_DEBUG)
+extern int scrlog_printk(const char * fmt, ...);
+
+extern struct RTL_LOG_PRINT_MASK
+{
+	uint32 ERROR:1;
+	uint32 WARN:1;
+	uint32 INFO:1;
+}RTL_LogTypeMask;
+
+extern struct RTL_LOG_ERROR_MASK
+{
+	uint32 MEM:1;
+	uint32 SKB:1;
+}RTL_LogErrorMask;
+extern uint32 RTL_LogRatelimit;
+
+extern struct RTL_LOG_MODULE_MASK
+{
+	uint8 NIC:1;
+	uint8 WIRELESS:1;
+	uint8 PROSTACK:1;
+}RTL_LogModuleMask;
+
+
+#define LOG_LIMIT (!RTL_LogRatelimit||net_ratelimit())
+
+
+#define LOG_ERROR(fmt, args...) do{ \
+	if(RTL_LogTypeMask.ERROR&&LOG_LIMIT)scrlog_printk("ERROR:"fmt, ## args); \
+		}while(0)
+		
+#define LOG_MEM_ERROR(fmt, args...) do{ \
+	if(RTL_LogTypeMask.ERROR&&RTL_LogErrorMask.MEM&&LOG_LIMIT)scrlog_printk("ERROR:"fmt, ## args); \
+		}while(0)
+		
+#define LOG_SKB_ERROR(fmt, args...) do{ \
+		if(RTL_LogTypeMask.ERROR&&RTL_LogErrorMask.SKB&&LOG_LIMIT)scrlog_printk("ERROR:"fmt, ## args); \
+			}while(0)
+			
+#define LOG_WARN(fmt, args...) do{ \
+		if(RTL_LogTypeMask.WARN&&LOG_LIMIT)scrlog_printk("WARN:"fmt, ## args); \
+			}while(0)
+			
+#define LOG_INFO(fmt, args...) do{ \
+		if(RTL_LogTypeMask.INFO&&LOG_LIMIT)scrlog_printk("INFO:"fmt, ## args); \
+			}while(0)
+
+#else
+
+#define LOG_ERROR(fmt, args...) 
+#define LOG_MEM_ERROR(fmt, args...) 
+#define LOG_SKB_ERROR(fmt, args...)
+#define LOG_WARN(fmt, args...)
+#define LOG_INFO(fmt, args...)
+
+#endif 
+
+#endif 
+
+
diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/zx_gmac_switch.c b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/zx_gmac_switch.c
new file mode 100644
index 0000000..1ee93f1
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/switch/zx_gmac_switch.c
@@ -0,0 +1,664 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2011, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾ 

+*

+* ÎļþÃû³Æ:	zx_gmac.c

+* Îļþ±êʶ:

+* ÄÚÈÝÕªÒª: sanchips Serial GMAC Çý¶¯ 

+* ÆäËü˵Ã÷:	±¾ÏµÍ³ËùÓÐÍâÉèʹÓù̶¨Ó³É䣬´Ó×ÊÔ´ÖлñÈ¡µÄµØÖ·¾ùΪÐéÄâµØÖ·£¬¹ÊÎÞÐëioremap

+*			Èç¹ûϵͳÖÐʹÓö¯Ì¬Ó³É䣬ÇëÐÞ¸Äprobeº¯ÊýÒÔÐÞ¶©µØÖ·Ó³Éä 

+* µ±Ç°°æ±¾:	1.1

+* ×÷¡¡¡¡Õß:	¹ùÒýÐã 

+* Íê³ÉÈÕÆÚ: 2011-8-1

+*

+* Ð޸ļǼ1

+* ÐÞ¸ÄÈÕÆÚ:

+* °æ±¾¡¡ºÅ:

+* Ð޸ġ¡ÈË:

+* ÐÞ¸ÄÄÚÈÝ:

+*

+*******************************************************************************/

+#include "rtl8306e_types.h"

+#include "rtl8306e_asicdrv.h"

+#include "rtk_api.h"

+#include "../zx_gmac.h"

+

+#include <mach/highspeed_debug.h>

+/*-----------------------------------------------------------------------------------

+* ºê¶¨Òå

+------------------------------------------------------------------------------*/

+//#define   CONFIG_SWITCH_TIMER_SET

+#define GMAC_NO_INT

+

+#define   SWITCH_PORT_NUM  	   5	

+#define   GMAC_PLUG_NAME    "eth_state"

+#define   SWITCH_CTL_MAC     SWITCH_PORT_NUM+1  

+#define   SWITCH_WAN_PORT   RTL8306_PORT4

+

+typedef enum{

+     GMAC_SWITCH_WAN_PLUGIN = 0,

+     GMAC_SWITCH_WAN_PLUGOUT,

+     GMAC_SWITCH_LAN_PLUGIN,

+     GMAC_SWITCH_LAN_PLUGOUT,

+     GMAC_SWITCH_NUM,

+}switch_notify_event;

+/****************************************************************************

+* 	                               Global Variables

+****************************************************************************/

+struct kset *kset_gmac;

+//struct kset kset_c;

+struct kobject *gmackobj = NULL;

+struct kobject *gmac_switchkobj = NULL;

+

+static unsigned int wan_plug = 0;

+static unsigned int lan_plug = 0;

+static unsigned int wan_lan_plug = 0;

+static unsigned int switch_init_state = 0;

+

+static char   wan_on_lan_off[] ="wan_on_lan_off";

+static char  wan_off_lan_on[] ="wan_off_lan_on";

+static char  wan_lan_on[]="wan_lan_on";

+static char  wan_lan_off[]="wan_lan_off";

+static char  switch_init_invalid[]="invalid";

+static unsigned long switch_init_time_start = 0;

+static unsigned long switch_init_time_now = 0;

+static unsigned int switch_init_flag = 1;

+

+extern struct net_device* 	gmac_net_dev;

+extern struct zx_net_dev* 	gmac_net_dev_prv;

+#ifdef GMAC_NO_INT

+static E_LINK_STATE g_switch_port_state[SWITCH_PORT_NUM]= {0};

+#endif

+

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪµ÷ÓõÄÍⲿº¯Êý½Ó¿Ú

+* 

+* 

+------------------------------------------------------------------------------*/

+extern rtk_api_ret_t rtk_port_macForceLinkExt0_set(rtk_mode_ext_t mode, rtk_port_mac_ability_t *pPortability);

+extern rtk_api_ret_t rtk_vlan_get(rtk_vlan_t vid, rtk_portmask_t *pMbrmsk, rtk_portmask_t *pUntagmsk, rtk_fid_t *pFid);

+extern rtk_api_ret_t rtk_vlan_portPvid_get(rtk_port_t port, rtk_vlan_t *pPvid, rtk_pri_t *pPriority);

+extern rtk_api_ret_t rtk_vlan_init(void);

+extern rtk_api_ret_t rtk_vlan_portPvid_set(rtk_port_t port, rtk_vlan_t pvid, rtk_pri_t priority);

+extern rtk_api_ret_t rtk_vlan_set(rtk_vlan_t vid, rtk_portmask_t mbrmsk, rtk_portmask_t untagmsk, rtk_fid_t fid);

+extern rtk_api_ret_t rtk_vlan_portAcceptFrameType_set(rtk_port_t port, rtk_vlan_acceptFrameType_t accept_frame_type);

+extern rtk_api_ret_t rtk_vlan_destroy(rtk_vlan_t vid);

+extern int32 rtl8306e_vlan_portBase_set();

+extern int gmac_mii_read(struct net_device *dev, int phy, int reg);

+extern void gmac_mii_write(struct net_device *dev, int phy, int reg, int val);

+#ifdef GMAC_NO_INT

+//void zx_gmac_plug_thread(unsigned long dev_id);

+void zx_gmac_plug_thread_ms(unsigned long dev_id);

+#endif

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪ´úÂëÕýÎÄÇø

+* 

+* 

+------------------------------------------------------------------------------*/

+ static E_LINK_STATE switch_port_state[SWITCH_PORT_NUM]={0};

+

+void switch_notify_up(gmac_notify_event notify_type, void* puf)

+{

+	unsigned char buf[100];

+	int rtv = -1;

+	enum kobject_action action;

+	char*envp_ext_sw0_wan[] = {"GMACEVENT=gmac_sw0_wan",NULL}; 

+	char*envp_ext_sw0_lan[] = {"GMACEVENT=gmac_sw0_lan",NULL}; 

+	switch(notify_type){

+		case GMAC_SWITCH_WAN_PLUGIN:

+			gmac_printk("gmac sw0 wan plugin \n");

+//			strcpy(envp_ext[0],"GMACEVENT=gmac_sw0_wan");

+			action = KOBJ_ADD;

+			if(gmac_switchkobj){

+				rtv = kobject_uevent_env(gmac_switchkobj, action,envp_ext_sw0_wan);

+			}			

+			break;

+

+		case GMAC_SWITCH_WAN_PLUGOUT:

+			gmac_printk("gmac sw0 wan plugout \n");

+		//	strcpy(envp_ext[0],"GMACEVENT=gmac_sw0_wan");

+			action = KOBJ_REMOVE;

+			if(gmac_switchkobj){

+				rtv = kobject_uevent_env(gmac_switchkobj, action,envp_ext_sw0_wan);

+			}			

+			break;

+

+		case GMAC_SWITCH_LAN_PLUGIN:

+			gmac_printk("gmac sw0 lan plugin \n");

+		//	strcpy(envp_ext[0],"GMACEVENT=gmac_sw0_lan");

+			action = KOBJ_ADD;

+			if(gmac_switchkobj){

+				rtv = kobject_uevent_env(gmac_switchkobj, action,envp_ext_sw0_lan);

+			}			

+			break;

+		case GMAC_SWITCH_LAN_PLUGOUT:

+			gmac_printk("gmac sw0 lan plugout\n");

+			//strcpy(envp_ext[0],"GMACEVENT=gmac_sw0_lan");

+			action = KOBJ_REMOVE;

+			if(gmac_switchkobj){

+				rtv = kobject_uevent_env(gmac_switchkobj, action,envp_ext_sw0_lan);

+			}			

+			break;

+		default:

+			gmac_printk("UNKWON GMAC EVENT \n");

+			break;

+	}

+

+

+	gmac_printk("rtv:%d \n",rtv);

+}

+void rtl8306e_all_port_state_get()

+{

+    int i = 0;

+    uint32 val = 0;

+     for(i= RTL8306_PORT0 ;i<RTL8306_PORT5;i++)

+       {

+            rtl8306e_port_phyLinkStatus_get(i,&val);   

+            if(val)

+            { 

+               if(i != RTL8306_PORT4)     lan_plug = 1;

+               else                                wan_plug = 1;

+            }     

+      }

+

+     if(lan_plug && wan_plug)

+     {

+           wan_lan_plug = 1;

+     }

+    

+}

+

+int smiRead(int phyad, int regad,int * data)

+{

+	*data = gmac_mii_read(gmac_net_dev, phyad, regad);	

+	return 1;

+}

+

+int smiWrite(int phyad, int regad, int data)

+{

+	gmac_mii_write(gmac_net_dev, phyad, regad, data);

+	return 1;

+}

+

+void zx_net_switch_notify(unsigned long dev_id)

+{

+    struct net_device* dev 		= (struct net_device*)dev_id;

+    struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+    uint32	 		val , nphy, i;

+    uint32	 link_in_count = 0;

+    uint32	 link_out_count  = 0;

+    unsigned int events = 0;	    

+	

+    while(1)

+    {

+        down(&prv->phy_sem);

+        events	= prv->ext_int_event;	

+        

+        for(i= RTL8306_PORT0 ;i<RTL8306_PORT5;i++)

+        {

+            // if(events &(0x1<<i))       //port0 -4 link  state

+            nphy = i;

+            if(nphy == SWITCH_WAN_PORT)  //wan

+            {

+                if(switch_port_state[nphy]&& (events &(0x1<<4))) //in

+                {

+                    gmac_printk("wan in !\n");

+                    switch_notify_up(GMAC_SWITCH_WAN_PLUGIN, NULL);

+                    wan_plug = 1;

+                }

+                else if(events &(0x1<<4)) //out

+                {

+                    gmac_printk("wan out !\n");

+                    switch_notify_up(GMAC_SWITCH_WAN_PLUGOUT, NULL); 

+                    wan_plug = 0;

+                }

+            }	 

+            else if((events &(0x1<<0))|| (events &(0x1<<1))|| (events &(0x1<<2))|| (events &(0x1<<3)))//lan

+            {                

+                if(switch_port_state[nphy]) //in

+                {    	   

+                    link_in_count++;

+                    gmac_printk("the value of  link_in_count is = %d  !\n",link_in_count);

+                }

+                else  //out

+                {

+                    link_out_count++;	

+                    gmac_printk("the value of  link_out_count is = %d  !\n",link_out_count);  

+                }

+            }

+            if(((events &(0x1<<0))&&switch_port_state[0] )|| ((events &(0x1<<1))&&switch_port_state[1] ) || ((events &(0x1<<2))&&switch_port_state[2] ) || ((events &(0x1<<3))&&switch_port_state[3] ))

+            {

+                if((nphy == RTL8306_PORT4) && (link_in_count == 1))

+                {

+                    gmac_printk("lan in !\n");

+                    switch_notify_up(GMAC_SWITCH_LAN_PLUGIN, NULL);    

+                    lan_plug = 1;

+                }

+            }

+            if((nphy == RTL8306_PORT4)&& (link_out_count == 4))

+            {

+                gmac_printk("lan out !\n");

+                switch_notify_up(GMAC_SWITCH_LAN_PLUGOUT, NULL);     

+                lan_plug = 0;

+            }	   

+                

+            if(i == RTL8306_PORT4)

+            {

+                link_in_count =0;

+                link_out_count=0;

+            }              							

+        }

+    }

+}

+E_LINK_STATE gmac_switch_linked(struct net_device *dev)

+{

+    unsigned int  rdata = 0;

+    rtl8306e_port_phyLinkStatus_get(SWITCH_CTL_MAC,&rdata);  

+    return rdata;

+}

+#if 0

+static E_LINK_STATE switch_linked(struct net_device *dev)

+{

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+       short unsigned	       val         =  0;

+       /*switch page 0*/

+       val  = mii_read(dev,0, 16); 

+       val  = (val & 0x7FFF) | 0x0002;

+       mii_write(dev,0,16,val);

+        /*read phy 6 reg 0  ,get link states*/

+       val = mii_read(dev,6,1);

+       

+       return (val >> 2) & 0x01;

+} 

+#endif

+#ifdef GMAC_NO_INT

+void zx_gmac_plug_thread_ms(unsigned long dev_id)

+{

+	struct net_device *dev = (struct net_device*)dev_id;

+	struct zx_net_dev *prv = (struct zx_net_dev*)netdev_priv(dev);

+    int          int_event = 0;

+    uint32       rdata     = 0;

+    uint32       phynum    = 0;

+    int          i         = 0;

+    int       state_change = 0;

+	while (!kthread_should_stop()){

+        rtl8306e_reg_get(4, 22, 3, &rdata);

+        prv->ext_int_event = rdata;

+

+        for(phynum = 0;phynum<RTL8306_PORT5;phynum++)

+        {

+            rdata = 0;

+            rtl8306e_port_phyLinkStatus_get(phynum,&rdata);   

+            switch_port_state[phynum] = rdata;

+

+            if( g_switch_port_state[phynum] != switch_port_state[phynum] )

+            {

+                g_switch_port_state[phynum] = switch_port_state[phynum];

+                state_change = 1;

+            }

+        }

+        

+        if (state_change == 1)

+        {

+            state_change = 0;

+            up(&prv->phy_sem);

+        }

+        

+        msleep(1000);

+	}

+}

+#else

+#ifdef CONFIG_SWITCH_TIMER_SET

+// Íø¿Ú¶¨Ê±Æ÷

+static void zx_net_switch_timer(unsigned long data)

+{

+    	struct net_device* 	dev		= (struct net_device*)data;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+	volatile unsigned 	*gmac 	= (unsigned*)dev->base_addr;

+	int					phy 	= prv->phy;

+	unsigned 			temp_val;

+       uint32   val = 0;

+       

+       spin_lock_irq(&prv->phy_lock);

+       rtl8306e_port_phyLinkStatus_get(SWITCH_CTL_MAC,&val);    

+

+       if(val)

+        {

+                if(!netif_carrier_ok(dev))	netif_carrier_on(dev);

+	}

+	else													// PHY δÄÜÁ¬½Ó

+	{

+		if(netif_carrier_ok(dev))	netif_carrier_off(dev);

+	}

+

+	prv->link 					= val;

+	prv->timer.expires 			= jiffies + HZ;				// Ï´ζ¨Ê±Æ÷£º1sºó¿ªÊ¼

+

+	spin_unlock_irq(&prv->phy_lock);

+	

+	add_timer(&prv->timer);

+}

+

+#else 

+// PHY Öжϴ¦Àíº¯Êý

+static irqreturn_t zx_switch_int(int irq, void *dev_id)

+{

+	struct net_device* dev 		= (struct net_device*)dev_id;

+	struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+       uint32 rdata;

+       uint32 phynum = 0;

+       

+#ifdef CONFIG_ARCH_ZX297520V2  

+			pcu_int_clear(PCU_EX6_INT);

+#elif CONFIG_ARCH_ZX297520V3

+       pcu_int_clear(PCU_GMACPHY_INT);

+#endif

+     //  phy_count++;

+       rtl8306e_reg_get(4, 22, 3, &rdata);

+   

+

+        prv->ext_int_event = rdata;

+

+        for(phynum = 0;phynum<RTL8306_PORT5;phynum++)

+        {

+            rdata = 0;

+            rtl8306e_port_phyLinkStatus_get(phynum,&rdata);   

+            switch_port_state[phynum] = rdata;    

+        }

+

+        up(&prv->phy_sem);

+        

+	return IRQ_HANDLED;

+}

+#endif

+#endif

+

+// ´ò¿ªÍøÂçÉ豸

+int zx_gmac_switch_open(struct net_device *dev)

+{

+    int ret;

+    struct zx_net_dev* prv	= (struct zx_net_dev*)netdev_priv(dev);

+    uint32 rdata = 0;

+    int ext_int6_no = 0;

+

+    

+    prv->link 		= gmac_switch_linked(dev);  

+    

+#ifdef CONFIG_SWITCH_TIMER_SET

+    init_timer(&prv->timer);

+    prv->timer.expires 		= jiffies + HZ;

+    prv->timer.data 		= (unsigned long)dev;

+    prv->timer.function 	= &zx_net_switch_timer;

+    add_timer(&prv->timer);   

+ #endif

+    return 0;

+}

+

+// ¹Ø±ÕÍøÂçÉ豸

+int zx_gmac_switch_stop(struct net_device *dev)

+{

+    unsigned long       flags = 0;

+

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+

+#ifdef CONFIG_SWITCH_TIMER_SET    

+       del_timer_sync(&prv->timer);

+#else

+	gpio_free(ZX29_GPIO_64);

+	free_irq(prv->ext_irq,dev); 

+#endif

+

+    return 0;

+}

+

+static struct attribute gmac_plug_attr =

+{

+        .name = "eth_state",

+        .mode = S_IRWXUGO,

+};

+

+static struct attribute *gmac_status_attrs[] =

+{

+       &gmac_plug_attr,

+       NULL,

+};

+

+ssize_t kobj_gmac_show(struct kobject *kobject,struct attribute *attr,char *buf)

+{

+        uint32 phynum = 0;

+        uint32 phyon_num = 6;

+	 uint32 rdata = 0;

+        for(phynum = 0;phynum<RTL8306_PORT5;phynum++)

+        {

+               rtl8306e_port_phyLinkStatus_get(phynum,&rdata);   

+		 switch_port_state[phynum] = rdata;

+		 if (switch_port_state[phynum] == 1)

+		{

+		     phyon_num = phynum;

+		     break;

+		}        

+         }

+         gmac_printk("attrname: %s.\n",attr->name);		 

+	  if(!strcmp(attr->name, GMAC_PLUG_NAME)){

+

+		 if(phyon_num != 6)

+		   {

+		      rtl8306e_all_port_state_get();

+                   if(wan_plug&&lan_plug)

+                   {

+                       sprintf(buf, "%s",wan_lan_on);

+                   }

+                   else if(wan_plug)

+                   {

+                       sprintf(buf, "%s",wan_on_lan_off);

+                    }

+                    else if(lan_plug)

+                    {

+                       sprintf(buf, "%s",wan_off_lan_on);

+                     }

+                     else 

+                     {

+                        sprintf(buf, "%s",wan_lan_off);

+                     }  

+		       return strlen(buf);

+		 }

+		 else

+		 {

+                   sprintf(buf, "%s",wan_lan_off);

+		     return strlen(buf);

+	        }		          

+	    }

+      return strlen(buf);

+}

+ssize_t kobj_gmac_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)

+{

+	unsigned int value = 0;

+	value = simple_strtoul(buf, NULL, 4);

+	gmac_printk("attrname: %s.\n",attr->name);

+	if(!strcmp(attr->name,GMAC_PLUG_NAME)){

+		wan_plug = value;

+	}

+	return size;

+}

+static struct sysfs_ops obj_gmac_sysops =

+{

+        .show = kobj_gmac_show,

+        .store = kobj_gmac_store,        

+};

+

+void obj_gmac_release(struct kobject *kobject)

+{

+	gmac_printk("[kobj_test: release!]\n");

+}

+

+static struct kobj_type gmacktype =

+

+{       .release = obj_gmac_release,

+        .sysfs_ops = &obj_gmac_sysops,

+        .default_attrs = gmac_status_attrs,

+};

+static int kset_filter(struct kset *kset,struct kobject *kobj)

+{

+   gmac_printk("kset Filter: kobj %s.\n",kobj->name);

+     return 1;

+}

+

+static const char *kset_name(struct kset *kset,struct kobject *kobj)

+{    

+       static char buf[20];

+       gmac_printk("Name:  kobj %s.\n",kobj->name);

+       sprintf(buf,"%s","gmac");

+       return buf;

+}

+

+static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)

+{

+   int i = 0;

+    gmac_printk("uevent: kobj %s.\n",kobj->name);

+

+   while(i < env->envp_idx)

+    {

+        gmac_printk("%s.\n",env->envp[i]);

+       i ++;

+    }

+

+    return 0;

+}

+

+static struct kset_uevent_ops gmac_uevent_ops =

+{

+    .filter = kset_filter,

+    .name = kset_name,

+    .uevent = kset_uevent,

+};

+

+static int  kset_gmac_init(void)

+{

+  int ret = 0;

+  

+   gmac_printk("kobject  init!\n");

+   /* ´´½¨²¢×¢²á kset_p */

+   

+     gmackobj = kzalloc(sizeof(*gmackobj),GFP_KERNEL);

+   if(!gmackobj){

+        printk(KERN_WARNING "mallock gmackobj failed \n");

+        return 0;

+    }

+   kobject_init(gmackobj, &gmacktype);

+   kobject_add(gmackobj,kernel_kobj,"%s","eth_debug");

+   

+    gmac_printk("kset test init!\n");

+   kset_gmac = kset_create_and_add("gmac", &gmac_uevent_ops, NULL); 

+

+   gmac_switchkobj = kzalloc(sizeof(*gmac_switchkobj),GFP_KERNEL);

+   if(!gmac_switchkobj){

+   	printk(KERN_WARNING "mallock gmac_switchkobj failed \n");

+	return 0;

+     }

+    kobject_init(gmac_switchkobj, &gmacktype);

+    kobject_add(gmac_switchkobj,&kset_gmac->kobj,"%s","gmacconfig");

+    gmac_switchkobj->kset = kset_gmac;

+

+   return ret;

+}

+

+int  zx_gmac_switch_init(struct net_device *dev)

+{

+    int	ret = 0;

+    rtk_mode_ext_t  Mode;

+    rtk_port_mac_ability_t portAbility;

+    uint32 rdata = 0;

+    int ext_int6_no = 0;

+	int a;

+    struct zx_net_dev* prv	= (struct zx_net_dev*)netdev_priv(dev);

+   //reset

+   rtl8306e_regbit_set(1, 0, 15, 0, 1);

+   

+   while (a == 1)

+   	{

+    rtl8306e_regbit_get(1, 0, 15, 0, &a);

+   }

+   

+    /*enable interrupt*/

+    rtl8306e_regbit_set(2, 22, 15, 3, 0);

+    /*mask interrupt phy 0-5 */

+    rtl8306e_reg_get(4, 23, 3, &rdata);

+    //rdata |= 0x5f;

+    rdata |= 0x1f;

+    rtl8306e_reg_set(4, 23, 3, rdata); 

+

+    sema_init(&prv->phy_sem,0);

+

+#ifdef GMAC_NO_INT

+    kthread_run(zx_gmac_plug_thread_ms, (unsigned long)dev, "gmac_switch/%s", "plug");

+#else

+#ifdef CONFIG_ARCH_ZX297520V2  

+    ret = gpio_request(ZX29_GPIO_56, "ext_int6");

+    if (ret) 

+    {

+    	gmac_printk("reset gpio6  request error.\n");

+    	return ret;

+    }

+    zx29_gpio_pd_pu_set(ZX29_GPIO_56,IO_CFG_PULL_DISABLE);

+	/* config as ext_int*/

+    ret = zx29_gpio_config(ZX29_GPIO_56, GPIO56_EXT_INT6); 

+#elif CONFIG_ARCH_ZX297520V3

+    ret = gpio_request(ZX29_GPIO_64, "phy_int");

+    if (ret) 

+    {

+    	gmac_printk("reset GPIO_64  request error.\n");

+    	return ret;

+    }

+    zx29_gpio_pd_pu_set(ZX29_GPIO_64,IO_CFG_PULL_DISABLE);

+    /* config as ext_int*/

+    ret = zx29_gpio_config(ZX29_GPIO_64, GPIO64_PHY_INT); 

+#endif 

+    if (ret) 

+    return ret;

+	

+    /* get int no */

+    ext_int6_no = prv->ext_irq;

+    gmac_printk("TSP zx29 gmac phy int no irq = %d  !\n",ext_int6_no);

+//    zx29_gpio_set_inttype(ZX29_GPIO_64, IRQ_TYPE_LEVEL_HIGH);

+#ifdef CONFIG_ARCH_ZX297520V2  

+			pcu_int_clear(PCU_EX6_INT);

+#elif CONFIG_ARCH_ZX297520V3

+			pcu_int_clear(PCU_GMACPHY_INT);

+#endif   

+    ret = request_threaded_irq(ext_int6_no, zx_switch_int, NULL,0, dev->name, dev);

+    if(ret)

+    return ret;

+    irq_set_irq_wake(ext_int6_no, 1);

+#endif

+

+    rtl8306e_asic_init();

+     /*MAC5 force link up*/

+     Mode = MODE_EXT_RMII;

+     portAbility.forcemode = 1;

+     portAbility.nway = 0;

+     portAbility.speed = PORT_SPEED_100M;

+     portAbility.link = 1;

+     portAbility.duplex = PORT_FULL_DUPLEX;

+     portAbility.rxpause = 1;

+     portAbility.txpause = 1;

+

+    rtk_port_macForceLinkExt0_set(Mode,&portAbility);

+    prv->link = eLINK_OFF;

+    rtl8306e_vlan_portBase_set();	

+   

+     switch_init_state = 1;

+     kset_gmac_init();

+	 

+#ifndef CONFIG_SWITCH_TIMER_SET

+	  

+    prv->switch_thread = kthread_run(zx_net_switch_notify, dev, "eth_sw0_thread");

+    if (IS_ERR(prv->switch_thread) )

+    {

+        prv->switch_thread = NULL;

+        gmac_printk("[%s] create switch_thread fail\n", __FUNCTION__);

+	 return 1;	 

+    }

+#endif

+    return ret;

+}

+

diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/zx_gmac.c b/ap/os/linux/linux-3.4.x/drivers/net/gmac/zx_gmac.c
new file mode 100644
index 0000000..1fc9891
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/zx_gmac.c
@@ -0,0 +1,1568 @@
+/*******************************************************************************

+* °æÈ¨ËùÓÐ (C)2011, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾ 

+*

+* ÎļþÃû³Æ:	zx_gmac.c

+* Îļþ±êʶ:

+* ÄÚÈÝÕªÒª: sanchips Serial GMAC Çý¶¯ 

+* ÆäËü˵Ã÷:	±¾ÏµÍ³ËùÓÐÍâÉèʹÓù̶¨Ó³É䣬´Ó×ÊÔ´ÖлñÈ¡µÄµØÖ·¾ùΪÐéÄâµØÖ·£¬¹ÊÎÞÐëioremap

+*			Èç¹ûϵͳÖÐʹÓö¯Ì¬Ó³É䣬ÇëÐÞ¸Äprobeº¯ÊýÒÔÐÞ¶©µØÖ·Ó³Éä 

+* µ±Ç°°æ±¾:	1.1

+* ×÷¡¡¡¡Õß:	¹ùÒýÐã 

+* Íê³ÉÈÕÆÚ: 2011-8-1

+*

+* Ð޸ļǼ1

+* ÐÞ¸ÄÈÕÆÚ:

+* °æ±¾¡¡ºÅ:

+* Ð޸ġ¡ÈË:

+* ÐÞ¸ÄÄÚÈÝ:

+*

+*******************************************************************************/

+#include <linux/gmac/gmac.h>

+#include "zx_gmac.h"

+#include <mach/highspeed_debug.h>

+/*-----------------------------------------------------------------------------------

+* ºêÒåÒå

+------------------------------------------------------------------------------*/

+#define	LOG_TAG						"GMAC"

+

+#define DEV_NAME					"GMAC"

+#define  GMAC_NO_INT

+

+#ifdef GMAC_NO_INT

+#define GTIMER_INTERVAL  2000

+#endif

+/****************************************************************************

+* 	                               Global Variables

+****************************************************************************/

+struct wake_lock gmac_wake_lock;

+u8 gmac_addr[MAC_ADDR_LENTH] = {0xec,0x1d,0x7f,0xb0,0x2f,0x32};

+struct net_device* 	gmac_net_dev = NULL;

+struct zx_net_dev* 	gmac_net_dev_prv= NULL;

+

+static     char  *gmac_switch_name = "sw";

+static     char  *gmac_phy_name = "eth";

+

+char* dma_tx_vir_bak = NULL;

+unsigned	dma_rx_phy_bak= 0;	

+volatile unsigned	*g_gmac = NULL;

+struct tasklet_struct	*g_gmac_tasklet = NULL;

+ struct zx_net_dev	*g_gmac_dev = NULL;

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪµ÷ÓõÄÍⲿº¯Êý½Ó¿Ú

+* 

+* 

+------------------------------------------------------------------------------*/

+extern void readreg();

+extern void invalid_cache(unsigned char *data,int len);

+extern void clean_cache(unsigned char *data,int len);

+extern unsigned long  virtaddr_to_phys(unsigned long virt);

+extern unsigned long  physaddr_to_virt(unsigned long phys);

+extern int nand_NvRead(int dwStart, int dwLen, char* to);

+extern int nand_NvProgram(int dwStart, int dwLen, char* from);

+#ifdef CONFIG_NET_ZX29_GMAC_SWITCH

+extern int zx_gmac_switch_open(struct net_device *dev);

+extern int zx_gmac_switch_stop(struct net_device *dev);

+extern int  zx_gmac_switch_init(struct net_device *dev);

+extern int zx_gmac_switch_release(struct net_device *dev);

+E_LINK_STATE gmac_switch_linked(struct net_device *dev);

+#endif

+#ifdef CONFIG_NET_ZX29_GMAC_PHY

+extern int zx_gmac_phy_open(struct net_device *dev);

+extern int zx_gmac_phy_stop(struct net_device *dev);

+extern int  zx_gmac_phy_init(struct net_device *dev);

+E_LINK_STATE gmac_phy_link_status(struct net_device *dev);

+extern int zx_gmac_phy_release(struct net_device *dev);

+#endif

+extern void gmac_kick_plug_thread(void);

+

+#ifdef GMAC_NO_INT

+static void gmac_start_timer(void);

+static int gmac_stop_timer(void);

+#endif

+/*------------------------------------------------------------------------------

+* ÒÔÏÂΪ´úÂëÕýÎÄÇø

+* 

+* 

+------------------------------------------------------------------------------*/

+

+int gmac_mii_read(struct net_device *dev, int phy, int reg)

+{

+	unsigned long flags;

+    volatile unsigned 	*gmac 	= (unsigned*)dev->base_addr;

+    struct zx_net_dev	*prv 	= (struct zx_net_dev*)netdev_priv(dev);

+

+    unsigned val	= ( 1 	        << 0 	|		// busy λ

+    				     0 		 << 1 	|		// R/W²Ù×÷ָʾλ

+    				    PHY_CLOCK	<< 2)	|		// ʱÖÓλ

+    				    (reg & 0x1F)     << 6	       |		// ¼Ä´æÆ÷

+    				    (phy & 0x1F)     << 11;			// ÎïÀíоƬ

+

+spin_lock_irqsave(&prv->lock,flags);

+    while(mac_mii_is_busy());

+    MAC(0x0010)		= val;

+spin_unlock_irqrestore(&prv->lock,flags);

+

+    while(mac_mii_is_busy());

+

+    return (MAC(0x0014) & 0xFFFF);

+}

+

+void gmac_mii_write(struct net_device *dev, int phy, int reg, int val)

+{

+	volatile unsigned 	*gmac	= (unsigned*)dev->base_addr;

+	struct zx_net_dev	*prv 	= (struct zx_net_dev*)netdev_priv(dev);

+

+	unsigned data	= ( 1 	<< 0 	|		// busy λ

+					     1 	<< 1 	|		// R/W²Ù×÷ָʾλ

+					    PHY_CLOCK	<< 2)	|		// ʱÖÓλ

+					    (reg & 0x1F)     << 6	|		// ¼Ä´æÆ÷

+					    (phy & 0x1F)    << 11;			// ÎïÀíоƬ

+

+	spin_lock_irq(&prv->lock);

+

+	while(mac_mii_is_busy());

+	MAC(0x0014)		= val;

+	MAC(0x0010)		= data;

+

+	spin_unlock_irq(&prv->lock);

+

+	while(mac_mii_is_busy());

+}

+

+void gmac_set_speed_duplex(struct net_device *dev, E_SPEED speed, E_DUPLEX duplex)

+{

+    unsigned			val;

+    struct zx_net_dev* 	prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    int					phy 	= prv->phy;

+    volatile unsigned 	*gmac 	= (unsigned*)dev->base_addr;

+

+    val = MAC(0x0000) | 1<<11 | 1<<14;  // ĬÈÏΪ100Mȫ˫¹¤

+    if(eSPEED_10M == speed)

+    {

+        val &= ~(1 << 14);                  // 10M

+    }

+    if(eDUPLEX_HALF == duplex)

+    {

+        val &= (~(1 << 11));                    // °ëË«¹¤

+        val |= (1 << 16);

+    }

+    MAC(0x0000) = val;

+}

+

+

+

+static void mac_init(struct net_device *dev)

+{

+    volatile unsigned *gmac = (unsigned*)dev->base_addr;

+    unsigned int i=0, j=0, mac_rst=0;

+

+    mac_provide_clock();

+#ifdef __DEAD_LOOP_POLL__                       //////¿ÉÄÜ»áÔì³ÉËÀÑ­»·ÎÞ·¨Í˳ö£¬Äں˳õʼ»¯ÎÞ·¨¼ÌÐø/////////

+    mac_reset();  								// ¿ØÖÆÆ÷¸´Î»

+    mac_set_gmii_mode();						// MII½Ó¿Ú

+    mac_wait_reset_finished();

+#else                                           /////ÒÔÏÂÐ޸ĴúÂëÐèÒª½øÐÐÑϸñ²âÊÔ////////

+    //LOG_INFO("wait for gmac reseting");

+    for(i=0; i<MAC_RESET_NUM; i++)              /////Èí¸´Î»³¢ÊÔ´ÎÊý/////

+    {

+        mac_reset();

+        mac_set_mii_mode();                 //ÉèÖÃΪmiiģʽ£¬10m»òÕß100m

+        for(j=0; j<MAC_WAIT_TIME; j++)          /////²éѯ¸´Î»×´Ì¬³¬Ê±¼ÆÊýÑ­»·1´ÎÊÇ0.1ms////////

+        {

+            printk(".");

+            if(!((MAC(0x1000)) & 1))

+            {

+                printk("ok\n");

+                mac_rst = 1;

+                goto mac_reset_option;

+            } 

+            udelay(100);                        ////µÈ´ý 0.1ms

+        }

+    }

+mac_reset_option:

+    if(!mac_rst)                                ////gmacÍø¿¨macоƬûÓи´Î»³É¹¦//////

+    {

+        gmac_printk("gmac reset failed!\n");

+    }

+#endif

+    while(mac_mii_is_busy());

+}

+

+// Í£Ö¹Ó²¼þ¹¤×÷

+static void gmac_stop(void* io)

+{

+    volatile unsigned *gmac = (unsigned*)io;

+

+    dma_disable();

+    mac_disable();

+    mac_int_disable();

+

+    // Çå¿Õ·¢ËÍFIFO

+    dma_clear_tx_fifo();

+    dma_wait_tx_fifo_cleared();

+}

+

+// ʹÄÜÓ²¼þ¹¤×÷

+static void gmac_start(void* io)

+{

+    volatile unsigned *gmac = (unsigned*)io;

+

+    mac_int_enable();

+    dma_enable();

+    mac_enable();

+}

+

+// ´¥·¢´«Êä

+static void gmac_trig_transmit(void* io)

+{

+    volatile unsigned *gmac 	= (unsigned*)io;

+    register unsigned status	= (MAC(0x1014) >> 20) & 0x07;

+    switch(status)

+    {

+        case 0:		// ´«ÊäÍ£Ö¹£»¸´Î»»òÕßÍ£Ö¹ÃüÁî·¢ËÍ

+            dma_enable();

+            break;

+        case 6:		// ¹ÒÆð£»´«ÊäÃèÊö·û²»¿ÉÓûòÕß´«Ê仺´æÏÂÒç¡£

+            dma_continue_tx();

+            break;

+        case 1:		// ÕýÔÚ½øÐУ»»ñÈ¡´«ÊäÃèÊö·û

+        case 2:		// ÕýÔÚ½øÐУ»µÈ´ý´«Êä״̬

+        case 3:		// ÕýÔÚ½øÐУ»´Ó·¢ËÍ»º´æ¶ÁÈ¡Êý¾Ý²¢·¢Ë͵½´«Êä FIFO(TxFIFO)

+        case 4:		// дÈëʱ¼ä´Á״̬

+        case 5:		// ±£Áô

+        case 7:		// ÔËÐУ»¹Ø±Õ´«ÊäÃèÊö·û¡£

+        default:

+            break;

+    }

+}

+

+// ´¥·¢½ÓÊÕ

+static void gmac_trig_receive(void* io)

+{

+    volatile unsigned *gmac 	= (unsigned*)io;

+    register unsigned status	= (MAC(0x1014) >> 17) & 0x07;;

+    switch(status)

+    {

+        case 0:		// ֹͣ

+            dma_enable();

+            break;

+        case 4:		// ¹ÒÆð

+            dma_continue_rx();

+            break;

+        default:

+            break;

+    }

+}

+

+// ÉèÖÃÓ²¼þMACµØÖ·

+static inline void gmac_update_mac(struct net_device *dev)

+{

+    volatile unsigned *gmac = (unsigned*)dev->base_addr;

+    unsigned char *mac		= (unsigned char *)(dev->dev_addr);

+

+    MAC(0x0044)	= mac[0] | mac[1] << 8 | mac[2] << 16 | mac[3] << 24;

+    MAC(0x0040) = mac[4] | mac[5] << 8;

+

+    //LOG_INFO("MAC: %02X-%02X-%02X-%02X-%02X-%02X\n", mac[5], mac[4], mac[3], mac[2], mac[1], mac[0]);

+}

+

+/*******************************************************************************

+* ÉèÖùýÂËÆ÷

+* ½ÓÊÜËùÓеÄÓë×ÔÉíMACÏà·ûµÄµ¥²¥Ö¡

+* ²»½ÓÊܶಥ֡

+* ½ÓÊܹ㲥֡

+*******************************************************************************/

+static void gmac_set_filter(struct net_device *dev)

+{

+	volatile unsigned *gmac = (unsigned*)dev->base_addr;

+

+	MAC(0x0004)	=	(0 << 31)	|				// Ö¡¹ýÂË: ÆôÓùýÂË: ²»½ÓÊÕËùÓÐÖ¡

+					(1 << 10)	|				// ¹þÏ£ÓëÍêÈ«¹ýÂËʹÄÜ: ʹÄܹþÏ£ÓëÍêÈ«¹ýÂË

+					(0 << 9)	|				// Ô´µØÖ·Óò¹ýÂË: ¹Ø±Õ

+					(3 << 6)	|				// ¸ù¾ÝµØÖ·¹ýÂËÇé¿ö½ÓÊÕ¿ØÖÆÖ¡

+					(0 << 5)	|				// ¹ã²¥Ö¡¹ýÂË: ²»¹ýÂËËùÓнÓÊյĹ㲥֡

+					(0 << 4)	|				// ¶à²¥Ö¡: ¹ýÂËËùÓжಥ֡

+					(0 << 3)	|				// ¶Ôµ¥²¥ºÍ¶à²¥Ö¡½øÐÐÕý³£Ä¿±êµØÖ·Æ¥Åä

+					(0 << 2)	|				// Ϊ1ʱ¶Ô½ÓÊÕµ½µÄ¶à²¥Ö¡¸ù¾Ý¹þÏ£±íµÄÄÚÈݽøÐÐÄ¿±êµØÖ·¹ýÂË

+					(0 << 1)	|				// Ϊ1ʱ¶Ô½ÓÊÕµ½µÄµ¥²¥Ö¡¸ù¾Ý¹þÏ£±íµÄÄÚÈݽøÐÐÄ¿±êµØÖ·¹ýÂË

+					(0 << 0);					// ²»½ÓÊÕËùÓÐÒÔÌ«ÍøÖ¡

+

+	gmac_update_mac(dev);

+}

+

+// È¡µÃµ±Ç°µÄ½ÓÊÕÃèÊö·û

+static struct bd_rx *get_rx_bd(struct net_device *dev)

+{

+    struct zx_net_dev* prv 		= (struct zx_net_dev*)netdev_priv(dev);

+    int   n						= prv->rx_bd_offset;

+    struct bd_rx *d				= (struct bd_rx*)prv->dma_rx_vir;

+

+    if(d[n].RDES0 & DMA_OWNER) 

+    {

+        return 0;

+    }

+    else	

+    {

+        return &d[n];

+    }

+}

+

+static inline int mod_sub(int left, int right, int mod)

+{

+    return (mod - right + left) % mod;

+}

+

+// È¡µÃµ±Ç°µÄ·¢ËÍÃèÊö·û

+static inline struct bd_tx *get_tx_bd(struct net_device *dev)

+{

+    struct zx_net_dev* prv 		= (struct zx_net_dev*)netdev_priv(dev);

+    int   n						= prv->tx_bd_offset;

+    struct bd_tx *d				= (struct bd_tx*)prv->dma_tx_vir;

+	

+    if( mod_sub(prv->tx_bd_offset, prv->txed_bd, GMAC_TX_BD_NUM) > GMAC_TX_BD_NUM - 2 )  

+	{

+		return 0;

+	}

+		

+    if(d[n].TDES0 & DMA_OWNER) 	

+    {

+        return 0;

+    }

+    else

+    {

+        return &d[n];

+    }

+}

+

+

+// È¡µÃÒÑ·¢ËÍÃèÊö·û

+static struct bd_tx *get_txed_bd(struct net_device *dev)

+{

+    struct bd_tx *d;

+    struct zx_net_dev* prv 		= (struct zx_net_dev*)netdev_priv(dev);

+    int n						= prv->txed_bd;

+

+    d	= (struct bd_tx*)prv->dma_tx_vir;

+

+	if(n == prv->tx_bd_offset) return 0;

+	

+    if(d[n].TDES0 & DMA_OWNER)	return 0;

+	

+	if(d[n].skb == NULL) return 0; 

+

+    prv->txed_bd++;

+    prv->txed_bd %= GMAC_TX_BD_NUM;

+

+    return &d[n];

+}

+

+// Ó²¼þÈ¥³õʼ»¯

+static void hw_net_uninit(struct net_device *dev)

+{

+    int 				i;

+    struct bd_rx 		*rx_bd;

+	struct bd_tx 		*tx_bd;

+    volatile unsigned 	*gmac	= (unsigned*)dev->base_addr;

+    struct zx_net_dev	*prv	= (struct zx_net_dev*)netdev_priv(dev);

+

+    gmac_stop((void*)dev->base_addr);

+

+    // ×¢Òârx tx Ò»ÆðÏú»Ù

+    if(prv->dma_rx_phy)

+    {

+        rx_bd   = (struct bd_rx*)prv->dma_rx_vir;

+

+        for(i = 0; i < GMAC_RX_BD_NUM; i++)

+        {

+        	if(rx_bd[i].skb != NULL)

+        	{        

+ 	           dev_kfree_skb_any(rx_bd[i].skb);

+        	}

+        }

+

+		tx_bd   = (struct bd_tx*)prv->dma_tx_vir;

+		

+        for(i = 0; i < GMAC_TX_BD_NUM; i++)

+        {

+        	if(tx_bd[i].skb != NULL)

+        	{

+            	dev_kfree_skb_any(tx_bd[i].skb);

+        	}

+        }

+

+       // dma_free_coherent(NULL, GMAC_BUF_LEN, prv->dma_rx_vir, prv->dma_rx_phy);   //ÊÍ·Ådma»º³åÇø

+    }

+

+    dma_set_tx_buffer(0);   //ÉèÖÃÊ׸öBDµÄ»º³åÇøÎª0£»

+    dma_set_rx_buffer(0);

+

+    prv->rx_bd_offset	= 0;

+    prv->tx_bd_offset	= 0;

+    prv->txed_bd		= 0;

+    prv->dma_rx_phy		= 0;

+    prv->dma_rx_vir		= 0;

+    prv->dma_tx_phy		= 0;

+    prv->dma_tx_vir		= 0;

+}

+

+static int gmac_init_rx_bd(struct net_device *dev, struct zx_net_dev* prv)

+{

+    struct sk_buff	*skb = NULL;

+    struct bd_rx *rx  = (struct bd_rx *)prv->dma_rx_vir;

+    int 			i = 0;	

+

+    prv->rx_bd_offset		= 0;

+

+	for(i = 0; i < GMAC_RX_BD_NUM; i++)

+	{

+		// ½ÓÊÕÃèÊö·û³õʼ»¯

+		// ½ÓÊÕÃèÊö·ûµÄÊý¾Ý»º³åÇøÎª SKBµÄdata¶Î£¬¹ÊÏÈ·ÖÅäÏàÓ¦ÊýÁ¿µÄskb£¬

+		// ¹ÒÔÚ½ÓÊÕÃèÊö·û»·»ØÁ´±íÉÏ£¬µ±GMACÓ²¼þ½«Êý¾Ý±£´æºó£¬½«¸Ãskbȡϣ¬Ë͸øÐ­ÒéÉϲã

+		// Í¬Ê±ÒªÖØÐ·ÖÅäÒ»¸öSKB£¬ÔÙ¹Òµ½½ÓÊÕÃèÊö·û»·»ØÁ´±íÉÏ

+

+		skb = netdev_alloc_skb(dev, GMAC_FRAME_LEN + NET_IP_ALIGN);

+

+		if(unlikely(!skb))

+		{

+		   // LOG_ERR("kmalloc memory failed\n");

+			hw_net_uninit(dev);

+			return -1;

+		}

+

+		skb_reserve(skb, NET_IP_ALIGN);

+

+		rx[i].RDES0 	   |= DMA_OWNER;

+		rx[i].RDES1  = 0;

+		rx[i].RDES1 	   = GMAC_FRAME_LEN | 1 << 14;

+		rx[i].dma_buf		= virtaddr_to_phys((unsigned)skb->data);

+		rx[i].next			= prv->dma_rx_phy + ((i + 1) << 5);

+		rx[i].skb			= skb;

+#if 0

+		if(i%4 != 0)

+		{

+	       rx[i].RDES1  |= 0x80000000;

+		}

+#endif

+		dma_sync_single_for_device(&dev->dev, rx[i].dma_buf, GMAC_FRAME_LEN, DMA_TO_DEVICE);

+

+	}

+

+	// Ï´ÎÊǶÔÁ´±í½øÐл·»Ø´¦Àí

+	rx[GMAC_RX_BD_NUM-1].next			= prv->dma_rx_phy;

+	rx[GMAC_RX_BD_NUM-1].RDES1 			= GMAC_FRAME_LEN	  | 1 << 14 | 1 << 15;

+

+	return 0;

+}

+

+static void gmac_init_tx_bd(struct zx_net_dev* prv)

+{

+    struct bd_tx *tx  = (struct bd_tx *)prv->dma_tx_vir;

+

+    int 			i = 0;

+

+    prv->tx_bd_offset		= 0;

+    prv->txed_bd			= 0;

+

+    for(i = 0; i < GMAC_TX_BD_NUM; i++)

+    {

+        // ·¢ËÍÃèÊö·û³õʼ»¯

+        // ·¢ËÍÃèÊö·ûµÄÊý¾Ý»º³åÇøÎª SKBµÄdata¶Î£¬¹Ê²»ÐèÒªÊý¾Ý»º³åÇø£¬

+        // ·¢ËÍʱ½«¸ÃSKBµÄÊý¾ÝÇø¹ÒÔÚ·¢ËÍÃèÊö·û»·»ØÁ´±íÉÏ£¬µ±GMACÓ²¼þ½«Êý¾ÝÊý¾Ý·¢Ëͺó£¬Ôݲ»´¦Àí£¬µÈ»·»ØÁ´±íÖØÐÂÈÆ»ØÊ±ÔÙ´¦Àí

+

+        tx[i].TDES0       	= (1 << 20 | 1 << 30);

+        tx[i].TDES1       	= GMAC_FRAME_LEN;

+        tx[i].next			= prv->dma_tx_phy + ((i + 1) << 5);

+    }

+

+    // Ï´ÎÊǶÔÁ´±í½øÐл·»Ø´¦Àí

+    tx[GMAC_TX_BD_NUM-1].next		    	= prv->dma_tx_phy;

+    tx[GMAC_TX_BD_NUM-1].TDES0            	= 1 << 20 | 1 << 21 | 1 << 30;	

+}

+

+// Ó²¼þ³õʼ»¯

+static int hw_net_init(struct net_device *dev)

+{

+	int ret = -1;

+    unsigned 		val;

+

+    volatile unsigned *gmac	= (unsigned*)dev->base_addr;   //WL  ÍøÂçÉ豸µÄIO»ùµØÖ·

+    struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(dev);

+   // rtk_mode_ext_t *Mode ;

+   // rtk_port_mac_ability_t portAbility;

+

+    // ÉêÇë·¢ËÍÓë½ÓÊÕÃèÊö·û»º³åÇø

+    // ʹÓÃSKBµÄdataÇø×÷ΪÊý¾Ý»º³åÇø£¬¹Ê²»ÐèÒª·ÖÅäÊý¾Ý»º³åÇø

+

+    if(prv->dma_rx_phy)

+    {

+        //LOG_DBG(4, "dma buffer has alloc, uninit hardware first\n");

+        hw_net_uninit(dev);

+    }

+

+    if(!prv->stopped)

+    {

+		prv->dma_rx_vir	= dma_alloc_coherent(NULL,

+							GMAC_BUF_LEN,

+						&prv->dma_rx_phy,

+						GFP_KERNEL);

+

+		if(0 == prv->dma_rx_vir)

+		{

+			prv->dma_rx_phy		= 0;						// ·ÖÅäʧ°Üʱ£¬¿ÉÄÜ»áÓеØÖ·Öµ

+			//LOG_ERR("alloc DMA buffer failed\n");

+			return -ENOMEM;

+		}

+		else

+		{

+			dma_tx_vir_bak = prv->dma_rx_vir;

+			dma_rx_phy_bak = prv->dma_rx_phy;

+		}

+    }

+    else

+    {

+		prv->dma_rx_vir = dma_tx_vir_bak;

+		prv->dma_rx_phy = dma_rx_phy_bak ;

+    }

+      // Ç°ÃæÎª 1 << CONFIG_GMAC_BUF_NUM ¸ö ½ÓÊÕÃèÊö·û

+    // ºóÃæÎª 1 << CONFIG_GMAC_BUF_NUM ¸ö ·¢ËÍÃèÊö·û

+    prv->dma_tx_vir	= prv->dma_rx_vir + GMAC_RX_BUF_LEN;

+    prv->dma_tx_phy	= prv->dma_rx_phy + GMAC_RX_BUF_LEN;

+

+    // ¶ÔÃèÊö·ûÊý¾ÝÇøÇåÁã

+    memset(prv->dma_rx_vir, 0, GMAC_BUF_LEN);

+

+    //LOG_INFO("alloc dma buffer at 0x%8X(0x%8X) size 0x%08X\n", (unsigned)prv->dma_rx_vir, prv->dma_rx_phy, 0x40 << CONFIG_GMAC_BUF_NUM);

+

+//ec616000600086,should check init_rx result

+    ret = gmac_init_rx_bd(dev, prv);

+	if(ret < 0)

+	{

+		printk("hw_net_init,init_rx_bd fail\n");

+		return ret;

+	}

+    gmac_init_tx_bd(prv);

+

+    // ÒÔÏÂÊÇÓ²¼þ³õʼ»¯

+    mac_init(dev);

+

+    // ¹Ø±ÕGMACËùÓй¦ÄÜ

+    dma_disable();

+    mac_disable();

+    mac_int_disable();

+

+    // ÉèÖÃÍ»·¢´«Ê䳤¶È

+    val		 	= MAC(0x1000);

+    

+    val			&= ~(0x3F << 8);

+    val			|=  (0x10 << 8);    //burst 16

+    

+   // val                   &= ~(0xDFF << 8);

+  //val                   |=  (0x1 << 8);    //burst 16

+

+    MAC(0x1000)	 = val;

+

+    //  ÉèÖýÓÊÕÓë·¢ËÍÃèÊö·û

+    dma_set_rx_buffer(prv->dma_rx_phy);

+    dma_set_tx_buffer(prv->dma_tx_phy);

+

+    mac_int_clear(0x0001FFFF);								// ÖжÏÇå³ý

+    while(mac_mii_is_busy());

+

+    MAC(0x0000)  |= (0x1<<14)|(0x1<<11);                                   //ÉèÖÃMacµÄspeedΪ100m£¬È«Ë«¹¤

+    mac_rece_all_data();									// ½ÓÊÕËùÓÐÊý¾Ý

+    //gmac_set_filter(dev);                                                          //²âÊÔʱ¿ÉÒÔ²»Óôò¿ª

+

+    return 0;

+}

+

+// ´ò¿ªÍøÂçÉ豸

+static int zx_net_open(struct net_device *dev)

+{

+    int ret;

+    struct zx_net_dev* prv	= (struct zx_net_dev*)netdev_priv(dev);

+        /*for 616000599226,phy not link ,so return fail 

+	        */	

+    if(eLINK_OFF == prv->link)

+    {

+    	printk("zx_net_open,no link, fail\n");

+    	return -ENOENT;

+    }

+

+    ret	= hw_net_init(dev);

+    

+    if(ret)		

+		return ret;

+

+    gmac_start((void*)dev->base_addr);

+	

+    netif_carrier_on(dev);

+	

+    ret = prv->open(dev);

+    if(ret)		return ret;

+

+    netif_start_queue(dev);

+

+    prv->stopped = 0;

+

+#ifdef GMAC_NO_INT

+	gmac_start_timer();

+#endif

+    

+    gmac_printk("TSP zx29 gmac net open\n");

+    return 0;

+}

+

+// ¹Ø±ÕÍøÂçÉ豸

+static int zx_net_stop(struct net_device *dev)

+{

+    unsigned long       flags = 0;

+    

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+    

+    spin_lock_irqsave(&prv->lock, flags);

+	

+#ifdef GMAC_NO_INT

+	gmac_stop_timer();

+#endif

+

+    prv->stopped = 1;

+    

+    netif_stop_queue(dev);

+    netif_carrier_off(dev);

+	

+    prv->stop(dev);

+	

+    hw_net_uninit(dev);

+    

+    memset(&dev->stats, 0, sizeof(struct net_device_stats));

+    

+    spin_unlock_irqrestore(&prv->lock,flags);

+    

+    gmac_printk("TSP zx29 gmac net stop\n");

+

+    return 0;

+}

+

+// ·¢Ëͺ¯Êý

+static int zx_net_start_xmit(struct sk_buff *skb, struct net_device *dev)

+    {

+    unsigned long       flags;

+    unsigned 			len;

+    struct sk_buff		*skb_old;

+    struct bd_tx 		*tx;

+    struct zx_net_dev* 	prv		= (struct zx_net_dev*)netdev_priv(dev);

+    unsigned int  retVal = 0;

+    if(eLINK_OFF == prv->link)

+    {

+        /*for 616000599226,phy not link ,so free skb 

+	        */

+        dev_kfree_skb_any(skb);

+    	//netif_stop_queue(dev);

+        gmac_printk("TSP zx29 gmac xmit  phy not link\n");   

+        return NETDEV_TX_OK;

+    }

+    

+    // ÔÚÈ¡µÃÃèÊö·ûʱÐèÒª»¥³â²Ù×÷

+

+    spin_lock_irqsave(&prv->lock, flags);

+

+    if(prv->stopped)

+    {

+        spin_unlock_irqrestore(&prv->lock,flags);

+        dev_kfree_skb_any(skb);

+        

+        gmac_printk("zx_net_start_xmit when stopped\n");

+        

+        return NETDEV_TX_OK;

+    }

+

+    tx	= get_tx_bd(dev);

+

+    if(!tx)

+    {

+        spin_unlock_irqrestore(&prv->lock,flags);

+        dev_kfree_skb_any(skb);

+        return NETDEV_TX_OK;

+    }

+    prv->tx_bd_offset++;

+    prv->tx_bd_offset %= GMAC_TX_BD_NUM;

+    spin_unlock_irqrestore(&prv->lock, flags);

+

+    if(skb->len > ETH_FRAME_LEN + 4)	//LOG_INFO("tx length too big\n");

+    gmac_printk("TSP zx29 gmac start xmit len too long\n");

+

+    // È¡µÃÃèÊö·ûÉϹÒ×ŵÄSKB£¬È»ºó½«¸ÃSKBÏú»Ù(¸ÃSKBµÄÊý¾ÝÒÑ·¢ËÍ)

+    // ÔÙ½«ÐµÄSKB¹ÒÉÏÈ¥(°üÀ¨SKBµØÖ·£¬ÒÔ¼°skb->data¶ÎµÄÎïÀíµØÖ·£¬ÓÃÓÚGMAC·¢ËÍÊý¾ÝÖ®ÓÃ)

+    // ×¢ÒâÔÚ½«skb->data¶ÎµÄÊý¾Ý·¢ËÍËùÓÐȨ½»¸øGMAC֮ǰ£¬ÐèÒª¶Ôdata¶ÎµÄÊý¾Ý½øÐÐCACHEͬ²½´¦Àí

+    // ÒòΪskb->dataµÄÊý¾ÝÊÇcachedµÄ

+

+    //wl skb_old		 = tx->skb;

+    //flush_skbuf(skb);

+

+    skb= flush_skbuf(skb);

+	if(NULL == skb)

+		BUG_ON(1);   

+    len 		        = MIN(skb->len, GMAC_FRAME_LEN - NET_IP_ALIGN);

+    tx->TDES0	      |= (0x07 << 28);					// ÉèÖÃ״̬±ê¼ÇΪ֡µÄµÚÒ»¸öÊý¾Ý°ü£¬×îºóÒ»¸öÊý°ü£¬Íê³ÉºóÖжÏ(Ò»Ö¡Ò»¸öÊý¾Ý°ü)

+    //tx->dma_buf	 = __virt_to_phys((unsigned)skb->data);

+    tx->dma_buf	 = virtaddr_to_phys((unsigned)skb->data);

+    tx->skb		 = skb;

+

+    // Êý¾ÝдÈëͬ²½

+    // dma_sync_single_for_device(&dev->dev, tx->dma_buf, len, DMA_TO_DEVICE);

+    //wl dev_kfree_skb_any(skb_old);

+      

+    tx->TDES1 	 = len;

+    tx->TDES0 	|= DMA_OWNER;

+

+    //prv->tx_bd_offset++;

+    //prv->tx_bd_offset %= GMAC_TX_BD_NUM;

+    wmb();

+    dev->stats.tx_bytes			+= len;

+    dev->stats.tx_packets++;

+    dev->trans_start			= jiffies;

+

+    gmac_trig_transmit((void*)dev->base_addr);

+    

+    return NETDEV_TX_OK;

+}

+

+// ³¬Ê±´¦Àíº¯Êý: ¸Ãº¯Êý²»ÔÙÖØÐ¶ÔÓ²¼þÍêÈ«³õʼ»¯

+static void zx_net_timeout(struct net_device *dev)

+{

+    struct zx_net_dev* prv	= (struct zx_net_dev*)netdev_priv(dev);

+	

+    prv->link= prv->link_state(dev);

+	

+    if(eLINK_OFF == prv->link)

+    {	

+        gmac_printk("TSP zx29 gmac net timeout phy not link\n");                                            // PHY δÁ¬½Ó

+        netif_stop_queue(dev);

+        netif_carrier_off(dev);

+    }

+    else

+    {

+        gmac_printk("TSP zx29 gmac net timeout phy linked\n"); 

+        gmac_trig_transmit(dev);

+        gmac_trig_receive(dev);

+

+        netif_carrier_on(dev);

+        netif_wake_queue(dev);

+        dev->trans_start 		= jiffies;

+        dev->stats.tx_errors++;

+        dev->stats.tx_dropped++;

+    }

+}

+

+// ÉèÖÃMACµØÖ·

+static int zx_net_set_mac_address(struct net_device *dev, void *p)

+{

+    int ret = eth_mac_addr(dev, p);

+	

+    if(!ret) {

+		gmac_update_mac(dev);

+		gmac_printk(" zx29 gmac set mac addr ok\n");

+    }

+

+    return ret;

+}

+

+u32 zx_net_get_link(struct net_device *dev)

+{

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+    int ret = -1;

+

+    spin_lock_irq(&prv->phy_lock);

+    ret = prv->link;

+    spin_unlock_irq(&prv->phy_lock);

+

+    return ret;

+}

+

+static int zx_net_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)

+{

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+    int ret = -1;

+

+    spin_lock_irq(&prv->phy_lock);

+    cmd->advertising = prv->set_duplex_mode;

+    cmd->autoneg = prv->autoneg;

+    spin_unlock_irq(&prv->phy_lock);

+

+    ret = 0;

+

+    return ret;

+}

+

+static int zx_net_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)

+{

+    u32 speed = ethtool_cmd_speed(cmd);

+    E_SPEED physpeed;

+    E_DUPLEX phyduplex;

+

+    struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+

+    spin_lock_irq(&prv->phy_lock);

+    if(cmd->advertising == prv->set_duplex_mode)

+    {

+        spin_unlock_irq(&prv->phy_lock);

+        return 0;

+    }

+    spin_unlock_irq(&prv->phy_lock);

+

+    //LOG_INFO("zx_net_set_settings cmd->advertising=%d\n", cmd->advertising);

+    // LOG_INFO("zx_net_set_settings cmd->autoneg=%d\n", cmd->autoneg);

+

+    //verify the setting we care about

+    if(cmd->autoneg == AUTONEG_DISABLE &&

+    ((speed != SPEED_100 &&

+    speed != SPEED_10) ||

+    (cmd->duplex != DUPLEX_HALF &&

+    cmd->duplex != DUPLEX_FULL)))

+    return -EINVAL;

+

+    if(cmd->autoneg == AUTONEG_ENABLE)

+    {

+        prv->autoneg    =   AUTONEG_ENABLE;

+       //return phy_negotiation(dev);

+       return 0;

+    }

+

+    physpeed = (speed == SPEED_10) ? eSPEED_10M : eSPEED_100M;

+    phyduplex = (cmd->duplex == DUPLEX_HALF) ? eDUPLEX_HALF : eDUPLEX_FULL;

+

+   // return phy_set_speed_duplex(dev, physpeed, phyduplex);

+   return  0;

+}

+

+static const struct ethtool_ops zx_net_ethtool_ops = 

+{

+    .get_settings	= zx_net_get_settings,

+    .set_settings	= zx_net_set_settings,

+    .get_link		= zx_net_get_link,

+};

+

+static inline int phy_mc_hash(__u8 *addr)

+{

+	return (bitrev32(~ crc32_le(~0, addr, ETH_ALEN)) >> 26);

+}

+

+// ÉèÖöಥHASH¹ýÂË

+static void zx_set_multicast(struct net_device *dev)

+{

+    volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+

+    if(dev->flags & IFF_PROMISC) 

+    {

+        MAC(0x0004)    |= 1 << 31;		// Ö¡¹ýÂË: ½ÓÊÕËùÓÐÖ¡

+    } 

+    else if(dev->flags & IFF_ALLMULTI) 

+    {

+        MAC(0x0008) 	= 0xffffffff;

+        MAC(0x000C) 	= 0xffffffff;

+        MAC(0x0004)     |= 1 << 2;

+        MAC(0x0004)    &= ~(1 << 31);	// Ö¡¹ýÂË: ÆôÓùýÂË: ²»½ÓÊÕËùÓÐÖ¡

+    } 

+    else if(dev->mc.count > 0) 

+    {

+        u32		hash[2];

+        u32		hash_id;

+        struct	netdev_hw_addr *ha;

+

+        hash[0]		= 0;

+        hash[1]		= 0;

+

+        netdev_hw_addr_list_for_each(ha, &dev->mc)

+        {

+        	hash_id	= phy_mc_hash(ha->addr);

+        	

+        	if(hash_id > 31) 

+        	{

+        		hash[1] |= 1 << (hash_id - 32);

+        	} 

+        	else 

+        	{

+        		hash[0] |= 1 << hash_id;

+        	}

+        }

+

+        MAC(0x0004)    &= ~(1 << 31);	// Ö¡¹ýÂË: ÆôÓùýÂË: ²»½ÓÊÕËùÓÐÖ¡

+        MAC(0x0004)    |= 1 << 2;

+

+        if((MAC(0x000C) == hash[0]) && (MAC(0x0008) == hash[1])) return;

+

+        MAC(0x0008) 	= hash[1];

+        MAC(0x000C) 	= hash[0];

+    } 

+    else 

+    {

+        MAC(0x0008) 	= 0x0;

+        MAC(0x000C) 	= 0x0;

+        MAC(0x0004)    |= 1 << 2;

+        MAC(0x0004)    &= ~(1 << 31);	// Ö¡¹ýÂË: ÆôÓùýÂË: ²»½ÓÊÕËùÓÐÖ¡

+    }

+}

+

+static const struct net_device_ops zx_net_netdev_ops =

+{

+    .ndo_open				= zx_net_open,

+    .ndo_stop				= zx_net_stop,

+    .ndo_start_xmit			= zx_net_start_xmit,

+    .ndo_tx_timeout			= zx_net_timeout,

+   // .ndo_set_multicast_list =  zx_set_multicast,

+    .ndo_change_mtu		= eth_change_mtu,

+    .ndo_validate_addr		= eth_validate_addr,

+    .ndo_set_mac_address	= zx_net_set_mac_address,

+};

+

+// ½ÓÊÕº¯Êý

+static int zx_net_rx(struct net_device *dev)

+{

+	struct bd_rx 	*rx;

+	struct sk_buff	*skb;

+	struct sk_buff	*skb_new;

+	unsigned		len;

+	int   exhausted = 0;

+

+	struct zx_net_dev* prv = (struct zx_net_dev*)netdev_priv(dev);

+

+    rx  = get_rx_bd(dev);

+

+    if(unlikely(!rx))	goto rcv_done;

+

+    while(rx)

+    {

+        if((rx->RDES0 & ERR_RX_ES) || (rx->RDES0 & ERR_RX_LE))

+        {

+            dev->stats.rx_errors++;

+            if(rx->RDES0 & ERR_RX_LE)	dev->stats.rx_length_errors++;

+            if(rx->RDES0 & ERR_RX_OE)	dev->stats.rx_over_errors++;

+            if(rx->RDES0 & ERR_RX_IPC)	dev->stats.rx_frame_errors++;

+            if(rx->RDES0 & ERR_RX_LC)	dev->stats.rx_fifo_errors++;

+            if(rx->RDES0 & ERR_RX_CE)	dev->stats.rx_crc_errors++;

+        }

+        else

+        {

+            // ¶Ô½ÓÊÕÊý¾Ý½øÐд¦Àí

+            // ½«»·»ØÁ´±íÖеÄskbÈ¡³ö£¬²¢½«Ð·ÖÅäÐÂskb¹ÒÉÏ£¬ÓÃÓÚ½ÓÊÕÊý¾Ý

+            // ´ËʱËùÓÐÊý¾ÝÒѾ­±£´æÔÚskb->dataÖÐÁË£¬µ«ÊÇÊý¾Ý³¤¶Èskb»¹²»ÖªµÀ£¬²¢ÇÒÊý¾Ý»¹Ã»ÓÐCACHEͬ²½

+            // ¶Ôskb½øÐÐÊý¾Ý³¤¶È¡¢Êý¾Ýͬ²½´¦Àí

+            // È»ºóÉϱ¨¸øÐ­ÒéÉϲã

+

+            len = ((rx->RDES0 >> 16) & 0x3FFF) - 4;

+            if(len  > (ETH_FRAME_LEN+8))  

+            {

+            //LOG_INFO("rx data length more than %d\n", ETH_FRAME_LEN);

+                dev->stats.rx_dropped++;

+                goto rx_bd_reset;

+            }

+

+            skb_new = netdev_alloc_skb(dev, GMAC_FRAME_LEN + NET_IP_ALIGN);

+            if(unlikely(!skb_new))

+            {

+                //LOG_DBG(3, "memory squeeze, dropping packet\n");

+                dev->stats.rx_dropped++;

+				exhausted++;

+            }

+            else

+            {	

+            	exhausted = 0;

+            	dev->stats.rx_packets++;

+				dev->stats.rx_bytes += len;

+				// Êý¾Ý¶Áȡͬ²½DMA buffer ¸üиøcpu

+				dma_sync_single_for_cpu(&dev->dev, rx->dma_buf, GMAC_FRAME_LEN, DMA_FROM_DEVICE);

+                skb				= rx->skb;

+                skb_put(skb, len);

+                skb->protocol 		= eth_type_trans(skb, dev);

+                netif_rx(skb);		

+				

+                skb_reserve(skb_new, NET_IP_ALIGN);

+                //rx->dma_buf    		= __virt_to_phys((unsigned)skb_new->data);

+                rx->dma_buf    		= virtaddr_to_phys((unsigned)skb_new->data);

+                rx->skb			= skb_new;

+				wmb();

+                // Êý¾Ý¶Áȡͬ²½¸øÉ豸

+				dma_sync_single_for_device(&dev->dev, rx->dma_buf, GMAC_FRAME_LEN, DMA_TO_DEVICE); //TODO

+            }

+        }

+        rx_bd_reset:

+        rx->RDES0 = rx->RDES0 | DMA_OWNER;

+        prv->rx_bd_offset++;

+        prv->rx_bd_offset %= GMAC_RX_BD_NUM;

+		wmb();

+		

+		if(exhausted >= 10)

+			break;

+	

+        gmac_trig_receive((void*)dev->base_addr);     //´¥·¢½ÓÊÕ£¬»ñÈ¡½ÓÊÕ´«ÊäÃèÊö·û

+        rx	= get_rx_bd(dev);

+    }

+

+    rcv_done:

+    gmac_trig_receive((void*)dev->base_addr);

+	

+	return (exhausted >= 10);

+}

+

+

+// ·¢ËÍÖжϴ¦Àíº¯Êý

+static void zx_net_tx(struct net_device *dev)

+{

+    register unsigned status;

+    struct net_device_stats	s	= dev->stats;

+    struct bd_tx *tx 			= get_txed_bd(dev);

+

+    while(tx)

+    {

+        status	= tx->TDES0;

+

+        if(tx->TDES0 & ERR_TX_ES)

+        {

+            s.tx_errors++;

+            if(status & ERR_TX_LC)		s.tx_carrier_errors++;

+            if(status & ERR_TX_NC)		s.tx_carrier_errors++;

+            if(status & ERR_TX_EC)		s.tx_window_errors++;

+            if(status & ERR_TX_LATECOL)	s.tx_window_errors++;

+            if(status & ERR_TX_UF)		s.tx_aborted_errors++;

+            if(status & ERR_TX_ED)		s.tx_aborted_errors++;

+            if(status & ERR_TX_JT)		s.tx_fifo_errors++;

+            if(status & ERR_TX_FF)		s.tx_fifo_errors++;

+

+            //LOG_DBG(3, "%s %ld\n", __FUNCTION__, s.tx_errors);

+        }

+	dev_kfree_skb_any( tx->skb);  //wl

+	tx->skb = NULL;

+	tx = get_txed_bd(dev);      

+    }

+

+   if(netif_queue_stopped(dev))

+  // if (netif_carrier_ok(dev))

+    {

+        netif_wake_queue(dev);    //ʹµÃÉϲãЭ¶¨¿ªÊ¼´«ËÍеÄ×ÊÁÏÏÂÀ´

+    }

+}

+

+#ifndef GMAC_NO_INT

+// GMAC ÈíÖжϴ¦Àíº¯Êý

+void zx_net_tasklet(unsigned long dev_id)

+{

+    struct net_device* dev 		= (struct net_device*)dev_id;

+    struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+

+    unsigned events				= prv->int_event;								// ¶ÁÈ¡ÖжÏÖб£´æµÄÖжϱê¼Ç

+

+    // ¶ÔGMACÖжϽøÐÐÊÂÎñ´¦Àí£¬Ö±µ½Ã»ÓÐÖжÏ(ÊÂÎñ)ÐèÒª´¦Àí

+    do

+    {

+        if(events & INT_ST_TX)

+        {

+            zx_net_tx(dev); 

+        }                                                     

+        if(events & INT_ST_RX)	    

+        {

+            zx_net_rx(dev);

+        }

+

+        events			= MAC(0x1014);

+        MAC(0x1014)		= events;

+

+    } while( events & (INT_ST_TX | INT_ST_RX));

+

+    // ´ËʱGMACµÄÖжÏÊǹرյģ¬ÐèÒªÔٴδò¿ª

+    mac_int_enable();															// ÔÊÐíGMACÔٴβúÉúÖжÏ

+}

+#else

+// GMAC ÈíÖжϴ¦Àíº¯Êý

+void zx_net_tasklet(unsigned long dev_id)

+{

+    struct net_device* dev 		= (struct net_device*)dev_id;

+    struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+	int rx_result = 0;

+    unsigned events				= prv->int_event;								// ¶ÁÈ¡ÖжÏÖб£´æµÄÖжϱê¼Ç

+

+    // ¶ÔGMACÖжϽøÐÐÊÂÎñ´¦Àí£¬Ö±µ½Ã»ÓÐÖжÏ(ÊÂÎñ)ÐèÒª´¦Àí

+    do

+    {

+        if(events & INT_ST_TX)

+        {

+            zx_net_tx(dev); 

+        }                                                     

+        if(events & INT_ST_RX)	    

+        {

+           rx_result = zx_net_rx(dev);

+			if(rx_result)//this means skb is exhausted,so break task

+				break;

+        }

+

+        events			= MAC(0x1014);

+        MAC(0x1014)		= events;

+

+    } while( events & (INT_ST_TX | INT_ST_RX));

+

+    // ´ËʱGMACµÄÖжÏÊǹرյģ¬ÐèÒªÔٴδò¿ª

+   // mac_int_enable();															// ÔÊÐíGMACÔٴβúÉúÖжÏ

+}

+static unsigned int gmac_sema_up_flag = 0;

+//DEFINE_SEMAPHORE(gmac_thread_sema);

+struct semaphore gmac_thread_sema;

+struct hrtimer *gmac_timer;

+

+static void gmac_kick_thread(void)

+{

+    unsigned  *gmac      = NULL;

+    unsigned   events    = 0;

+    

+	gmac        = g_gmac;

+    events	    = MAC(0x1014);

+	MAC(0x1014)	= events;

+	

+    if ( events >> 15)

+	{

+		if(!test_and_set_bit(1, &gmac_sema_up_flag))

+			up(&gmac_thread_sema);

+	}

+}

+

+ enum hrtimer_restart gmac_timer_callback(struct hrtimer *timer)

+{

+	unsigned long delay_in_us = GTIMER_INTERVAL;

+	ktime_t gmac_schdule_time;

+	

+	gmac_schdule_time = ktime_set(0, delay_in_us * 1000);

+	hrtimer_forward_now(timer, gmac_schdule_time);

+

+	//gmac_kick_thread();

+    tasklet_schedule(g_gmac_tasklet);

+    //gmac_kick_plug_thread();

+    //tasklet_schedule(&gmac_net_dev_prv->tasklet);

+	return HRTIMER_RESTART;

+}

+

+static void gmac_init_timer(void)

+{

+	sema_init(&gmac_thread_sema, 0);

+

+	gmac_timer = kzalloc(sizeof(struct hrtimer),GFP_KERNEL);

+	if(gmac_timer == NULL){

+		BUG_ON(1);

+	}

+    hrtimer_init(gmac_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL );

+

+    gmac_timer->function = gmac_timer_callback;

+}

+

+static void gmac_start_timer(void)

+{

+	unsigned long delay_in_us = GTIMER_INTERVAL;

+	ktime_t gmac_schdule_time;

+

+	gmac_schdule_time = ktime_set(0, delay_in_us * 1000);

+    hrtimer_start(gmac_timer, gmac_schdule_time, HRTIMER_MODE_REL );

+}

+

+static int gmac_stop_timer(void)

+{

+	int ret = 0;

+	

+    ret = hrtimer_cancel(gmac_timer);

+	if(ret < 0)

+		BUG_ON(1);

+	

+	return ret;

+}

+

+void zx_net_thread(unsigned long dev_id)

+{

+    struct net_device* dev 		= (struct net_device*)dev_id;

+    struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(dev);

+    volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+    unsigned events	= 0;								// ¶ÁÈ¡ÖжÏÖб£´æµÄÖжϱê¼Ç

+

+	while (!kthread_should_stop()){

+		down(&gmac_thread_sema);

+		if(!test_and_clear_bit(1, &gmac_sema_up_flag))

+			continue;

+

+		events = prv->int_event;

+

+		// ¶ÔGMACÖжϽøÐÐÊÂÎñ´¦Àí£¬Ö±µ½Ã»ÓÐÖжÏ(ÊÂÎñ)ÐèÒª´¦Àí

+		do

+	    {

+	        if(events & INT_ST_TX)

+	        {

+	            zx_net_tx(dev); 

+	        }                                                     

+	        if(events & INT_ST_RX)	    

+	        {

+	            zx_net_rx(dev);

+	        }

+

+	        events			= MAC(0x1014);

+	        MAC(0x1014)		= events;

+

+	    } while( events & (INT_ST_TX | INT_ST_RX));

+

+		//msleep(1);

+	}

+}

+

+#endif

+

+

+// GMAC Öжϴ¦Àíº¯Êý

+static irqreturn_t zx_net_int(int irq, void *dev_id)

+{

+	struct net_device* dev 		= (struct net_device*)dev_id;

+	struct zx_net_dev* prv 		= (struct zx_net_dev*)netdev_priv(dev);

+	volatile unsigned *gmac 	= (unsigned*)dev->base_addr;

+

+	prv->int_event				= MAC(0x1014);									// ¶ÁÈ¡ÖжÏÐÅÏ¢

+	MAC(0x1014)					= prv->int_event;								// Çå³ýÖжÏ

+

+	// ÏȽ«GMACÖÐ¶ÏÆÁ±Î£¬È»ºó½«Ö÷Òª´¦ÀíÁ÷³Ì·ÅÔÚÈíÖжÏÖÐÍê³É

+	// ÈíÖжÏÍê³Éºó£¬ÔÙ´ò¿ªGAMCÖжÏ

+

+	mac_int_disable();

+	tasklet_schedule(&prv->tasklet);

+

+	return IRQ_HANDLED;

+}

+

+//chenhao debug for setting gmac mac addr

+static inline void zx_net_set_mac(struct net_device* ndev)

+{

+    // È¡µÃMAC µØÖ·: 

+    // ²éÕÒMAC¼Ä´æÆ÷ÖеĵØÖ·£¬Èç¹ûÓÐЧ£¬Ê¹ÓøÃMAC£¬

+    // ÎÞЧÔòËæ»úÉú³É//zx297520v2   Ö±½ÓËæ»úÁËmac µØÖ·

+ 

+   int i =0;

+   u8 gmac_nvaddr[MAC_ADDR_LENTH] = {0};

+   int retval = 0;

+#if  0 

+   //now can not read NV,just change

+    retval = nand_NvRead(MAC_HWETHER,MAC_ADDR_LENTH,gmac_nvaddr);

+    if(retval < 0)

+    {

+	gmac_printk("TSP zx29 gmac read mac nv error");

+    }

+    else

+    {

+	gmac_printk("TSP zx29 gmac read mac nv ok");

+	if(is_valid_ether_addr(gmac_nvaddr))

+	{

+		for(i = 0;i<MAC_ADDR_LENTH;i++)

+		{

+			ndev->dev_addr[i]   = gmac_nvaddr[i];

+		}

+		return;

+	}

+    }

+#endif	

+#if  MAC_ADDR_SET

+    for(i = 0;i<MAC_ADDR_LENTH;i++)

+    {

+     ndev->dev_addr[i]   = gmac_addr[i];

+    }

+

+    if(!is_valid_ether_addr(ndev->dev_addr))

+    {

+	    random_ether_addr(ndev->dev_addr);

+    }

+#else

+    random_ether_addr(ndev->dev_addr);

+#endif

+}

+

+//static void __iomem *virt_gmac= 0;

+static int __devinit zx_net_probe(struct platform_device *pdev)

+{

+    int	ret = 0;

+    struct zx_net_dev	*prv = NULL;

+    volatile unsigned	*gmac = NULL;

+    // Ê×ÏÈ·ÖÅä½á¹¹Ì壬²¢»ñÈ¡ IO Óë IRQ ×ÊÔ´

+    struct net_device* 	ndev	= alloc_etherdev(sizeof(struct zx_net_dev));

+    struct resource* 	res		= platform_get_resource(pdev, IORESOURCE_MEM, 0);

+

+#ifndef GMAC_NO_INT	

+    int gmac_irq				= platform_get_irq_byname(pdev, "gmac_int");

+#endif

+	struct zx29_gmac_platform_data *pdata = pdev->dev.platform_data;

+    struct clk *pclk=NULL;

+    unsigned int value;

+    //pclk=clk_get_sys("zx29_gmac.0", "rmii_clk");     //gmac rmii_clk_o    50M

+    //clk_set_rate(pclk,50000000);

+    //clk_prepare_enable(pclk);

+    wake_lock_init(&gmac_wake_lock, WAKE_LOCK_SUSPEND, "gmac_pm");

+    wake_lock(&gmac_wake_lock);

+	

+    // zx_cpuidle_set_busy(IDLE_FLAG_GMAC);

+    

+    *(volatile unsigned int  *)(ZX_TOP_CRM_BASE+0x11C) = 0x00000005 ;   // GMAC_MOD_CFG gmac clk 50m

+ 

+    platform_set_drvdata(pdev, ndev);

+

+    if(NULL == res)		return -ENXIO;	// RES ÒѾ­Ö¸ÏòÐéÄâµØÖ·

+    if(NULL == ndev)	return -ENOMEM;

+#ifndef GMAC_NO_INT	

+    if(gmac_irq < 0)	return -EINVAL;

+#endif    

+    gmac_net_dev = ndev;

+    prv 					= (struct zx_net_dev*)netdev_priv(ndev);

+    prv->netdev 			= ndev;

+    prv->set_duplex_mode	= eSET_AUTO_NEGO;

+    prv->autoneg                  = AUTONEG_ENABLE;     //ÔÊÐí×ÔЭÉÌ

+    prv->stopped 			= 0;                //init stop

+#ifdef CONFIG_ARCH_ZX297520V2  

+	prv->ext_irq			= platform_get_irq_byname(pdev, "ext_int");

+#elif CONFIG_ARCH_ZX297520V3

+	

+#ifndef GMAC_NO_INT

+    prv->ext_irq			= platform_get_irq_byname(pdev, "phy_int");

+#endif

+#endif	

+	

+    //gmac_printk("TSP zx29 gmac  irq = %d  !!!!!\n",gmac_irq);

+    gmac_printk("TSP zx29 gmac phy irq = %d  !!!!!\n",prv->ext_irq);

+

+#ifndef GMAC_NO_INT	

+    if(prv->ext_irq < 0)		return -EINVAL;

+	

+    ndev->irq				= gmac_irq;

+#endif			

+    ndev->dev.parent		= &pdev->dev;

+    ndev->base_addr		= res->start;

+    ndev->netdev_ops		= &zx_net_netdev_ops;

+    ndev->ethtool_ops		= &zx_net_ethtool_ops;

+    ndev->watchdog_timeo 	=  HZ   ;    //for what ?

+

+    gmac_net_dev_prv = prv;

+#ifdef CONFIG_NET_ZX29_GMAC_SWITCH

+   snprintf(ndev->name, sizeof(ndev->name), "%s%%d", gmac_switch_name);

+   prv->device_type =  ePERIPHERAL_SWITCH;

+   prv->init = zx_gmac_switch_init;

+   prv->open = zx_gmac_switch_open;

+   prv->stop = zx_gmac_switch_stop;

+   prv->link_state = gmac_switch_linked;

+#endif

+

+#ifdef CONFIG_NET_ZX29_GMAC_PHY

+   snprintf(ndev->name, sizeof(ndev->name), "%s%%d", gmac_phy_name);

+   prv->device_type =  ePERIPHERAL_PHY;

+   prv->init = zx_gmac_phy_init;

+   prv->open = zx_gmac_phy_open;

+   prv->stop = zx_gmac_phy_stop;

+   prv->release = zx_gmac_phy_release;

+   prv->link_state = gmac_phy_link_status;

+#endif

+

+    gmac 	= (unsigned*)ndev->base_addr;

+	g_gmac  = gmac;

+    // ÅäÖÃMAC µØÖ·

+    zx_net_set_mac(ndev);

+

+    spin_lock_init(&prv->lock);

+    spin_lock_init(&prv->phy_lock);

+

+    dma_disable();

+    mac_disable();

+    mac_int_disable();

+   // gmac_stop((void*)ndev->base_addr);

+

+#ifndef GMAC_NO_INT

+    // Çå³ýÒÑ·¢ÉúÖжϣ¬È»ºó°²×°ÖжÏ

+    ret = request_irq(ndev->irq, zx_net_int, IRQF_DISABLED, pdev->name, ndev);

+    if(ret)		goto failed_request_irq;

+#endif

+

+    // ×¢²áÉ豸

+    ret = register_netdev(ndev);

+    if(ret)		goto failed_register;

+	

+    gmac_printk("TSP zx29 gmac netdev register success \n");

+

+

+	//div			= (unsigned*)GMAC_CLKEN;

+    //div[0]					= 0x0;

+

+//don't request this gpio

+#if 0//ndef CONFIG_NET_ZX29_GMAC_PHY    

+	if(gpio_request(pdata->pwr_gpio, pdata->pwr_name))

+		goto failed_request_gpio;

+	zx29_gpio_config(pdata->pwr_gpio, pdata->pwr_func);

+	gpio_direction_output(pdata->pwr_gpio, 1);

+#endif	

+    value = *(volatile unsigned int  *)(ZX_SOC_SYS_BASE+0x150); 

+    *(volatile unsigned int  *)(ZX_SOC_SYS_BASE+0x150) = value | 0x10 ;   // GMAC_MOD_CFG gmac phy reset

+    mdelay(500);      //phy delay >10ms  ²Åok

+    

+   ret = prv->init (ndev);

+  if(ret)   goto failed_phy_request_irq;

+

+#if 1//ndef ///GMAC_NO_INT

+    g_gmac_dev = prv;

+    tasklet_init(&prv->tasklet, zx_net_tasklet, (unsigned long)ndev);

+    g_gmac_tasklet = &prv->tasklet;

+    gmac_init_timer();

+#else

+	kthread_run(zx_net_thread, (unsigned long)ndev, "gmac_proc/%s", "txrx");

+	

+#endif

+

+

+    return 0;

+

+

+failed_phy_request_irq:

+	unregister_netdev(ndev);

+failed_request_gpio:

+#if 0//def CONFIG_NET_ZX29_GMAC_PHY 

+	gpio_free(pdata->pwr_gpio);

+#endif

+failed_request_irq:

+#ifndef GMAC_NO_INT

+	free_irq(ndev->irq, ndev);

+#endif

+failed_register:

+	free_netdev(ndev);

+	platform_set_drvdata(pdev, NULL);

+	gmac_net_dev_prv = NULL;

+	g_gmac = NULL;

+

+	return ret;

+}

+

+static int zx_net_suspend(struct device *dev)      //¹ÒÆðgmac

+{

+    struct platform_device *pdev	= to_platform_device(dev);

+    struct net_device 	*ndev		= platform_get_drvdata(pdev);

+

+    if(ndev)

+    {

+    	if(netif_running(ndev))

+    	{

+    		netif_device_detach(ndev);

+    		gmac_stop((void*)ndev->base_addr);

+    		// TODO: ÈçÓбØÒª£¬Çë¹ÒÆð PHY

+    	}

+    }

+    return 0;

+}

+

+static int zx_net_resume(struct device *dev)       //»Ö¸´GMAC

+{

+    struct platform_device *pdev	= to_platform_device(dev);

+    struct net_device *ndev 		= platform_get_drvdata(pdev);

+

+    if(ndev)

+    {

+    	if(netif_running(ndev))

+    	{

+        	// TODO: Èç¹ûÓбØÒª£¬Çë»Ö¸´ PHY ΪÕý³£Ä£Ê½

+        	gmac_start((void*)ndev->base_addr);

+        	netif_device_attach(ndev);

+    	}

+    }

+    return 0;

+}

+

+// Ð¶ÔØÍøÂçÉ豸

+static int __devexit zx_net_remove(struct platform_device *pdev)

+{

+    struct net_device *ndev 	= platform_get_drvdata(pdev);

+    struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(ndev);

+	struct zx29_gmac_platform_data *pdata = pdev->dev.platform_data;

+

+    tasklet_disable(&prv->tasklet);

+    tasklet_kill(&prv->tasklet);

+

+	if(prv->release)

+		prv->release(ndev);

+	

+#ifdef CONFIG_NET_ZX29_GMAC_PHY 

+	gpio_free(pdata->pwr_gpio);

+#endif

+	free_irq(ndev->irq, ndev);

+	

+    if(prv->switch_thread)

+    {

+        kthread_stop(prv->switch_thread);

+        prv->switch_thread = NULL;

+    }

+

+    if(prv->dma_rx_vir)

+    {

+	dma_free_coherent(NULL, GMAC_BUF_LEN, prv->dma_rx_vir, prv->dma_rx_phy);   //ÊÍ·Ådma»º³åÇø

+     }

+    unregister_netdev(ndev);

+    //free_netdev(ndev);

+    platform_set_drvdata(pdev, NULL);

+

+	wake_unlock(&gmac_wake_lock);

+	wake_lock_destroy(&gmac_wake_lock);

+

+	gmac_printk("TSP zx29 gmac remove success\n");

+    return 0;

+}

+

+static struct dev_pm_ops driver_pm_ops =

+{

+	.suspend		= zx_net_suspend,

+	.resume		= zx_net_resume,

+};

+

+static void zx_net_shutdown(struct platform_device *pdev)    //make phy into power down mode

+{

+    struct net_device *ndev 	= platform_get_drvdata(pdev);

+    //struct zx_net_dev* prv 	= (struct zx_net_dev*)netdev_priv(ndev);

+    if(ndev)

+    {	   

+        /*netif_device_detach(ndev);

+        gmac_stop((void*)ndev->base_addr);*/

+        // TODO: ÈçÓбØÒª£¬Çë¹ÒÆð PHY

+        //phy_pwd_mode(ndev);

+    }

+    return ;

+}

+static struct platform_driver net_driver =

+{

+	.driver			=

+	{

+		.name    		= "zx29_gmac",

+		.owner	 	= THIS_MODULE,

+		.pm	 		= &driver_pm_ops,

+	},

+	.probe			= zx_net_probe,

+	.remove			= __devexit_p(zx_net_remove),

+	.shutdown       	= zx_net_shutdown,

+	

+};

+

+static int __init zx_init(void)

+{

+    int ret = platform_driver_register(&net_driver);     /*³õʼ»¯×¢²áº¯Êý£¬É豸ÃûÊÇzx_gmac*/

+

+    if(ret)	

+    {

+        gmac_printk("TSP zx29 gmac driver register failed\n");

+    }

+    else	

+    {

+        gmac_printk("TSP zx29 gmac driver register successed\n");

+    }

+

+    return    ret;

+}

+

+static void __exit zx_cleanup(void)

+{

+    platform_driver_unregister(&net_driver);

+	gmac_printk("TSP zx29 gmac unregister success\n");

+}

+

+module_init(zx_init);

+module_exit(zx_cleanup);

+MODULE_AUTHOR("sanchips, SOC");

+MODULE_DESCRIPTION("ZX279000 Serial GMAC network driver");

+MODULE_LICENSE("GPL");

diff --git a/ap/os/linux/linux-3.4.x/drivers/net/gmac/zx_gmac.h b/ap/os/linux/linux-3.4.x/drivers/net/gmac/zx_gmac.h
new file mode 100644
index 0000000..2b7fd21
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/net/gmac/zx_gmac.h
@@ -0,0 +1,244 @@
+/*
+* Copyright (C) 2010 Realtek Semiconductor Corp.
+* All Rights Reserved.
+*
+*                
+*
+*/
+
+#ifndef __ZX_GMAC_H__
+#define __ZX_GMAC_H__
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/clk.h>
+#include <linux/semaphore.h>
+#include <linux/gpio.h>
+#include <linux/kthread.h>
+
+#include <mach/iomap.h>
+#include <mach/pcu.h>
+
+
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/kobject.h>
+//#include <linux/android_notify.h>
+
+#include <linux/soc/zte/pm/drv_idle.h>
+#include <linux/nvro_comm.h>
+
+#define GMAC_BD_LEN                32
+
+#define GMAC_RX_BD_NUM    (1 << 9)
+#define GMAC_TX_BD_NUM    (1 << 10)
+
+#define GMAC_RX_BUF_LEN    (GMAC_BD_LEN * GMAC_RX_BD_NUM)
+#define GMAC_TX_BUF_LEN    (GMAC_BD_LEN * GMAC_TX_BD_NUM)
+
+#define GMAC_BUF_LEN        (GMAC_RX_BUF_LEN + GMAC_TX_BUF_LEN)
+
+#define MAC_ADDR_SET                            1
+#define MAC_ADDR_LENTH		                 6	
+
+#define PHY_AUTONEG_TIMEOUT              100000                                       //×ÔЭÉ̵ȴýʱ¼ä
+
+#define MAC_RESET_NUM                       3 //´ÎÊý
+#define MAC_WAIT_TIME                       10000 //0.1ms //ʱ¼äΪºÁÃëms
+#define PHY_CLOCK			  		5											// ʱÖÓΪ 2£¬ubootÖÐʹÓÃʱÖÓ3 0x03
+#define PHY_RESET					(1 << 15)									// PHY ¸´Î»
+#define DMA_OWNER 					(1 << 31)									// ÃèÊö·ûËùÓÐȨ¹éDMA
+
+//#define GMAC_CLKEN            		0xFCA0013C
+/* Basic mode control register. */
+#define BMCR_RESV			0x003f	/* Unused...		       */
+#define BMCR_SPEED1000		0x0040	/* MSB of Speed (1000)	       */
+#define BMCR_CTST			0x0080	/* Collision test	       */
+#define BMCR_FULLDPLX		0x0100	/* Full duplex		       */
+#define BMCR_ANRESTART		0x0200	/* Auto negotiation restart    */
+#define BMCR_ISOLATE		0x0400	/* Disconnect DP83840 from MII */
+#define BMCR_PDOWN			0x0800	/* Powerdown the DP83840       */
+#define BMCR_ANENABLE		0x1000	/* Enable auto negotiation     */
+#define BMCR_SPEED100		0x2000	/* Select 100Mbps	       */
+#define BMCR_LOOPBACK		0x4000	/* TXD loopback bits	       */
+#define BMCR_RESET			0x8000	/* Reset the DP83840	       */
+#define MAC_HWETHER      	OS_FLASH_AMT_COMM_RO_GMAC_OFFSET
+/*------------------------------------------------------------------------------
+* ºêÒåÒå:
+* ·¢ËÍ´íÎó
+* ½ÓÊÕ´íÎó
+* ¼Ä´æÆ÷·¢ËÍÓë½ÓÊÕÖжÏ״̬
+------------------------------------------------------------------------------*/
+#define ERR_TX_ES 					(1 << 15)									// ·¢ËÍ´íÎó»ã×Ü
+#define ERR_TX_JT 					(1 << 14)  									// Jabber Timeout
+#define ERR_TX_FF 					(1 << 13)  									// Frame Flushed
+#define ERR_TX_LC 					(1 << 11)  									// Loss of Carrier
+#define ERR_TX_NC 					(1 << 10)  									// No Carrier
+#define ERR_TX_LATECOL 				(1 << 9)  									// Late Collision
+#define ERR_TX_EC 					(1 << 8)  									// Excessive Collision
+#define ERR_TX_ED 					(1 << 2)  									// Excessive Deferral
+#define ERR_TX_UF 					(1 << 1)  									// Underflow Error
+#define ERR_RX_ES 					(1 << 15)  									// ½ÓÊÕ´íÎó»ã×Ü
+#define ERR_RX_LE 					(1 << 12)   								// Length Error
+#define ERR_RX_OE 					(1 << 11)   								// Overflow Error
+#define ERR_RX_IPC 					(1 << 7)   									// Timestamp Available/IP Checksum Error (Type1) /Giant Frame
+#define ERR_RX_LC 					(1 << 6)   									// Late Collision
+#define ERR_RX_CE 					(1 << 1)   									// Rx MAC Address/Payload Checksum Error
+#define INT_ST_TX  					0x01       									// ·¢ËͺóÖжÏ
+#define INT_ST_RX  					0x40										// ½ÓÊÕºóÖжÏ
+
+#define GMAC_FRAME_LEN                0x5F8
+/*------------------------------------------------------------------------------
+* ºêÒåÒå: ¶Ô¼Ä´æÆ÷µÄһЩ²Ù×÷
+------------------------------------------------------------------------------*/
+#define	MAC(x)						gmac[(x) >> 2]
+#define mac_mii_is_busy()			(MAC(0x0010) & 0x01)
+#define mac_provide_clock()			(MAC(0x0010) = (PHY_CLOCK <<2))
+#define mac_reset()					(MAC(0x1000)	|= 1)
+#define mac_wait_reset_finished()	while(MAC(0x1000) & 1)
+#define mac_int_enable()			(MAC(0x101C)	 = 0x180f5)
+#define mac_int_disable()			(MAC(0x101C)	 = 0x00)
+#define mac_int_clear(x)			(MAC(0x1014)	 = (x))
+#define mac_enable()				(MAC(0x0000)	|= (0x3 << 2))                    
+#define mac_disable()				(MAC(0x0000)	&= ~(0x3 << 2))                               //  gmac stop rx&tx
+#define mac_set_duplex_mode()		(MAC(0x0000)	|= 1 << 11)					// ÉèÖÃΪȫ˫¹¤Ä£Ê½
+#define mac_set_gmii_mode()			(MAC(0x0000)	&=  ~(1 << 15))					// ÉèÖÃPHYµÄ½Ó¿ÚΪGMII
+#define mac_set_mii_mode()			(MAC(0x0000)	|= 1 << 15)					// ÉèÖÃPHYµÄ½Ó¿ÚΪMII
+#define mac_rece_all_data()			(MAC(0x0004)	|= (1 << 31) | 1)			// ÔÊÐí½ÓÊÜËùÓÐÊý¾Ý
+#define dma_enable()				(MAC(0x1018)	|= ((1 << 1) | (1 << 13)))
+#define dma_disable()				(MAC(0x1018)	&= ~((1 << 1) | (1 << 13)))    // Í£Ö¹ÊÕ·¢dma stop
+#define dma_continue_tx()			(MAC(0x1004)	 = 1)						// µ±Í£Ö¹ºóÖØÆô·¢ËÍ
+#define dma_continue_rx()			(MAC(0x1008)	 = 1)						// µ±Í£Ö¹ºóÖØÆô½ÓÊÕ
+#define dma_set_tx_buffer(x)		(MAC(0x1010)	 = (x))						// ÉèÖ÷¢ËÍ»º³åÇø(ÎïÀíµØÖ·)
+#define dma_set_rx_buffer(x)		(MAC(0x100C)	 = (x))						// ÉèÖýÓÊÕ»º³åÇø(ÎïÀíµØÖ·)
+#define dma_clear_tx_fifo()			(MAC(0x1018)	|= 1 << 20)					// Çå³ý·¢ËÍFIFO
+#define dma_wait_tx_fifo_cleared()	while(MAC(0x1018) & (1 << 20));				// µÈ´ýÇå³ý·¢ËÍFIFOÍê³É
+
+
+#define MIN(a,b)   					((a) < (b) ? (a) : (b))
+
+typedef enum
+{
+	eSPEED_10M = 0,
+	eSPEED_100M,
+	eSPEED_END
+} E_SPEED;
+
+typedef enum
+{
+	eDUPLEX_HALF = 0,
+	eDUPLEX_FULL,
+	eDUPLEX_END
+} E_DUPLEX;
+
+typedef enum
+{
+	eSET_AUTO_NEGO = 0,
+	eSET_10M_FULL_DUPLEX = 2,
+	eSET_100M_HALF_DUPLEX = 4,
+	eSET_100M_FULL_DUPLEX = 8,
+	eSET_10M_HALF_DUPLEX = 1,
+	eSET_SPEED_DUPLEX_END = 5
+} E_SET_SPEED_DUPLEX;
+
+typedef enum
+{
+	eLINK_OFF = 0,
+	eLINK_ON,
+	eLINK_END
+} E_LINK_STATE;
+
+typedef enum
+{
+	ePERIPHERAL_PHY = 0,
+	ePERIPHERAL_SWITCH,
+	ePERIPHERAL_END
+} E_DEV_TYPE;
+
+typedef enum{
+     GMAC_ETH_PLUGIN,
+     GMAC_ETH_PLUGOUT,
+     GMAC_EVNET_NUM,
+}gmac_notify_event;
+/*------------------------------------------------------------------------------
+* ÒÔϼ¸¸öΪ½á¹¹Ì嶨Òå:
+* ½ÓÊÕÃèÊö·û
+* ·¢ËÍÃèÊö·û
+------------------------------------------------------------------------------*/
+struct bd_rx
+{
+    u32 					RDES0;							// ¿ØÖƼĴæÆ÷
+    u32 					RDES1;							// Êý¾Ý³¤¶È
+    u32 					dma_buf;						// Êý¾Ý»º³åÇøµØÖ·
+    u32 					next;							// ÏÂÒ»¸öÃèÊö·û
+    struct sk_buff 			*skb;							// SKB Ö¸Õë
+    u32						data0;							// δʹÓã¬ÓÃÓÚÊý¾Ý¶ÔÆë
+    u32						data1;							// δʹÓã¬ÓÃÓÚÊý¾Ý¶ÔÆë
+    u32						data2;							// δʹÓã¬ÓÃÓÚÊý¾Ý¶ÔÆë
+};
+
+struct bd_tx
+{
+    u32 					TDES0;							// ¿ØÖƼĴæÆ÷
+    u32 					TDES1;							// Êý¾Ý³¤¶È
+    u32 					dma_buf;						// Êý¾Ý»º³åÇøµØÖ·
+    u32 					next;							// ÏÂÒ»¸öÃèÊö·û
+    struct sk_buff 			*skb;							// SKB Ö¸Õë
+    u32						data0;							// δʹÓã¬ÓÃÓÚÊý¾Ý¶ÔÆë
+    u32						data1;							// δʹÓã¬ÓÃÓÚÊý¾Ý¶ÔÆë
+    u32						data2;							// δʹÓã¬ÓÃÓÚÊý¾Ý¶ÔÆë
+};
+
+struct zx_net_dev
+{
+	struct net_device*		netdev;
+	struct clk				*clk;							// ×¢Ò⣬ʱÖÓ×ÊÔ´Ö»ÊÇÔݲ»Ê¹ÓÃ
+	int						phy;							// PHY ÔÚ½Ó¿ÚÖеĴÎÐò
+	unsigned				phy_id;							// PHY ID
+	unsigned				dma_rx_phy;						// DMA ÎïÀíµØÖ·
+	char*					dma_rx_vir;						// DMA ÐéÄâµØÖ·
+	unsigned				dma_tx_phy;						// DMA ÎïÀíµØÖ·
+	char*					dma_tx_vir;						// DMA ÐéÄâµØÖ·
+	int						rx_bd_offset;					// ½ÓÊÕÃèÊö·ûÆ«ÒÆ
+	int						tx_bd_offset;					// ·¢ËÍÃèÊö·ûÆ«ÒÆ
+	int						txed_bd;						// ÒÑ·¢ËÍÃèÊö·ûÆ«ÒÆ
+	struct timer_list		timer;							// Ö÷ÒªÓÃÀ´¶¨Ê±²éѯPHYµÄÁ¬½Ó״̬
+	E_LINK_STATE			link;							// PHYµÄÁ¬½Ó״̬
+	E_SPEED					speed;							//0,10M; 1,100M
+	E_DUPLEX				duplex;							//0,half; 1,full
+	E_SET_SPEED_DUPLEX		set_duplex_mode;				//0:×ÔÊÊÓ¦, 1:10Mȫ˫¹¤£¬2:100M°ëË«¹¤£¬3:100Mȫ˫¹¤£¬4:10M°ëË«¹¤
+	int                     autoneg;
+	struct spinlock			phy_lock;						//ÓÃÀ´±£»¤Óëlink¡¢speed¡¢duplex¡¢set_duplex_modeµÈÓëPHYÏà¹ØµÄÐÅÏ¢Ò»ÖÂÐÔ
+	struct spinlock			lock;
+	struct tasklet_struct	tasklet;						// ºó°ë²¿
+	unsigned				int_event;						// ±£´æ×´Ì¬
+	int 					ext_irq;
+       struct task_struct *      switch_thread;
+       struct semaphore       phy_sem;
+       //struct tasklet_struct	ext_tasklet;						// ºó°ë²¿
+       unsigned	int			ext_int_event;						// ±£´æ×´Ì¬
+       int                                stopped;       
+	E_DEV_TYPE                  device_type;  
+	int (*init)(struct net_device *dev);
+	int (*open)(struct net_device *dev);
+	int (*stop)(struct net_device *dev);
+	int (*release)(struct net_device *dev);
+	E_LINK_STATE (*link_state)(struct net_device *dev);
+};
+    
+
+#endif  /*__RTK_API_H__*/
+
+
+