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, ®Val);
+ 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, ®Val);
+ 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, ®Val);
+ 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, ®Val);
+ pPortability->nway = regVal ? 1 : 0;
+ pPortability->forcemode = ~(pPortability->nway);
+
+ rtl8306e_regbit_get (6, 24, 12, 0, ®Val);
+ pPortability->symflc = regVal ? 0 : 1;
+
+ rtl8306e_regbit_get (6, 24, 13, 0, ®Val);
+ pPortability->rxpause = regVal ? 0 : 1;
+
+ rtl8306e_regbit_get (6, 24, 14, 0, ®Val);
+ pPortability->txpause = regVal ? 0 : 1;
+
+ rtl8306e_regbit_get (6, 22, 15, 0, ®Val);
+ pPortability->link= regVal ? 1 : 0;
+
+ rtl8306e_reg_get (6, 22, 0, ®Val);
+ 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, ®Val);
+
+ /*speed and duplex*/
+ rtl8306e_reg_get(5, 0, 0, ®Val);
+ 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, ®Val);
+ 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, ®Val);
+ 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, ®Val);
+ pPortability->nway = regVal ? 1 : 0;
+ pPortability->forcemode = regVal ? 0: 1;
+
+ /*get speed and duplex ability*/
+ rtl8306e_regbit_get (5, 0, 13, 0, ®Val);
+ if(regVal)
+ pPortability->speed =PORT_SPEED_100M;
+ else
+ pPortability->speed = PORT_SPEED_10M;
+
+ rtl8306e_regbit_get (5, 0, 8, 0, ®Val);
+ 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, ®Val);
+ 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, ®Val);
+ pPortability->link= regVal ? 1 : 0;
+ }
+ else if (RTL8306_PORT5 == port)
+ {
+ rtl8306e_regbit_set(0, 16, 11, 0, 1);
+ rtl8306e_reg_get(6, 26, 3, ®Val);
+ 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, ®Val);
+ 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, ®Val);
+ pPortability->nway = regVal ? 1 : 0;
+ pPortability->forcemode = regVal ? 0: 1;
+
+ rtl8306e_regbit_get (6, 24, 12, 0, ®Val);
+ pPortability->symflc = regVal ? 0 : 1;
+
+ rtl8306e_regbit_get (6, 24, 13, 0, ®Val);
+ pPortability->rxpause = regVal ? 0 : 1;
+
+ rtl8306e_regbit_get (6, 24, 14, 0, ®Val);
+ pPortability->txpause = regVal ? 0 : 1;
+
+ rtl8306e_regbit_get (6, 22, 15, 0, ®Val);
+ pPortability->link= regVal ? 1 : 0;
+
+ rtl8306e_reg_get (6, 22, 0, ®Val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®Val);
+ 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, ®Val);
+ *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, ®Val);
+ *pMac_cnt = (regVal & 0x7FF) ;
+ }
+ else
+ {
+ rtl8306e_reg_get(port, 31, 1, ®Val);
+ *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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ *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, ®val);
+ 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, ®val);
+ *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, ®val);
+ 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, ®val);
+ 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, ®val);
+ rtl8306e_reg_get(4, 26, 0, ®val2);
+ 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, ®val3);
+ 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, ®val3);
+ regval3 &= ~0x3;
+ regval3 |= 0x2;
+ rtl8306e_reg_set(0, 31, 3, regval3);
+ rtl8306e_reg_get(1, 31, 3, ®val3);
+ regval3 &= ~0x3;
+ regval3 |= 0x2;
+ rtl8306e_reg_set(1, 31, 3, regval3);
+ rtl8306e_reg_get(2, 31, 3, ®val3);
+ regval3 &= ~0x3;
+ regval3 |= 0x2;
+ rtl8306e_reg_set(2, 31, 3, regval3);
+ rtl8306e_reg_get(3, 31, 3, ®val3);
+ regval3 &= ~0x3;
+ regval3 |= 0x2;
+ rtl8306e_reg_set(3, 31, 3, regval3);
+ rtl8306e_reg_get(5, 31, 3, ®val3);
+ 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, ®val3);
+ regval3 &= ~(0x7 << 4);
+ regval3 |= (0x6 << 4);
+ rtl8306e_phyReg_set(0, 25, 4, regval3);
+
+ rtl8306e_phyReg_get(0, 28, 4, ®val3);
+ 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, ®val3);
+ regval3 &= ~(0x1 << 8);
+ rtl8306e_phyReg_set(0, 28, 4, regval3);
+
+ rtl8306e_phyReg_get(0, 25, 4, ®val3);
+ 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, ®val3);
+ regval3 &= ~(0xFF);
+ regval3 |= 0xF3;
+ rtl8306e_phyReg_set(phy, 24, 4, regval3);
+ }
+
+ /*RTCT*/
+ for (phy = 0; phy <= 4; phy++)
+ {
+ rtl8306e_phyReg_get(phy, 16, 2, ®val3);
+ regval3 &= ~(0x3FF);
+ regval3 |= 0xFA;
+ rtl8306e_phyReg_set(phy, 16, 2, regval3);
+ rtl8306e_phyReg_get(phy, 22, 2, ®val3);
+ regval3 &= ~(0x7FF);
+ regval3 |= 0x12C;
+ rtl8306e_phyReg_set(phy, 22, 2, regval3);
+ rtl8306e_phyReg_get(phy, 23, 2, ®val3);
+ regval3 &= ~(0x3FF);
+ regval3 |= 0xC8;
+ rtl8306e_phyReg_set(phy, 23, 2, regval3);
+ rtl8306e_phyReg_get(phy, 24, 2, ®val3);
+ regval3 &= ~(0x1FF);
+ regval3 |= 0x32;
+ rtl8306e_phyReg_set(phy, 24, 2, regval3);
+ rtl8306e_phyReg_get(phy, 19, 2, ®val3);
+ regval3 &= ~(0xF << 12);
+ regval3 |= (0x4 << 12);
+ rtl8306e_phyReg_set(phy, 19, 2, regval3);
+ rtl8306e_phyReg_get(phy, 18, 2, ®val3);
+ regval3 &= ~(0x1F << 10);
+ regval3 |= (0x5 << 10);
+ rtl8306e_phyReg_set(phy, 18, 2, regval3);
+ rtl8306e_phyReg_get(phy, 25, 2, ®val3);
+ regval3 &= ~(0xFF << 8);
+ regval3 |= (0x4 << 8);
+ rtl8306e_phyReg_set(phy, 25, 2, regval3);
+ rtl8306e_phyReg_get(phy, 25, 2, ®val3);
+ 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, ®val);
+ rtl8306e_reg_get(4, 26, 0, ®val2);
+ 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, ®val);
+ if(regval)
+ {
+ *pMaxLen = RTL8306_MAX_PKT_LEN_2000;
+ }
+ else
+ {
+ rtl8306e_regbit_get(2, 23, 1, 3, ®val);
+ if (regval)
+ {
+ *pMaxLen = RTL8306_MAX_PKT_LEN_1518;
+ }
+ else
+ {
+ rtl8306e_regbit_get(0, 18, 14, 0, ®val);
+ 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, ®Data);
+ *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, ®Data);
+ 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, ®val);
+ 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, ®val);
+ *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, ®Value);
+ regValue = (regValue & 0xFFF) | (vlanIndex << 12);
+ rtl8306e_reg_set(port, 24, 0, regValue);
+ } else
+ {
+ rtl8306e_reg_get(0, 26, 1, ®Value);
+ 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, ®val);
+ 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, ®val);
+ regval &= ~(0x3 << 6);
+ regval |= (accept_frame_type << 6);
+ rtl8306e_reg_set(6, 30, 1, regval);
+ }
+ else
+ {
+ rtl8306e_reg_get(port, 21, 2, ®val);
+ 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, ®val);
+ regval &= (0x3 << 7);
+ *pAccept_frame_type = (rtl8306e_acceptFrameType_t)(regval >> 7);
+ }
+ else if (RTL8306_PORT5 == port)
+ {
+ rtl8306e_reg_get(6, 30, 1, ®val);
+ regval &= (0x3 << 6);
+ *pAccept_frame_type = (rtl8306e_acceptFrameType_t)(regval >> 6);
+ }
+ else
+ {
+ rtl8306e_reg_get(port, 21, 2, ®val);
+ 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, ®val);
+ regval &= ~(0x3F << 1);
+ regval |= (igPortMsk << 1);
+ rtl8306e_reg_set(0, 28, 3, regval);
+ }
+ else if(RTL8306_PORT5 == egPort)
+ {
+ rtl8306e_reg_get(6, 30, 1, ®val);
+ regval &= ~0x3F;
+ regval |= igPortMsk;
+ rtl8306e_reg_set(6, 30, 1, regval);
+ }
+ else
+ {
+ rtl8306e_reg_get(egPort, 30, 1, ®val);
+ 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, ®val);
+ if(!regval)
+ *pIgPortMsk = 0;
+
+ if(RTL8306_PORT0 == egPort)
+ {
+ rtl8306e_reg_get(0, 28, 3, ®val);
+ regval &= (0x3F << 1);
+ *pIgPortMsk = regval >> 1;
+ }
+ else if(RTL8306_PORT5 == egPort)
+ {
+ rtl8306e_reg_get(6, 30, 1, ®val);
+ regval &= 0x3F;
+ *pIgPortMsk = regval;
+ }
+ else
+ {
+ rtl8306e_reg_get(egPort, 30, 1, ®val);
+ 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, ®Value);
+ 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, ®Value);
+ *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, ®Value);
+ regValue = (regValue & 0xF000) | vid ;
+ rtl8306e_reg_set(0, 25, 0, regValue);
+ rtl8306e_reg_get(0, 24, 0, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(0, 24, 0, regValue);
+ rtl8306e_reg_get(0, 29, 0, ®Value);
+ regValue &= ~0x3F;
+ regValue |= untagmsk;
+ rtl8306e_reg_set(0, 29, 0, regValue);
+ break;
+
+ case 1: /* VLAN[B] */
+ rtl8306e_reg_get(1, 25, 0, ®Value);
+ regValue = (regValue & 0xF000) | vid ;
+ rtl8306e_reg_set(1, 25, 0, regValue);
+ rtl8306e_reg_get(1, 24, 0, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(1, 24, 0, regValue);
+ rtl8306e_reg_get(1, 30, 1, ®Value);
+ regValue &= ~0x3F;
+ regValue |= untagmsk;
+ rtl8306e_reg_set(1, 30, 1, regValue);
+ break;
+
+ case 2: /* VLAN[C] */
+ rtl8306e_reg_get(2, 25, 0, ®Value);
+ regValue = (regValue & 0xF000) | vid ;
+ rtl8306e_reg_set(2, 25, 0, regValue);
+ rtl8306e_reg_get(2, 24, 0, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(2, 24, 0, regValue);
+ rtl8306e_reg_get(2, 30, 1, ®Value);
+ regValue &= ~0x3F;
+ regValue |= untagmsk;
+ rtl8306e_reg_set(2, 30, 1, regValue);
+ break;
+
+ case 3: /* VLAN[D] */
+ rtl8306e_reg_get(3, 25, 0, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(3, 25, 0, regValue);
+ rtl8306e_reg_get(3, 24, 0, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(3, 24, 0, regValue);
+ rtl8306e_reg_get(3, 30, 1, ®Value);
+ regValue &= ~0x3F;
+ regValue |= untagmsk;
+ rtl8306e_reg_set(3, 30, 1, regValue);
+ break;
+
+ case 4: /* VLAN[E] */
+ rtl8306e_reg_get(4, 25, 0, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(4, 25, 0, regValue);
+ rtl8306e_reg_get(4, 24, 0, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(4, 24, 0, regValue);
+ rtl8306e_reg_get(4, 30, 1, ®Value);
+ regValue &= ~0x3F;
+ regValue |= untagmsk;
+ rtl8306e_reg_set(4, 30, 1, regValue);
+ break;
+
+ case 5: /* VLAN[F] */
+ rtl8306e_reg_get(0, 27, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(0, 27, 1, regValue);
+ rtl8306e_reg_get(0, 26, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(0, 26, 1, regValue);
+ rtl8306e_reg_get(0, 26, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(0, 26, 1, regValue);
+ break;
+
+ case 6: /* VLAN[G] */
+ rtl8306e_reg_get(1, 27, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(1, 27, 1, regValue);
+ rtl8306e_reg_get(1, 26, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(1, 26, 1, regValue);
+ rtl8306e_reg_get(1, 26, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(1, 26, 1, regValue);
+ break;
+
+ case 7: /* VLAN[H] */
+ rtl8306e_reg_get(2, 27, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(2, 27, 1, regValue);
+ rtl8306e_reg_get(2, 26, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(2, 26, 1, regValue);
+ rtl8306e_reg_get(2, 26, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(2, 26, 1, regValue);
+ break;
+
+ case 8: /* VLAN[I] */
+ rtl8306e_reg_get(3, 27, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(3, 27, 1, regValue);
+ rtl8306e_reg_get(3, 26, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(3, 26, 1, regValue);
+ rtl8306e_reg_get(3, 26, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(3, 26, 1, regValue);
+
+ break;
+
+ case 9: /* VLAN[J] */
+ rtl8306e_reg_get(4, 27, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(4, 27, 1, regValue);
+ rtl8306e_reg_get(4, 26, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(4, 26, 1, regValue);
+ rtl8306e_reg_get(4, 26, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(4, 26, 1, regValue);
+ break;
+
+ case 10: /* VLAN[K] */
+ rtl8306e_reg_get(0, 29, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(0, 29, 1, regValue);
+ rtl8306e_reg_get(0, 28, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(0, 28, 1, regValue);
+ rtl8306e_reg_get(0, 28, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(0, 28, 1, regValue);
+ break;
+
+ case 11: /* VLAN[L] */
+ rtl8306e_reg_get(1, 29, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(1, 29, 1, regValue);
+ rtl8306e_reg_get(1, 28, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(1, 28, 1, regValue);
+ rtl8306e_reg_get(1, 28, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(1, 28, 1, regValue);
+ break;
+
+ case 12: /* VLAN[M] */
+ rtl8306e_reg_get(2, 29, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(2, 29, 1, regValue);
+ rtl8306e_reg_get(2, 28, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(2, 28, 1, regValue);
+ rtl8306e_reg_get(2, 28, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(2, 28, 1, regValue);
+ break;
+
+ case 13: /* VLAN[N] */
+ rtl8306e_reg_get(3, 29, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(3, 29, 1, regValue);
+ rtl8306e_reg_get(3, 28, 1, ®Value);
+ regValue = (regValue & 0xFFC0) |mbrmsk;
+ rtl8306e_reg_set(3, 28, 1, regValue);
+ rtl8306e_reg_get(3, 28, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(3, 28, 1, regValue);
+ break;
+
+ case 14: /* VLAN[O] */
+ rtl8306e_reg_get(4, 29, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(4, 29, 1, regValue);
+ rtl8306e_reg_get(4, 28, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(4, 28, 1, regValue);
+ rtl8306e_reg_get(4, 28, 1, ®Value);
+ regValue &= ~(0x3F << 6);
+ regValue |= (untagmsk << 6);
+ rtl8306e_reg_set(4, 28, 1, regValue);
+ break;
+
+ case 15: /* VLAN[P] */
+ rtl8306e_reg_get(0, 31, 1, ®Value);
+ regValue = (regValue & 0xF000) | vid;
+ rtl8306e_reg_set(0, 31, 1, regValue);
+ rtl8306e_reg_get(0, 30, 1, ®Value);
+ regValue = (regValue & 0xFFC0) | mbrmsk;
+ rtl8306e_reg_set(0, 30, 1, regValue);
+ rtl8306e_reg_get(0, 30, 1, ®Value);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ regval &= (0x3 << 6);
+ *pPri = regval >> 6;
+ break;
+
+ case 1: /*VLAN[B]*/
+ rtl8306e_reg_get(1, 30, 1, ®val);
+ regval &= (0x3 << 6);
+ *pPri = regval >> 6;
+ break;
+
+ case 2: /*VLAN[C]*/
+ rtl8306e_reg_get(2, 30, 1, ®val);
+ regval &= (0x3 << 6);
+ *pPri = regval >> 6;
+ break;
+
+ case 3: /*VLAN[D]*/
+ rtl8306e_reg_get(3, 30, 1, ®val);
+ regval &= (0x3 << 6);
+ *pPri = regval >> 6;
+ break;
+
+ case 4: /*VLAN[E]*/
+ rtl8306e_reg_get(4, 30, 1, ®val);
+ regval &= (0x3 << 6);
+ *pPri = regval >> 6;
+ break;
+
+ case 5: /*VLAN[F]*/
+ rtl8306e_reg_get(0, 27, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 6: /*VLAN[G]*/
+ rtl8306e_reg_get(1, 26, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 7: /*VLAN[H]*/
+ rtl8306e_reg_get(2, 26, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 8: /*VLAN[I]*/
+ rtl8306e_reg_get(3, 26, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 9: /*VLAN[J]*/
+ rtl8306e_reg_get(4, 26, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 10: /*VLAN[K]*/
+ rtl8306e_reg_get(0, 28, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 11: /*VLAN[L]*/
+ rtl8306e_reg_get(1, 28, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 12: /*VLAN[M]*/
+ rtl8306e_reg_get(2, 28, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 13: /*VLAN[N]*/
+ rtl8306e_reg_get(3, 28, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 14: /*VLAN[O]*/
+ rtl8306e_reg_get(4, 28, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ case 15: /*VLAN[P]*/
+ rtl8306e_reg_get(0, 30, 1, ®val);
+ regval &= (0x3 << 12);
+ *pPri = regval >> 12;
+ break;
+
+ default: /*unmatched vlan entry*/
+ rtl8306e_reg_get(0, 29, 0, ®val);
+ 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, ®val);
+
+ 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, ®val);
+ 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, ®val);
+ regval &= ~0xfff;
+ regval |= transVid;
+ rtl8306e_reg_set(6, 17 + vlanIndex, 4, regval);
+ }
+ else
+ {
+ rtl8306e_reg_get(6, 18, 1, ®val);
+ 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, ®val);
+ *pTransVid = (regval & 0xfff);
+ }
+ else
+ {
+ rtl8306e_reg_get(6, 18, 1, ®val);
+ *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, ®val);
+ *pEnable = regval ? 1:0;
+ }
+ else
+ {
+ rtl8306e_reg_get(6, 17 + port, 0, ®val);
+ *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, ®val);
+ 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, ®val);
+ 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, ®val);
+ *pOvidsrc = (regval & (1 << 3)) ? 1:0;
+ *pOpriSrc = (regval & (1 << 2)) ? 1:0;
+ }
+ else
+ {
+ rtl8306e_reg_get(6, 17 + port, 0, ®val);
+ *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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ *pEnabled = (regValue ? FALSE:TRUE);
+ rtl8306e_reg_get(port, 21, 2, ®Value);
+ *pN64Kbps = regValue & 0x7FF;
+ }
+ else
+ {
+ /*Get port Tx rate*/
+ rtl8306e_regbit_get(port, 18, 15, 2, pEnabled);
+ rtl8306e_reg_get(port, 18, 2, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ else
+ rtl8306e_reg_get(6, 17, 2, ®Value);
+
+ *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, ®Value);
+ 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, ®Value);
+ 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, ®Value1);
+ rtl8306e_reg_get(1, 24, 3, ®Value2);
+ 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, ®Value1);
+ rtl8306e_reg_get(1, 24, 3, ®Value2);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ regval |= (1 << (priArbit.acl_pri_lev -1 + 12));
+ rtl8306e_reg_set(1, 21, 3, regval);
+ }
+
+ /*dscp based priority*/
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®val);
+ regval |= (1 << (priArbit.dscp_pri_lev -1 + 8));
+ rtl8306e_reg_set(1, 21, 3, regval);
+ }
+
+ /*1Q based priority*/
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®val);
+ regval |= ( 1 << (priArbit.dot1q_pri_lev -1 + 4));
+ rtl8306e_reg_set(1, 21, 3, regval);
+ }
+
+ /*port based priority*/
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ if(regval)
+ {
+ pPriArbit->acl_pri_lev = 5;
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®val);
+ if (regval)
+ {
+ pPriArbit ->dscp_pri_lev = 5;
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®val);
+ if (regval)
+ {
+ pPriArbit ->dot1q_pri_lev = 5;
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®val);
+ if (regval)
+ {
+ pPriArbit ->port_pri_lev = 5;
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 21, 3, ®val);
+ 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, ®Value);
+ 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, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+ regValue &= ~0x7FF;
+ regValue |= sch_para.q2_n64Kbps;
+ rtl8306e_reg_set(5, 18, 3, regValue);
+
+ rtl8306e_reg_get(5, 19, 3, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ regValue &= ~0x7FF;
+ regValue |= sch_para.q2_n64Kbps;
+ rtl8306e_reg_set(5, 23, 3, regValue);
+
+ rtl8306e_reg_get(5, 24, 3, ®Value);
+ 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, ®Value);
+ pSch_para->q0_wt = regValue & 0x7F;
+ pSch_para->q1_wt = (regValue & (0x7F << 8)) >> 8;
+
+ rtl8306e_reg_get(5, 21, 3, ®Value);
+ 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, ®Value);
+ pSch_para->q2_n64Kbps = regValue & 0x7FF;
+ rtl8306e_reg_get(5, 19, 3, ®Value);
+ pSch_para->q3_n64Kbps = regValue & 0x7FF;
+
+ break;
+
+ case RTL8306_QOS_SET1:
+ rtl8306e_reg_get(5, 25, 3, ®Value);
+ pSch_para->q0_wt = regValue & 0x7F;
+ pSch_para->q1_wt = (regValue & (0x7F << 8)) >> 8;
+
+ rtl8306e_reg_get(5, 26, 3, ®Value);
+ 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, ®Value);
+ pSch_para->q2_n64Kbps = regValue & 0x7FF;
+ rtl8306e_reg_get(5, 24, 3, ®Value);
+ 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, ®Value);
+ 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, ®Value );
+ *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, ®Value);
+ 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, ®Value);
+ regValue &= 0xfff8;
+ regValue |= (value & 0x70) >> 4;
+ rtl8306e_reg_set(1, 26, 3, regValue);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ 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, ®Value);
+ regValue &= 0x8fff;
+ regValue |= ((value & 0x70) >> 4) << 12;
+ rtl8306e_reg_set(1, 26, 3, regValue);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ regValue &= 0x7fff;
+ regValue |= (((value & 0x10) >> 4) << 15);
+ rtl8306e_reg_set(1, 26, 3, regValue);
+
+ /*bit[6:5]*/
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ regValue &= 0xfffc;
+ regValue |= ((value & 0x60) >> 5) ;
+ rtl8306e_reg_set(1, 27, 3, regValue);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ regValue = (regValue & 0xC0FF) | ((value & 0x3f) << 8);
+ rtl8306e_reg_set(5, reg, 2, regValue);
+ }
+ else
+ {
+ rtl8306e_reg_get(5, reg, 2, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ regValue &= 0xff8f;
+ regValue |= ((value & 0x70) >> 4) << 4;
+ rtl8306e_reg_set(1, 28, 3, regValue);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ regValue &= 0xfc7f;
+ regValue |= ((value & 0x70) >> 4) << 7;
+ rtl8306e_reg_set(1, 28, 3, regValue);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ regValue = (regValue & 0xC0FF) | ((value & 0x3f) << 8);
+ rtl8306e_reg_set(5, reg, 2, regValue);
+ }
+ else
+ {
+ rtl8306e_reg_get(5, reg, 2, ®Value);
+ 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, ®Value);
+ *pValue = (regValue & mask) >> shift;
+
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ regValue &= 0x7;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ regValue &= 0x1c0;
+ regValue = regValue >> 6;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ regValue &= 0x7000;
+ regValue = regValue >> 12;
+ *pValue |= (regValue << 4);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ 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, ®Value);
+ *pValue = (regValue & mask) >> shift;
+
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ regValue &= 0x38;
+ regValue = regValue >> 3;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ regValue &= 0xe00;
+ regValue = regValue >> 9;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_reg_get(1, 26, 3, ®Value);
+ regValue &= 0x8000;
+ regValue = regValue >> 15;
+ *pValue |= (regValue << 4);
+
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ regValue &= 0x3;
+ *pValue |= (regValue << 5);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ 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, ®Value);
+ *pValue = regValue & 0x3F;
+
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_regbit_get(5, 21, 7, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_regbit_get(5, 21, 15, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_regbit_get(5, 24, 7, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else
+ {
+ rtl8306e_regbit_get(5, 24, 15, 2, ®Value);
+ *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, ®Value);
+ *pValue = (regValue & 0x3F00) >> 8 ;
+ } else
+ {
+ rtl8306e_reg_get(5, reg, 2, ®Value);
+ *pValue = (regValue & 0xFC00) >> 10;
+ }
+
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_regbit_get(5, 21, 6, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_regbit_get(5, 21, 14, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_regbit_get(5, 24, 6, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else
+ {
+ rtl8306e_regbit_get(5, 24, 14, 2, ®Value);
+ *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, ®Value);
+ *pValue = (regValue & mask) >> shift;
+
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ regValue &= 0x700;
+ regValue = regValue >> 8;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ regValue &= 0xc000;
+ regValue = regValue >> 14;
+ *pValue |= (regValue << 4);
+ rtl8306e_regbit_get(1, 28, 0, 3, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ regValue &= 0x70;
+ regValue = regValue >> 4;
+ *pValue |= (regValue << 4);
+ } else
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ 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, ®Value);
+ *pValue = (regValue & mask) >> shift;
+
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_reg_get(1, 27, 3, ®Value);
+ regValue &= 0x3800;
+ regValue = regValue >> 11;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ regValue &= 0xe;
+ regValue = regValue >> 1;
+ *pValue |= (regValue << 4);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ regValue &= 0x380;
+ regValue = regValue >> 7;
+ *pValue |= (regValue << 4);
+ }
+ else
+ {
+ rtl8306e_reg_get(1, 28, 3, ®Value);
+ 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, ®Value);
+ *pValue = (regValue & 0x3F) >> shift;
+
+ /*bit 6*/
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_regbit_get(5, 25, 7, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_regbit_get(5, 25, 15, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_regbit_get(5, 27, 7, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else
+ {
+ rtl8306e_regbit_get(5, 27, 15, 2, ®Value);
+ *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, ®Value);
+ *pValue = (regValue & 0x3F00) >> 8 ;
+ }
+ else
+ {
+ rtl8306e_reg_get(5, reg, 2, ®Value);
+ *pValue = (regValue & 0xFC00) >> 10;
+ }
+ /*bit 6*/
+ if (RTL8306_QUEUE0 == queue)
+ {
+ rtl8306e_regbit_get(5, 25, 6, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE1 == queue)
+ {
+ rtl8306e_regbit_get(5, 25, 14, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else if (RTL8306_QUEUE2 == queue)
+ {
+ rtl8306e_regbit_get(5, 27, 6, 2, ®Value);
+ *pValue |= (regValue << 6);
+ }
+ else
+ {
+ rtl8306e_regbit_get(5, 27, 14, 2, ®Value);
+ *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, ®Value);
+ else
+ rtl8306e_reg_get(port, 19, 3, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ *pData = regValue;
+ rtl8306e_reg_get(3, 22, 3, ®Value);
+ *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, ®Value1);
+ rtl8306e_reg_get(port, 23, 2, ®Value2);
+ *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, ®Value1);
+ rtl8306e_reg_get(port, 25, 2, ®Value2);
+ *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, ®Value1);
+ rtl8306e_reg_get(port, 27, 2, ®Value2);
+ *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, ®Value1);
+ rtl8306e_reg_get(port, 29, 2, ®Value2);
+ *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, ®Value1);
+ rtl8306e_reg_get(port, 31, 2, ®Value2);
+ *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, ®Value);
+ 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, ®Value);
+ regValue = (regValue & 0xFFC0) | rxmbr ;
+ rtl8306e_reg_set(6, 21, 3, regValue);
+
+ /*Set Ports Whose TX Data are Mirrored */
+ rtl8306e_reg_get(6, 21, 3, ®Value);
+ 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, ®Value);
+ *pMirport = (regValue & 0x3800) >> 11;
+
+ /*Get Ports Whose RX Data are Mirrored*/
+ rtl8306e_reg_get(6, 21, 3, ®Value);
+ *pRxmbr = regValue & 0x3F;
+
+ /*Get Ports Whose TX Data are Mirrored */
+ rtl8306e_reg_get(6, 21, 3, ®Value);
+ *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, ®Value);
+ macAddr[0] = regValue & 0xFF;
+ macAddr[1] = (regValue & 0xFF00) >> 8;
+ rtl8306e_reg_get(6, 23, 3, ®Value);
+ macAddr[2] = regValue & 0xFF;
+ macAddr[3] = (regValue & 0xFF00) >> 8;
+ rtl8306e_reg_get(6, 24, 3, ®Value);
+ 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, ®Value);
+ macAddr[5] = (regValue & 0x300) >> 8;
+ macAddr[4] = regValue & 0xF8;
+
+ /*Read Data[31:16]*/
+ rtl8306e_reg_get(4, 19, 0, ®Value);
+ macAddr[3] = (regValue & 0xFF00) >> 8;
+ macAddr[2] = regValue & 0xFF;
+
+ /*Read Data[15:0]*/
+ rtl8306e_reg_get(4, 20, 0, ®Value);
+ 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, ®Value);
+ macAddr[5] = ((regValue & 0x300) >> 8) | (*pIndex & 0xFC);
+ macAddr[4] = (regValue & 0xF8) | ((*pIndex >> 8) & 0x7);
+
+ /*Read Data[31:16]*/
+ rtl8306e_reg_get(4, 19, 0, ®Value);
+ macAddr[3] = (regValue & 0xFF00) >> 8;
+ macAddr[2] = regValue & 0xFF;
+
+ /*Read Data[15:0]*/
+ rtl8306e_reg_get(4, 20, 0, ®Value);
+ 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, ®Value);
+ *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, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+ 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, ®Value);
+ *pMacCnt = (regValue & (0x1F << 11)) >> 11;
+ }
+ else
+ {
+ rtl8306e_regbit_get(port, 30, 15, 1, &bitValue);
+ *pEnabled = bitValue ? TRUE : FALSE;
+ rtl8306e_reg_get(port, 31, 1, ®Value);
+ *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, ®Value);
+ regValue &= ~(0x7F);
+ regValue |= (macCnt & 0x7F) ;
+ rtl8306e_reg_set(0, 31, 0, regValue);
+
+ rtl8306e_reg_get(0, 31, 0, ®Value);
+ 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, ®Value);
+ *pMacCnt = (regValue & 0x7F);
+
+ rtl8306e_reg_get(0, 31, 0, ®Value);
+ *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, ®Value);
+ 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, ®Value);
+ *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, ®val);
+ *pAction = regval ? RTL8306_ACT_TRAPCPU : RTL8306_ACT_PERMIT;
+ break;
+ case RTL8306_MLD:
+ rtl8306e_regbit_get(2, 21, 13, 3, ®val);
+ *pAction = regval ? RTL8306_ACT_TRAPCPU : RTL8306_ACT_PERMIT;
+ break;
+ case RTL8306_PPPOE_IGMPMLD:
+ rtl8306e_regbit_get(2, 22, 4, 3, ®val);
+ *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, ®val);
+ *pAction = regval ? RTL8306_ACT_DROP: RTL8306_ACT_PERMIT;
+ break;
+ case RTL8306_IPV6_MULTICAST:
+ rtl8306e_regbit_get(4, 21, 8, 0, ®val);
+ *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, ®val);
+ *pAction = regval ? RTL8306_ACT_DROP: RTL8306_ACT_TRAPCPU;
+ break;
+ case RTL8306_DOT1XUNAUTH:
+ rtl8306e_regbit_get(2, 22, 5, 3, ®val);
+ *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, ®Value);
+ 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, ®Value);
+ *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, ®Value);
+ *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, ®val);
+ 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, ®val);
+ 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, ®val);
+ 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, ®val);
+ *pTrigNum = ((regval >> 8) & 0x3) ? RTL8306_STM_FILNUM256 : RTL8306_STM_FILNUM128;
+ *pFilTime = (regval >> 5) & 0x3;
+ }
+ else
+ {
+ rtl8306e_reg_get(6, 25, 0, ®val);
+ *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__*/
+
+
+