[][Add initial mtk feed for OpenWRT v21.02]

[Description]
Add initial mtk feed for OpenWRT v21.02

[Release-log]
N/A

Change-Id: I8051c6ba87f1ccf26c02fdd88a17d66f63c0b101
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4495320
diff --git a/feed/mii_mgr/Makefile b/feed/mii_mgr/Makefile
new file mode 100755
index 0000000..166e3f5
--- /dev/null
+++ b/feed/mii_mgr/Makefile
@@ -0,0 +1,36 @@
+#
+# hua.shao@mediatek.com
+#
+# MTK Property Software.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mii_mgr
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/mii_mgr
+  SECTION:=MTK Properties
+  CATEGORY:=MTK Properties
+  TITLE:=mii_mgr/mii_mgr_cl45
+  SUBMENU:=Applications
+endef
+
+define Package/mii_mgr/description
+  An mdio r/w phy regs program.
+endef
+
+define Package/mii_mgr/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/mii_mgr $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/mii_mgr $(1)/usr/sbin/mii_mgr_cl45
+endef
+
+
+$(eval $(call BuildPackage,mii_mgr))
+
diff --git a/feed/mii_mgr/src/Makefile b/feed/mii_mgr/src/Makefile
new file mode 100644
index 0000000..55d6a6f
--- /dev/null
+++ b/feed/mii_mgr/src/Makefile
@@ -0,0 +1,16 @@
+EXEC = mii_mgr
+
+CFLAGS += -Wall -Werror
+
+all: $(EXEC)
+
+mii_mgr: mii_mgr.o
+
+	$(CC) $(LDFLAGS) -o $@ $^
+
+romfs:
+	$(ROMFSINST) /bin/mii_mgr
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
+
diff --git a/feed/mii_mgr/src/mii_mgr.c b/feed/mii_mgr/src/mii_mgr.c
new file mode 100644
index 0000000..34cf8d5
--- /dev/null
+++ b/feed/mii_mgr/src/mii_mgr.c
@@ -0,0 +1,131 @@
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <linux/ethtool.h>
+#include <linux/mdio.h>
+#include <linux/sockios.h>
+
+void show_usage(void)
+{
+	printf("mii_mgr -g -i [ifname] -p [phy number] -r [register number]\n");
+	printf("  Get: mii_mgr -g -p 3 -r 4\n\n");
+	printf("mii_mgr -s -p [phy number] -r [register number] -v [0xvalue]\n");
+	printf("  Set: mii_mgr -s -p 4 -r 1 -v 0xff11\n");
+	printf("#NOTE: Without -i , eth0 is default ifname!\n");
+	printf("----------------------------------------------------------------------------------------\n");
+	printf("Get: mii_mgr_cl45 -g -p [port number] -d [dev number] -r [register number]\n");
+	printf("Example: mii_mgr_cl45 -g -p 3 -d 0x5 -r 0x4\n\n");
+	printf("Set: mii_mgr_cl45 -s -p [port number] -d [dev number] -r [register number] -v [value]\n");
+	printf("Example: mii_mgr_cl45 -s -p 4 -d 0x6 -r 0x1 -v 0xff11\n\n");
+}
+
+static int __phy_op(char *ifname,uint16_t phy_id,uint16_t reg_num, uint16_t *val, int cmd)
+{
+        static int sd = -1;
+
+        struct ifreq ifr;
+        struct mii_ioctl_data* mii = (struct mii_ioctl_data *)(&ifr.ifr_data);
+        int err;
+
+        if (sd < 0)
+                sd = socket(AF_INET, SOCK_DGRAM, 0);
+
+        if (sd < 0)
+                return sd;
+
+        strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+
+        mii->phy_id  = phy_id;
+        mii->reg_num = reg_num;
+        mii->val_in  = *val;
+        mii->val_out = 0;
+
+        err = ioctl(sd, cmd, &ifr);
+        if (err)
+                return -errno;
+
+        *val = mii->val_out;
+        return 0;
+}
+
+int main(int argc, char *argv[])
+{
+	int opt;
+	char options[] = "gsi:p:d:r:v:?t";
+	int is_write = 0,is_cl45 = 0;
+	unsigned int port=0, dev=0,reg_num=0,val=0;
+	char ifname[IFNAMSIZ]="eth0";	
+	uint16_t phy_id=0;
+
+
+	if (argc < 6) {
+		show_usage();
+		return 0;
+	}
+
+	while ((opt = getopt(argc, argv, options)) != -1) {
+		switch (opt) {
+			case 'g':
+				is_write=0;
+				break;
+			case 's':
+				is_write=1;
+				break;
+			case 'i':
+				strncpy(ifname,optarg, 5);
+				break;	
+			case 'p':
+				port = strtoul(optarg, NULL, 16);
+				break;
+                        case 'd':				
+                                dev = strtoul(optarg, NULL, 16);
+				is_cl45 = 1;
+				break;
+			case 'r':
+				reg_num = strtoul(optarg, NULL, 16);
+				break;
+
+			case 'v':
+				val = strtoul(optarg, NULL, 16);
+				break;
+			case '?':
+				show_usage();
+				break;
+		}
+	}
+
+	if(is_cl45)
+		phy_id = mdio_phy_id_c45(port, dev);
+	else
+		phy_id = port;
+
+	if(is_write) { 
+		__phy_op(ifname,phy_id,reg_num,(uint16_t *)&val,SIOCSMIIREG);
+
+		if(is_cl45)
+			printf("Set: port%x dev%Xh_reg%Xh = 0x%04X\n",port, dev, reg_num, val);
+		else
+			printf("Set: phy[%x].reg[%x] = %04x\n",port, reg_num, val);
+	}	
+	else {
+		__phy_op(ifname,phy_id,reg_num,(uint16_t *)&val,SIOCGMIIREG);
+
+		if(is_cl45)
+			printf("Get: port%x dev%Xh_reg%Xh = 0x%04X\n",port, dev, reg_num, val);
+		else
+			printf("Get: phy[%x].reg[%x] = %04x\n",port, reg_num, val);
+	
+	}
+
+	return 0;	
+}
diff --git a/feed/mt76-vendor/Makefile b/feed/mt76-vendor/Makefile
new file mode 100644
index 0000000..7436e0d
--- /dev/null
+++ b/feed/mt76-vendor/Makefile
@@ -0,0 +1,29 @@
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mt76-vendor
+PKG_RELEASE=1
+
+PKG_LICENSE:=GPLv2
+PKG_LICENSE_FILES:=
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+CMAKE_SOURCE_DIR:=$(PKG_BUILD_DIR)
+CMAKE_BINARY_DIR:=$(PKG_BUILD_DIR)
+
+define Package/mt76-vendor
+  SECTION:=devel
+  CATEGORY:=Development
+  TITLE:=vendor cmd for mt76
+  DEPENDS:=+libnl-tiny
+endef
+
+TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
+
+define Package/mt76-vendor/install
+	mkdir -p $(1)/usr/sbin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/mt76-vendor $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,mt76-vendor))
diff --git a/feed/mt76-vendor/src/CMakeLists.txt b/feed/mt76-vendor/src/CMakeLists.txt
new file mode 100644
index 0000000..97059d0
--- /dev/null
+++ b/feed/mt76-vendor/src/CMakeLists.txt
@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 2.8)
+
+PROJECT(mt76-vendor C)
+ADD_DEFINITIONS(-Os -Wall --std=gnu99 -g3)
+
+ADD_EXECUTABLE(mt76-vendor main.c)
+TARGET_LINK_LIBRARIES(mt76-vendor nl-tiny)
+
+SET(CMAKE_INSTALL_PREFIX /usr)
+
+INSTALL(TARGETS mt76-vendor
+	RUNTIME DESTINATION sbin
+)
diff --git a/feed/mt76-vendor/src/main.c b/feed/mt76-vendor/src/main.c
new file mode 100644
index 0000000..188a151
--- /dev/null
+++ b/feed/mt76-vendor/src/main.c
@@ -0,0 +1,355 @@
+// SPDX-License-Identifier: ISC
+/* Copyright (C) 2021 Mediatek Inc. */
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <net/if.h>
+
+#include "mt76-vendor.h"
+
+struct unl unl;
+static const char *progname;
+struct csi_data *csi;
+int csi_idx;
+
+static struct nla_policy csi_ctrl_policy[NUM_MTK_VENDOR_ATTRS_CSI_CTRL] = {
+	[MTK_VENDOR_ATTR_CSI_CTRL_CFG] = { .type = NLA_NESTED },
+	[MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR] = { .type = NLA_NESTED },
+	[MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM] = { .type = NLA_U16 },
+	[MTK_VENDOR_ATTR_CSI_CTRL_DATA] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy csi_data_policy[NUM_MTK_VENDOR_ATTRS_CSI_DATA] = {
+	[MTK_VENDOR_ATTR_CSI_DATA_VER] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_TS] = { .type = NLA_U64 },
+	[MTK_VENDOR_ATTR_CSI_DATA_RSSI] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_SNR] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_BW] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_CH_IDX] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_TA] = { .type = NLA_NESTED },
+	[MTK_VENDOR_ATTR_CSI_DATA_I] = { .type = NLA_NESTED },
+	[MTK_VENDOR_ATTR_CSI_DATA_Q] = { .type = NLA_NESTED },
+	[MTK_VENDOR_ATTR_CSI_DATA_INFO] = { .type = NLA_U32 },
+	[MTK_VENDOR_ATTR_CSI_DATA_TX_ANT] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_RX_ANT] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_MODE] = { .type = NLA_U8 },
+	[MTK_VENDOR_ATTR_CSI_DATA_H_IDX] = { .type = NLA_U32 },
+};
+
+void usage(void)
+{
+	static const char *const commands[] = {
+		"set csi_ctrl=",
+		"dump <packet num> <filename>",
+	};
+	int i;
+
+	fprintf(stderr, "Usage:\n");
+	for (i = 0; i < ARRAY_SIZE(commands); i++)
+		printf("  %s wlanX %s\n", progname, commands[i]);
+
+	exit(1);
+}
+
+static int mt76_dump_cb(struct nl_msg *msg, void *arg)
+{
+	struct nlattr *tb[NUM_MTK_VENDOR_ATTRS_CSI_CTRL];
+	struct nlattr *tb_data[NUM_MTK_VENDOR_ATTRS_CSI_DATA];
+	struct nlattr *attr;
+	struct nlattr *cur;
+	int rem, idx;
+	struct csi_data *c = &csi[csi_idx];
+
+	attr = unl_find_attr(&unl, msg, NL80211_ATTR_VENDOR_DATA);
+	if (!attr) {
+		fprintf(stderr, "Testdata attribute not found\n");
+		return NL_SKIP;
+	}
+
+	nla_parse_nested(tb, MTK_VENDOR_ATTR_CSI_CTRL_MAX,
+			 attr, csi_ctrl_policy);
+
+	if (!tb[MTK_VENDOR_ATTR_CSI_CTRL_DATA])
+		return NL_SKIP;
+
+	nla_parse_nested(tb_data, MTK_VENDOR_ATTR_CSI_DATA_MAX,
+			 tb[MTK_VENDOR_ATTR_CSI_CTRL_DATA], csi_data_policy);
+
+	if (!(tb_data[MTK_VENDOR_ATTR_CSI_DATA_VER] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_TS] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_RSSI] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_SNR] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_BW] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_CH_IDX] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_TA] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_I] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_Q] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_INFO] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_MODE] &&
+	      tb_data[MTK_VENDOR_ATTR_CSI_DATA_H_IDX])) {
+		fprintf(stderr, "Attributes error for CSI data\n");
+		return NL_SKIP;
+	}
+
+	c->rssi = nla_get_u8(tb_data[MTK_VENDOR_ATTR_CSI_DATA_RSSI]);
+	c->snr = nla_get_u8(tb_data[MTK_VENDOR_ATTR_CSI_DATA_SNR]);
+	c->data_bw = nla_get_u8(tb_data[MTK_VENDOR_ATTR_CSI_DATA_BW]);
+	c->pri_ch_idx = nla_get_u8(tb_data[MTK_VENDOR_ATTR_CSI_DATA_CH_IDX]);
+	c->rx_mode = nla_get_u8(tb_data[MTK_VENDOR_ATTR_CSI_DATA_MODE]);
+
+	c->tx_idx = nla_get_u16(tb_data[MTK_VENDOR_ATTR_CSI_DATA_TX_ANT]);
+	c->rx_idx = nla_get_u16(tb_data[MTK_VENDOR_ATTR_CSI_DATA_RX_ANT]);
+
+	c->info = nla_get_u32(tb_data[MTK_VENDOR_ATTR_CSI_DATA_INFO]);
+	c->h_idx = nla_get_u32(tb_data[MTK_VENDOR_ATTR_CSI_DATA_H_IDX]);
+
+	c->ts = nla_get_u64(tb_data[MTK_VENDOR_ATTR_CSI_DATA_TS]);
+
+	idx = 0;
+	nla_for_each_nested(cur, tb_data[MTK_VENDOR_ATTR_CSI_DATA_TA], rem) {
+		c->ta[idx++] = nla_get_u8(cur);
+	}
+
+	idx = 0;
+	nla_for_each_nested(cur, tb_data[MTK_VENDOR_ATTR_CSI_DATA_I], rem) {
+		c->data_i[idx++] = nla_get_u16(cur);
+	}
+
+	idx = 0;
+	nla_for_each_nested(cur, tb_data[MTK_VENDOR_ATTR_CSI_DATA_Q], rem) {
+		c->data_q[idx++] = nla_get_u16(cur);
+	}
+
+	csi_idx++;
+
+	return NL_SKIP;
+}
+
+static int mt76_csi_to_json(const char *name)
+{
+#define MAX_BUF_SIZE	6000
+	FILE *f;
+	int i;
+
+	f = fopen(name, "a+");
+	if (!f) {
+		printf("open failure");
+		return 1;
+	}
+
+	fwrite("[", 1, 1, f);
+
+	for (i = 0; i < csi_idx; i++) {
+		char *pos, *buf = malloc(MAX_BUF_SIZE);
+		struct csi_data *c = &csi[i];
+		int j;
+
+		pos = buf;
+
+		pos += snprintf(pos, MAX_BUF_SIZE, "%c", '[');
+
+		pos += snprintf(pos, MAX_BUF_SIZE, "%ld,", c->ts);
+		pos += snprintf(pos, MAX_BUF_SIZE, "\"%02x%02x%02x%02x%02x%02x\",", c->ta[0], c->ta[1], c->ta[2], c->ta[3], c->ta[4], c->ta[5]);
+
+		pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->rssi);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->snr);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->data_bw);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->pri_ch_idx);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%u,", c->rx_mode);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->tx_idx);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->rx_idx);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->h_idx);
+		pos += snprintf(pos, MAX_BUF_SIZE, "%d,", c->info);
+
+		pos += snprintf(pos, MAX_BUF_SIZE, "%c", '[');
+		for (j = 0; j < 256; j++) {
+			pos += snprintf(pos, MAX_BUF_SIZE, "%d", c->data_i[j]);
+			if (j != 255)
+				pos += snprintf(pos, MAX_BUF_SIZE, ",");
+		}
+		pos += snprintf(pos, MAX_BUF_SIZE, "%c,", ']');
+
+		pos += snprintf(pos, MAX_BUF_SIZE, "%c", '[');
+		for (j = 0; j < 256; j++) {
+			pos += snprintf(pos, MAX_BUF_SIZE, "%d", c->data_q[j]);
+			if (j != 255)
+				pos += snprintf(pos, MAX_BUF_SIZE, ",");
+		}
+		pos += snprintf(pos, MAX_BUF_SIZE, "%c", ']');
+
+		pos += snprintf(pos, MAX_BUF_SIZE, "%c", ']');
+		if (i != csi_idx - 1)
+			pos += snprintf(pos, MAX_BUF_SIZE, ",");
+
+		fwrite(buf, 1, pos - buf, f);
+		free(buf);
+	}
+
+	fwrite("]", 1, 1, f);
+	
+	fclose(f);
+}
+
+static int mt76_dump(int idx, int argc, char **argv)
+{
+	int pkt_num, ret, i;
+	struct nl_msg *msg;
+	void *data;
+
+	if (argc < 2)
+		return 1;
+	pkt_num = strtol(argv[0], NULL, 10);
+
+#define CSI_DUMP_PER_NUM	3
+	csi_idx = 0;
+	csi = (struct csi_data *)calloc(pkt_num, sizeof(*csi));
+
+	for (i = 0; i < pkt_num / CSI_DUMP_PER_NUM; i++) {
+		if (unl_genl_init(&unl, "nl80211") < 0) {
+			fprintf(stderr, "Failed to connect to nl80211\n");
+			return 2;
+		}
+
+		msg = unl_genl_msg(&unl, NL80211_CMD_VENDOR, true);
+
+		if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, idx) ||
+		nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
+		nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL))
+			return false;
+
+		data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
+
+		if (nla_put_u16(msg, MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM, CSI_DUMP_PER_NUM))
+			return false;
+
+		nla_nest_end(msg, data);
+
+		ret = unl_genl_request(&unl, msg, mt76_dump_cb, NULL);
+		if (ret)
+			fprintf(stderr, "nl80211 call failed: %s\n", strerror(-ret));
+
+		unl_free(&unl);
+	}
+
+	mt76_csi_to_json(argv[1]);
+	free(csi);
+
+	return ret;
+}
+
+static int mt76_csi_ctrl(struct nl_msg *msg, int argc, char **argv)
+{
+	int idx = MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE;
+	char *val, *s1, *s2, *cur;
+	void *data;
+
+	val = strchr(argv[0], '=');
+	if (val)
+		*(val++) = 0;
+
+	s1 = s2 = strdup(val);
+
+	data = nla_nest_start(msg, MTK_VENDOR_ATTR_CSI_CTRL_CFG | NLA_F_NESTED);
+
+	while ((cur = strsep(&s1, ",")) != NULL)
+		nla_put_u8(msg, idx++, strtoul(cur, NULL, 0));
+
+	nla_nest_end(msg, data);
+
+	free(s2);
+
+	if (argc == 2 &&
+	    !strncmp(argv[1], "mac_addr", strlen("mac_addr"))) {
+		u8 a[ETH_ALEN];
+		int matches, i;
+
+		val = strchr(argv[1], '=');
+		if (val)
+			*(val++) = 0;
+
+		matches = sscanf(val, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
+				a, a+1, a+2, a+3, a+4, a+5);
+
+		if (matches != ETH_ALEN)
+			return -EINVAL;
+
+		data = nla_nest_start(msg, MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR | NLA_F_NESTED);
+		for (i = 0; i < ETH_ALEN; i++)
+			nla_put_u8(msg, i, a[i]);
+
+		nla_nest_end(msg, data);
+	}
+
+	return 0;
+}
+
+static int mt76_set(int idx, int argc, char **argv)
+{
+	struct nl_msg *msg;
+	void *data;
+	int ret;
+
+	if (argc < 1)
+		return 1;
+
+	msg = unl_genl_msg(&unl, NL80211_CMD_VENDOR, false);
+
+	if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, idx) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, MTK_NL80211_VENDOR_ID) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL))
+		return false;
+
+	data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA | NLA_F_NESTED);
+
+	if (!strncmp(argv[0], "csi_ctrl", strlen("csi_ctrl")))
+		mt76_csi_ctrl(msg, argc, argv);
+
+	nla_nest_end(msg, data);
+
+	ret = unl_genl_request(&unl, msg, NULL, NULL);
+	if (ret)
+		fprintf(stderr, "nl80211 call failed: %s\n", strerror(-ret));
+
+	return ret;
+}
+
+int main(int argc, char **argv)
+{
+	const char *cmd;
+	int ret = 0;
+	int idx;
+
+	progname = argv[0];
+	if (argc < 3)
+		usage();
+
+	idx = if_nametoindex(argv[1]);
+	if (!idx) {
+		fprintf(stderr, "%s\n", strerror(errno));
+		return 2;
+	}
+
+	cmd = argv[2];
+	argv += 3;
+	argc -= 3;
+
+	if (!strcmp(cmd, "dump"))
+		ret = mt76_dump(idx, argc, argv);
+	else if (!strcmp(cmd, "set")) {
+		if (unl_genl_init(&unl, "nl80211") < 0) {
+			fprintf(stderr, "Failed to connect to nl80211\n");
+			return 2;
+		}
+
+		ret = mt76_set(idx, argc, argv);
+		unl_free(&unl);
+	}
+	else
+		usage();
+
+	return ret;
+}
diff --git a/feed/mt76-vendor/src/mt76-vendor.h b/feed/mt76-vendor/src/mt76-vendor.h
new file mode 100644
index 0000000..3407903
--- /dev/null
+++ b/feed/mt76-vendor/src/mt76-vendor.h
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: ISC
+/* Copyright (C) 2020 Felix Fietkau <nbd@nbd.name> */
+#ifndef __MT76_TEST_H
+#define __MT76_TEST_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <linux/nl80211.h>
+#include <netlink/attr.h>
+#include <unl.h>
+
+typedef uint8_t u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+typedef uint64_t u64;
+typedef int8_t s8;
+typedef int16_t s16;
+typedef int32_t s32;
+typedef int64_t s64, ktime_t;
+
+#define MTK_NL80211_VENDOR_ID	0x0ce7
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+#endif
+
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d))
+#endif
+
+struct nl_msg;
+struct nlattr;
+
+enum mtk_nl80211_vendor_subcmds {
+	MTK_NL80211_VENDOR_SUBCMD_CSI_CTRL = 0xc2,
+};
+
+enum mtk_vendor_attr_csi_ctrl {
+	MTK_VENDOR_ATTR_CSI_CTRL_UNSPEC,
+
+	MTK_VENDOR_ATTR_CSI_CTRL_CFG,
+	MTK_VENDOR_ATTR_CSI_CTRL_CFG_MODE,
+	MTK_VENDOR_ATTR_CSI_CTRL_CFG_TYPE,
+	MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL1,
+	MTK_VENDOR_ATTR_CSI_CTRL_CFG_VAL2,
+	MTK_VENDOR_ATTR_CSI_CTRL_MAC_ADDR,
+
+	MTK_VENDOR_ATTR_CSI_CTRL_DUMP_NUM,
+
+	MTK_VENDOR_ATTR_CSI_CTRL_DATA,
+
+	/* keep last */
+	NUM_MTK_VENDOR_ATTRS_CSI_CTRL,
+	MTK_VENDOR_ATTR_CSI_CTRL_MAX =
+		NUM_MTK_VENDOR_ATTRS_CSI_CTRL - 1
+};
+
+enum mtk_vendor_attr_csi_data {
+	MTK_VENDOR_ATTR_CSI_DATA_UNSPEC,
+	MTK_VENDOR_ATTR_CSI_DATA_PAD,
+
+	MTK_VENDOR_ATTR_CSI_DATA_VER,
+	MTK_VENDOR_ATTR_CSI_DATA_TS,
+	MTK_VENDOR_ATTR_CSI_DATA_RSSI,
+	MTK_VENDOR_ATTR_CSI_DATA_SNR,
+	MTK_VENDOR_ATTR_CSI_DATA_BW,
+	MTK_VENDOR_ATTR_CSI_DATA_CH_IDX,
+	MTK_VENDOR_ATTR_CSI_DATA_TA,
+	MTK_VENDOR_ATTR_CSI_DATA_I,
+	MTK_VENDOR_ATTR_CSI_DATA_Q,
+	MTK_VENDOR_ATTR_CSI_DATA_INFO,
+	MTK_VENDOR_ATTR_CSI_DATA_RSVD1,
+	MTK_VENDOR_ATTR_CSI_DATA_RSVD2,
+	MTK_VENDOR_ATTR_CSI_DATA_RSVD3,
+	MTK_VENDOR_ATTR_CSI_DATA_RSVD4,
+	MTK_VENDOR_ATTR_CSI_DATA_TX_ANT,
+	MTK_VENDOR_ATTR_CSI_DATA_RX_ANT,
+	MTK_VENDOR_ATTR_CSI_DATA_MODE,
+	MTK_VENDOR_ATTR_CSI_DATA_H_IDX,
+
+	/* keep last */
+	NUM_MTK_VENDOR_ATTRS_CSI_DATA,
+	MTK_VENDOR_ATTR_CSI_DATA_MAX =
+		NUM_MTK_VENDOR_ATTRS_CSI_DATA - 1
+};
+
+#define CSI_MAX_COUNT 256
+#define ETH_ALEN 6
+
+struct csi_data {
+	s16 data_i[CSI_MAX_COUNT];
+	s16 data_q[CSI_MAX_COUNT];
+	s8 rssi;
+	u8 snr;
+	ktime_t ts;
+	u8 data_bw;
+	u8 pri_ch_idx;
+	u8 ta[ETH_ALEN];
+	u32 info;
+	u8 rx_mode;
+	u32 h_idx;
+	u16 tx_idx;
+	u16 rx_idx;
+};
+
+struct vendor_field {
+	const char *name;
+	const char *prefix;
+
+	bool (*parse)(const struct vendor_field *field, int idx, struct nl_msg *msg,
+		      const char *val);
+	void (*print)(const struct vendor_field *field, struct nlattr *attr);
+
+	union {
+		struct {
+			const char * const *enum_str;
+			int enum_len;
+		};
+		struct {
+			bool (*parse2)(const struct vendor_field *field, int idx,
+				       struct nl_msg *msg, const char *val);
+			void (*print2)(const struct vendor_field *field,
+				       struct nlattr *attr);
+		};
+		struct {
+			void (*print_extra)(const struct vendor_field *field,
+					    struct nlattr **tb);
+			const struct vendor_field *fields;
+			struct nla_policy *policy;
+			int len;
+		};
+	};
+};
+
+extern struct unl unl;
+extern const struct vendor_field msg_field;
+
+void usage(void);
+
+#endif
diff --git a/feed/mtk_factory_rw/Makefile b/feed/mtk_factory_rw/Makefile
new file mode 100644
index 0000000..ad5316f
--- /dev/null
+++ b/feed/mtk_factory_rw/Makefile
@@ -0,0 +1,43 @@
+#
+# MTK-factory read and write
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtk_factory_rw
+PKG_VERSION:=1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_CONFIG_DEPENDS:=
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mtk_factory_rw
+  SECTION:=MTK Properties
+  CATEGORY:=MTK Properties
+  SUBMENU:=Misc
+  TITLE:=mtk factory read and write
+  VERSION:=$(PKG_RELEASE)-$(REVISION)
+endef
+
+define Package/mtk_factory_rw/description
+  mtk factory's data read and write
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile/Default
+endef
+
+Build/Compile = $(Build/Compile/Default)
+
+define Package/mtk_factory_rw/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(INSTALL_BIN) ./files/mtk_factory_rw.sh $(1)/sbin/mtk_factory_rw.sh
+endef
+
+$(eval $(call BuildPackage,mtk_factory_rw))
+
diff --git a/feed/mtk_factory_rw/files/mtk_factory_rw.sh b/feed/mtk_factory_rw/files/mtk_factory_rw.sh
new file mode 100755
index 0000000..7657260
--- /dev/null
+++ b/feed/mtk_factory_rw/files/mtk_factory_rw.sh
@@ -0,0 +1,160 @@
+#!/bin/sh
+
+usage()
+{
+	echo "This is a script to get or set mtk factory's data"
+	echo "-Typically, get or set the eth lan/wan mac_address-"
+	echo "Usage1: $0 <op> <side> [mac_address] "
+	echo "	<op>: -r or -w (Read or Write action)"
+	echo "	[mac_address]: MAC[1] MAC[2] MAC[3] MAC[4] MAC[5] MAC[6] (only for write action)"
+	echo "Usage2: $0 <op> <length> <offset> [data] "
+	echo "	<length>: length bytes of input"
+	echo "	<offset>: Skip offset bytes from the beginning of the input"
+	echo "Usage3: $0 -o <length> <get_from> <overwrite_to>"
+	echo "Example:"
+	echo "$0 -w lan 00 0c 43 68 55 56"
+	echo "$0 -r lan"
+	echo "$0 -w 8 0x22 11 22 33 44 55 66 77 88"
+	echo "$0 -r 8 0x22"
+	echo "$0 -o 12 0x24 0x7fff4"
+	exit 1
+}
+
+factory_name="Factory"
+factory_mtd=/dev/$(grep -i ''${factory_name}'' /proc/mtd | cut -c 1-4)
+
+#default:7622
+lan_mac_offset=0x2A
+wan_mac_offset=0x24
+
+case `cat /tmp/sysinfo/board_name` in
+	*7621*ax*)
+		# 256k - 12 byte
+		lan_mac_offset=0x3FFF4
+		wan_mac_offset=0x3FFFA
+		;;
+	*7621*)
+		lan_mac_offset=0xe000
+		wan_mac_offset=0xe006
+		;;
+	*7622*)
+		#512k -12 byte
+		lan_mac_offset=0x7FFF4
+		wan_mac_offset=0x7FFFA
+		;;
+	*7623*)
+		lan_mac_offset=0x1F800
+		wan_mac_offset=0x1F806
+		;;
+	*)
+		lan_mac_offset=0x2A
+		wan_mac_offset=0x24
+		;;
+esac
+
+#1.Read the offset's data from the Factory
+#usage: Get_offset_data length offset
+Get_offset_data()
+{
+	local length=$1
+	local offset=$2
+
+	hexdump -v -n ${length} -s ${offset} -e ''`expr ${length} - 1`'/1 "%02x-" "%02x "' ${factory_mtd}
+}
+
+overwrite_data=
+
+Get_offset_overwrite_data()
+{
+        local length=$1
+        local offset=$2
+
+        overwrite_data=`hexdump -v -n ${length} -s ${offset} -e ''\`expr ${length} - 1\`'/1 "%02x " " %02x"' ${factory_mtd}`
+}
+
+#2.Write the offset's data from the Factory
+#usage: Set_offset_data length offset data
+Set_offset_data()
+{
+	local length=$1
+	local offset=$2
+	local index=`expr $# - ${length} + 1`
+	local data=""
+
+	for j in $(seq ${index} `expr ${length} + ${index} - 1`)
+	do
+		temp=`eval echo '$'{"$j"}`
+		data=${data}"\x${temp}"
+	done
+
+	dd if=${factory_mtd} of=/tmp/Factory.backup
+	printf "${data}" | dd conv=notrunc of=/tmp/Factory.backup bs=1 seek=$((${offset}))
+	mtd write /tmp/Factory.backup ${factory_name}
+	rm -rf /tmp/Factory.backup
+}
+
+#3.Read Factory lan/wan mac address
+GetMac()
+{
+	if [ "$1" == "lan" ]; then
+		#read lan mac
+		Get_offset_data 6 ${lan_mac_offset}
+	elif [ "$1" == "wan" ]; then
+		#read wan mac
+		Get_offset_data 6 ${wan_mac_offset}
+	else
+		usage
+		exit 1
+	fi
+}
+
+
+#4.write Factory lan/wan mac address
+SetMac()
+{
+	if [ "$#" != "9" ]; then
+		echo "Mac address must be 6 bytes!"
+		exit 1
+	fi
+
+	if [ "$1" == "lan" ]; then
+		#write lan mac
+		Set_offset_data 6 ${lan_mac_offset} $@
+
+	elif [ "$1" == "wan" ]; then
+		#write wan mac
+		Set_offset_data 6 ${wan_mac_offset} $@
+	else
+		usage
+		exit 1
+	fi
+}
+
+#usage:
+# 1. Set/Get the mac_address: mtk_factory -r/-w lan/wan /data
+# 2. Set/Get the offset data: mtk_factory -r/-w length offset /data
+# 3. Overwrite from offset1 to offset2 by length byte : mtk_factory -o length from to
+if [ "$1" == "-r" ]; then
+	if [ "$2" == "lan" -o "$2" == "wan" ]; then
+		GetMac $2
+	elif [ "$2" -eq "$2" ]; then
+		Get_offset_data $2 $3
+	else
+		echo "Unknown command!"
+		usage
+		exit 1
+	fi
+elif [ "$1" == "-w" ]; then
+	if [ "$2" == "lan" -o "$2" == "wan" ]; then
+		SetMac $2 $@
+	else
+		Set_offset_data $2 $3 $@
+	fi
+elif [ "$1" == "-o" ]; then
+	Get_offset_overwrite_data $2 $3
+	Set_offset_data $2 $4 ${overwrite_data}
+else
+	echo "Unknown command!"
+	usage
+	exit 1
+fi
diff --git a/feed/mtk_failsafe/Makefile b/feed/mtk_failsafe/Makefile
new file mode 100755
index 0000000..7cbd3ca
--- /dev/null
+++ b/feed/mtk_failsafe/Makefile
@@ -0,0 +1,43 @@
+#
+# MTK-factory read and write
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtk_failsafe
+PKG_VERSION:=1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_CONFIG_DEPENDS:=
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mtk_failsafe
+  SECTION:=MTK Properties
+  CATEGORY:=MTK Properties
+  SUBMENU:=Misc
+  TITLE:=mtk failsafe script
+  VERSION:=$(PKG_RELEASE)-$(REVISION)
+endef
+
+define Package/mtk_failsafe/description
+  mtk init script for failsafe mode
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile/Default
+endef
+
+Build/Compile = $(Build/Compile/Default)
+
+define Package/mtk_failsafe/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(INSTALL_BIN) ./files/mtk_failsafe.sh $(1)/sbin/mtk_failsafe.sh
+endef
+
+$(eval $(call BuildPackage,mtk_failsafe))
+
diff --git a/feed/mtk_failsafe/files/mtk_failsafe.sh b/feed/mtk_failsafe/files/mtk_failsafe.sh
new file mode 100755
index 0000000..d9b9e60
--- /dev/null
+++ b/feed/mtk_failsafe/files/mtk_failsafe.sh
@@ -0,0 +1,39 @@
+#!/bin/sh
+
+mtk_common_init() {
+	echo "Running mtk failsafe script..."
+	echo "You can edit here : package/mtk/mtk_failsafe/file/mtk_failsafe.sh"
+	echo "mtk_common_init....."
+	mount_root
+	mount_root done
+	sync
+	echo 3 > /proc/sys/vm/drop_caches
+}
+
+mtk_wifi_init() {
+	echo "mtk_wifi_init....."
+	# once the bin is correct, unmark below
+        #insmod wifi_emi_loader
+        #rmmod wifi_emi_loader
+	#insmod mt_wifi
+        #ifconfig ra0 up
+        #ifconfig rax0 up
+}
+
+mtk_network_init() {
+	echo "mtk_network_init....."
+	# NOTE : LAN IP subnet should be 192.168.1.x
+        ifconfig eth0 0.0.0.0
+        brctl addbr br-lan
+        ifconfig br-lan 192.168.1.1 netmask 255.255.255.0 up
+        brctl addif br-lan eth0
+        #brctl addif br-lan ra0
+        #brctl addif br-lan rax0
+	./etc/init.d/telnet start
+	#./usr/bin/ated
+}
+
+mtk_common_init
+mtk_wifi_init
+mtk_network_init
+
diff --git a/feed/mtkhnat_util/Makefile b/feed/mtkhnat_util/Makefile
new file mode 100755
index 0000000..8ef168a
--- /dev/null
+++ b/feed/mtkhnat_util/Makefile
@@ -0,0 +1,48 @@
+#
+# MTK-factory read and write
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=mtkhnat_util
+PKG_VERSION:=1
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+PKG_CONFIG_DEPENDS:=
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/mtkhnat_util
+  SECTION:=net
+  CATEGORY:=Network
+  TITLE:=mtk hnat utility
+  VERSION:=$(PKG_RELEASE)-$(REVISION)
+endef
+
+define Package/mtkhnat_util/description
+  mtk hnat util to init hnat module
+endef
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)
+endef
+
+define Build/Compile/Default
+endef
+
+Build/Compile = $(Build/Compile/Default)
+
+define Package/mtkhnat_util/install
+	$(INSTALL_DIR) $(1)/sbin
+	$(INSTALL_DIR) $(1)/etc/config
+	$(INSTALL_DIR) $(1)/etc/init.d
+	$(INSTALL_DIR) $(1)/etc/uci-defaults
+
+	$(INSTALL_BIN) ./files/mtkhnat $(1)/sbin/
+	$(INSTALL_BIN) ./files/mtkhnat.config $(1)/etc/config/mtkhnat
+	$(INSTALL_BIN) ./files/mtkhnat.init $(1)/etc/init.d/mtkhnat
+	$(INSTALL_BIN) ./files/99-firewall $(1)/etc/uci-defaults	
+endef
+
+$(eval $(call BuildPackage,mtkhnat_util))
diff --git a/feed/mtkhnat_util/files/99-firewall b/feed/mtkhnat_util/files/99-firewall
new file mode 100755
index 0000000..9c72762
--- /dev/null
+++ b/feed/mtkhnat_util/files/99-firewall
@@ -0,0 +1,6 @@
+echo "iptables -t mangle -A FORWARD -m dscp --dscp-class BE -j MARK --set-mark 0" >> /etc/firewall.user
+echo "iptables -t mangle -A FORWARD -m dscp --dscp-class CS2 -j MARK --set-mark 2" >> /etc/firewall.user
+echo "iptables -t mangle -A FORWARD -m dscp --dscp-class CS4 -j MARK --set-mark 4" >> /etc/firewall.user
+echo "iptables -t mangle -A FORWARD -m dscp --dscp-class CS6 -j MARK --set-mark 6" >> /etc/firewall.user
+
+exit 0
diff --git a/feed/mtkhnat_util/files/mtkhnat b/feed/mtkhnat_util/files/mtkhnat
new file mode 100755
index 0000000..ce3ef9a
--- /dev/null
+++ b/feed/mtkhnat_util/files/mtkhnat
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+. /lib/functions.sh
+
+config_load mtkhnat
+config_get enable global enable 0
+config_get hqos global hqos 0
+config_get txq_num global txq_num 16
+config_get scheduling global scheduling "wrr"
+config_get sch0_bw global sch0_bw 100000
+config_get sch1_bw global sch1_bw 100000
+
+#if enable=0, disable qdma_sch & qdma_txq
+[ "${enable}" -eq 1 ] || {
+	echo 0 ${scheduling} ${sch0_bw} > /sys/kernel/debug/hnat/qdma_sch0
+	echo 0 ${scheduling} ${sch1_bw} > /sys/kernel/debug/hnat/qdma_sch1
+	echo 1 0 0 0 0 0 4 > /sys/kernel/debug/hnat/qdma_txq0
+	for i in $(seq 1 $((txq_num - 1)))
+	do
+		echo 0 0 0 0 0 0 0 > /sys/kernel/debug/hnat/qdma_txq$i
+	done
+
+	rmmod mtkhnat
+	exit 0
+}
+
+insmod mtkhnat
+
+#if hqos=0, disable qdma_sch & qdma_txq
+[ "${hqos}" -eq 1 ] || {
+	echo 0 ${scheduling} ${sch0_bw} > /sys/kernel/debug/hnat/qdma_sch0
+	echo 0 ${scheduling} ${sch1_bw} > /sys/kernel/debug/hnat/qdma_sch1
+	echo 1 0 0 0 0 0 4 > /sys/kernel/debug/hnat/qdma_txq0
+	for i in $(seq 1 $((txq_num - 1)))
+	do
+		echo 0 0 0 0 0 0 0 > /sys/kernel/debug/hnat/qdma_txq$i
+	done
+
+	exit 0
+}
+
+# enable qdma_sch0 and qdma_sch1
+echo 1 ${scheduling} ${sch0_bw} > /sys/kernel/debug/hnat/qdma_sch0
+echo 1 ${scheduling} ${sch1_bw} > /sys/kernel/debug/hnat/qdma_sch1
+
+setup_queue() {
+	local queue_id queue_scheduler queue_minebl queue_maxebl
+	local queue_minrate queue_maxrate queue_resv minrate maxrate queue_weight
+
+	config_get queue_id $1 id 0
+	config_get queue_minrate $1 minrate 0
+	config_get queue_maxrate $1 maxrate 0
+	config_get queue_resv $1 resv 4
+	config_get queue_weight $1 weight 4
+
+	# check qid < txq max num or not for loop condition
+	[ "${queue_id}" -gt $((txq_num - 1)) ] && return 0
+
+	# start to set per queue config
+	queue_minebl=1
+	queue_maxebl=1
+	queue_scheduler=0
+
+	# if min rate = 0, set min enable = 0
+	# if max rate = 0, set max enable = 0
+	[ "${queue_minrate}" -eq 0 ] && queue_minebl=0
+	[ "${queue_maxrate}" -eq 0 ] && queue_maxebl=0
+
+	# calculate min rate according to sch0_bw
+	minrate=$((sch0_bw * $queue_minrate))
+	minrate=$((minrate / 100))
+
+	# calculate max rate according to sch0_bw
+	maxrate=$((sch0_bw * $queue_maxrate))
+	maxrate=$((maxrate / 100))
+
+	# set the queue of sch0 group(the lower half of total queues)
+	[ "${queue_id}" -le $(((txq_num / 2) - 1)) ] && \
+	echo 0 ${queue_minebl} ${minrate} ${queue_maxebl} ${maxrate} ${queue_weight} \
+		${queue_resv} > /sys/kernel/debug/hnat/qdma_txq${queue_id}
+
+	# calculate min rate according to sch1_bw
+	minrate=$((sch1_bw * $queue_minrate))
+	minrate=$((minrate / 100))
+
+	# calculate max rate according to sch1_bw
+	maxrate=$((sch1_bw * $queue_maxrate))
+	maxrate=$((maxrate / 100))
+
+	# set the queue of sch1 group(the upper half of total queues)
+	[ "${queue_id}" -gt $(((txq_num / 2) - 1)) ] && \
+	echo 1 ${queue_minebl} ${minrate} ${queue_maxebl} ${maxrate} ${queue_weight} \
+		${queue_resv} > /sys/kernel/debug/hnat/qdma_txq${queue_id}
+}
+
+config_foreach setup_queue queue
diff --git a/feed/mtkhnat_util/files/mtkhnat.config b/feed/mtkhnat_util/files/mtkhnat.config
new file mode 100755
index 0000000..f252a98
--- /dev/null
+++ b/feed/mtkhnat_util/files/mtkhnat.config
@@ -0,0 +1,921 @@
+####################################################################
+#	hqos: 1:ON, 0:OFF                                          #
+#	txq_num: 16:default (only supports 64 queues for MT7622)   #
+#	scheduling: wrr: weighted round-robin, sp: strict priority #
+#	sch0_bw: sch0 bandwidth (unit:Kbps)                        #
+#	sch1_bw: sch1 bandwidth (unit:Kbps)                        #
+####################################################################
+config global global
+	option enable 1
+	option hqos 0
+	option txq_num 16
+	option scheduling 'wrr'
+	option sch0_bw 1000000
+	option sch1_bw 1000000
+
+####################################################################
+#	id: queue id                                               #
+#	minrate: percentage of min rate limit                      #
+#	maxrate: percentage of max rate limit                      #
+#	weight: weight for queue schedule                          #
+#	resv: buffer reserved for HW/SW path                       #
+####################################################################
+config queue
+        option id 0
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 1
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 2
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 3
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 4
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 5
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 6
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 7
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 8
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 9
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 10
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 11
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 12
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 13
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 14
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 15
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+####################################################################
+#	Default setting supports 16 queues (id: 0~15)              #
+#	Only supports 64 queues for MT7622                         #
+####################################################################
+config queue
+        option id 16
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 17
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 18
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 19
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 20
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 21
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 22
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 23
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 24
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 25
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 26
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 27
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 28
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 29
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 30
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 31
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 32
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 33
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 34
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 35
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 36
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 37
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 38
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 39
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 40
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 41
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 42
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 43
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 44
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 45
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 46
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 47
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 48
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 49
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 50
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 51
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 52
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 53
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 54
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 55
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 56
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 57
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 58
+        option minrate 30
+        option maxrate 100
+        option weight 2
+        option resv 4
+
+config queue
+        option id 59
+        option minrate 30
+        option maxrate 100
+        option weight 4
+        option resv 4
+
+config queue
+        option id 60
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 61
+        option minrate 30
+        option maxrate 100
+        option weight 6
+        option resv 4
+
+config queue
+        option id 62
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 63
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 64
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 65
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 66
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 67
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 68
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 69
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 70
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 71
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 72
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 73
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 74
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 75
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 76
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 77
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 78
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 79
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 80
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 81
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 82
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 83
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 84
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 85
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 86
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 87
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 88
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 89
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 90
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 91
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 92
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 93
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 94
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 95
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 96
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 97
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 98
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 99
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 100
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 101
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 102
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 103
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 104
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 105
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 106
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 107
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 108
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 109
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 110
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 111
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 112
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 113
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 114
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 115
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 116
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 117
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 118
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 119
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 120
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 121
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 122
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 123
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 124
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 125
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 126
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
+
+config queue
+        option id 127
+        option minrate 30
+        option maxrate 100
+        option weight 8
+        option resv 4
diff --git a/feed/mtkhnat_util/files/mtkhnat.init b/feed/mtkhnat_util/files/mtkhnat.init
new file mode 100755
index 0000000..528e62e
--- /dev/null
+++ b/feed/mtkhnat_util/files/mtkhnat.init
@@ -0,0 +1,17 @@
+#!/bin/sh /etc/rc.common
+
+START=19
+
+USE_PROCD=1
+NAME=mtkhnat
+PROG=/sbin/mtkhnat
+
+start_service() {
+	procd_open_instance
+	procd_set_param command "${PROG}"
+	procd_close_instance
+}
+
+service_triggers() {
+	procd_add_reload_trigger "mtkhnat"
+}
diff --git a/feed/regs/Makefile b/feed/regs/Makefile
new file mode 100755
index 0000000..d0f2444
--- /dev/null
+++ b/feed/regs/Makefile
@@ -0,0 +1,39 @@
+#
+# hua.shao@mediatek.com
+#
+# MTK Property Software.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=regs
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/regs
+  SECTION:=MTK Properties
+  CATEGORY:=MTK Properties
+  TITLE:=an program to read/write from/to a pci device from userspace.
+  SUBMENU:=Applications
+  DEPENDS:=+@KERNEL_DEVMEM
+endef
+
+define Package/regs/description
+  Simple program to read/write from/to a pci device from userspace.
+endef
+
+define Build/Configure
+endef
+
+define Package/regs/install
+	$(INSTALL_DIR) $(1)/usr/bin
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/regs $(1)/usr/bin
+endef
+
+
+$(eval $(call BuildPackage,regs))
+
diff --git a/feed/regs/src/Makefile b/feed/regs/src/Makefile
new file mode 100644
index 0000000..bc3a12f
--- /dev/null
+++ b/feed/regs/src/Makefile
@@ -0,0 +1,13 @@
+EXEC = regs
+
+all: $(EXEC)
+
+$(EXEC): $(EXEC).c
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $@.c $(LDLIBS)
+
+romfs:
+	$(ROMFSINST) /bin/$(EXEC)
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
+
diff --git a/feed/regs/src/regs.c b/feed/regs/src/regs.c
new file mode 100755
index 0000000..43397dd
--- /dev/null
+++ b/feed/regs/src/regs.c
@@ -0,0 +1,166 @@
+/*
+ * pcimem.c: Simple program to read/write from/to a pci device from userspace.
+ *
+ *  Copyright (C) 2010, Bill Farrow (bfarrow@beyondelectronics.us)
+ *
+ *  Based on the devmem2.c code
+ *  Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#define PRINT_ERROR \
+	do { \
+		fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
+		__LINE__, __FILE__, errno, strerror(errno)); exit(1); \
+	} while(0)
+
+#define MAP_SIZE 4096UL
+#define MAP_MASK (MAP_SIZE - 1)
+
+void dump_page(uint32_t *vaddr, uint32_t *vbase, uint32_t *pbase)
+{
+	int i =0;
+	uint32_t *end = vaddr + (MAP_SIZE >> 6);
+	uint32_t *start = vaddr;
+
+	while(start  < end) {
+		printf("%p:%08x %08x %08x %08x\n",
+			start - vbase + pbase, start[0], start[1] , start[2], start[3]);
+		start+=4;
+	}
+}
+
+void reg_mod_bits(uint32_t *virt_addr, int data, int  start_bit, int data_len)
+{
+    int mask=0;
+    int value;
+    int i;
+
+	if ((start_bit < 0) || (start_bit > 31) ||
+	    (data_len < 1) || (data_len > 32) ||
+	    (start_bit + data_len > 32)) {
+		fprintf(stderr, "Startbit range[0~31], and DataLen range[1~32], and Startbit + DataLen <= 32\n");
+		return;
+	}
+
+	for (i = 0; i < data_len; i++)
+		mask |= 1 << (start_bit + i);
+
+	value = *((volatile uint32_t *) virt_addr);
+	value &= ~mask;
+	value |= (data << start_bit) & mask;;
+
+	*((uint32_t *) virt_addr) = value;
+
+	printf("Modify 0x%X[%d:%d]; ", data, start_bit + data_len - 1, start_bit);
+}
+
+void usage(void)
+{
+		fprintf(stderr, "\nUsage:\tregs [Type] [ Offset:Hex ] [ Data:Hex ] [StartBit:Dec] [DataLen:Dec]\n"
+			"\tType    : access operation type : [m]odify, [w]wite, [d]ump\n"
+			"\tOffset  : offset into memory region to act upon\n"
+			"\tData    : data to be written\n"
+			"\tStartbit: Startbit of Addr that want to be modified. Range[0~31]\n"
+			"\tDataLen : Data length of Data. Range[1~32], and Startbit + DataLen <= 32\n\n"
+			"Example:\tRead/Write/Modify register \n"
+			"\tRead    : regs d 0x1b100000           //dump 0x1b100000~0x1b1000f0 \n"
+			"\tWrite   : regs w 0x1b100000 0x1234    //write 0x1b100000=0x1234\n"
+			"\tModify  : regs m 0x1b100000 0x0 29 3  //modify 0x1b100000[29:31]=0\n");
+}
+
+int main(int argc, char **argv) {
+	int fd;
+	void *map_base = NULL;
+        void *virt_addr = NULL;
+	uint32_t read_result =0;
+        uint32_t writeval = 0;
+	uint32_t startbit = 0;
+       	uint32_t datalen = 0;
+	char *filename = NULL;
+	off_t offset = 0;
+	int access_type = 0;
+
+	if(argc < 3) {
+		usage();
+		exit(1);
+	}
+
+	access_type = tolower(argv[1][0]);
+	if ((access_type == 'w' && argc < 4) || (access_type == 'm' && argc < 6)) {
+		usage();
+		exit(1);
+	}
+
+	filename = "/dev/mem";
+	if((fd = open(filename, O_RDWR | O_SYNC)) == -1)
+		PRINT_ERROR;
+
+	/* Map one page */
+	offset = strtoul(argv[2], NULL, 16);
+	map_base = mmap(0, 2*MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset & ~MAP_MASK);
+	if(map_base == (void *) -1)
+		PRINT_ERROR;
+
+	virt_addr = map_base + (offset & MAP_MASK);
+	read_result = *((volatile uint32_t *) virt_addr);
+	printf("Value at 0x%llX (%p): 0x%X\n",
+	       (unsigned long long)offset, virt_addr, read_result);
+
+	switch(access_type) {
+		case 'm':
+			writeval = strtoul(argv[3], 0, 16);
+			startbit = strtoul(argv[4], 0, 10);
+			datalen  = strtoul(argv[5], 0, 10);
+			reg_mod_bits((uint32_t *)virt_addr, writeval, startbit, datalen);
+			break;
+		case 'w':
+			writeval = strtoul(argv[3], 0, 16);
+			*((uint32_t *) virt_addr) = writeval;
+			printf("Written 0x%X; ", writeval);
+			break;
+		case 'd':
+			dump_page(virt_addr, map_base, (uint32_t *)(offset & ~MAP_MASK));
+			goto out;
+		default:
+			fprintf(stderr, "Illegal data type '%c'.\n", access_type);
+			goto out;
+	}
+
+	read_result = *((volatile uint32_t *) virt_addr);
+	printf("Readback 0x%X\n", read_result);
+
+out:
+	if(munmap(map_base, MAP_SIZE) == -1)
+		PRINT_ERROR;
+
+	close(fd);
+	return 0;
+}
diff --git a/feed/switch/Makefile b/feed/switch/Makefile
new file mode 100755
index 0000000..0eb3d7e
--- /dev/null
+++ b/feed/switch/Makefile
@@ -0,0 +1,48 @@
+#
+# hua.shao@mediatek.com
+#
+# MTK Property Software.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=switch
+PKG_RELEASE:=1
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+define Package/switch
+  SECTION:=MTK Properties
+  CATEGORY:=MTK Properties
+  DEPENDS:=+libnl-tiny
+  TITLE:=Command to config switch
+  SUBMENU:=Applications
+endef
+
+define Package/switch/description
+  An program to config switch.
+endef
+
+TARGET_CPPFLAGS := \
+	-D_GNU_SOURCE \
+	-I$(LINUX_DIR)/user_headers/include \
+	-I$(STAGING_DIR)/usr/include/libnl-tiny \
+	-I$(PKG_BUILD_DIR) \
+	$(TARGET_CPPFLAGS) \
+
+define Build/Compile
+	CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
+	$(MAKE) -C $(PKG_BUILD_DIR) \
+		$(TARGET_CONFIGURE_OPTS) \
+		LIBS="$(TARGET_LDFLAGS) -lnl-tiny -lm"
+endef
+
+define Package/switch/install
+	$(INSTALL_DIR) $(1)/usr/sbin
+	$(INSTALL_DIR) $(1)/lib/network
+	$(INSTALL_BIN) $(PKG_BUILD_DIR)/switch $(1)/usr/sbin
+endef
+
+$(eval $(call BuildPackage,switch))
diff --git a/feed/switch/src/Makefile b/feed/switch/src/Makefile
new file mode 100644
index 0000000..81ae127
--- /dev/null
+++ b/feed/switch/src/Makefile
@@ -0,0 +1,14 @@
+EXEC = switch
+
+SRC=switch_fun.c switch_753x.c switch_ioctl.c switch_netlink.c
+
+all: $(EXEC)
+
+switch: $(SRC)
+	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(SRC) $(LDLIBS) $(LIBS)
+
+romfs:
+	$(ROMFSINST) /bin/switch
+
+clean:
+	-rm -f $(EXEC) *.elf *.gdb *.o
diff --git a/feed/switch/src/NOTICE b/feed/switch/src/NOTICE
new file mode 100644
index 0000000..c031eed
--- /dev/null
+++ b/feed/switch/src/NOTICE
@@ -0,0 +1,202 @@
+MediaTek (C) 2011
+
+The GNU General Public License (GPL)
+
+Version 2, June 1991
+
+Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Everyone is permitted to copy and distribute verbatim copies
+of this license document, but changing it is not allowed.
+
+Preamble
+
+The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU
+General Public License is intended to guarantee your freedom to share and change free software--to make sure the
+software is free for all its users. This General Public License applies to most of the Free Software Foundation's
+software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is
+covered by the GNU Library General Public License instead.) You can apply it to your programs, too.
+
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make
+sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you
+receive source code or can get it if you want it, that you can change the software or use pieces of it in new free
+programs; and that you know you can do these things.
+
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to
+surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the
+software, or if you modify it.
+
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all
+the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them
+these terms so they know their rights.
+
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal
+permission to copy, distribute and/or modify the software.
+
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty
+for this free software. If the software is modified by someone else and passed on, we want its recipients to know that
+what they have is not the original, so that any problems introduced by others will not reflect on the original authors'
+reputations.
+
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors
+of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this,
+we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.
+
+The precise terms and conditions for copying, distribution and modification follow.
+
+TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it
+may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or
+work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to
+say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into
+another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is
+addressed as "you".
+
+Activities other than copying, distribution and modification are not covered by this License; they are outside its
+scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents
+constitute a work based on the Program (independent of having been made by running the Program). Whether that is true
+depends on what the Program does.
+
+1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided
+that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of
+warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other
+recipients of the Program a copy of this License along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection
+in exchange for a fee.
+
+2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and
+copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of
+these conditions:
+
+a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any
+change.
+
+b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the
+Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this
+License.
+
+c) If the modified program normally reads commands interactively when run, you must cause it, when started running for
+such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright
+notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may
+redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if
+the Program itself is interactive but does not normally print such an announcement, your work based on the Program is
+not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the
+Program, and can be reasonably considered independent and separate works in themselves, then this License, and its
+terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same
+sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part
+regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you;
+rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the
+Program.
+
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the
+Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.
+
+3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you also do one of the following:
+
+a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms
+of Sections 1 and 2 above on a medium customarily used for software interchange; or,
+
+b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than
+your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source
+code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange;
+or,
+
+c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This
+alternative is allowed only for noncommercial distribution and only if you received the program in object code or
+executable form with such an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for making modifications to it. For an executable work,
+complete source code means all the source code for all modules it contains, plus any associated interface definition
+files, plus the scripts used to control compilation and installation of the executable. However, as a special exception,
+the source code distributed need not include anything that is normally distributed (in either source or binary form)
+with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless
+that component itself accompanies the executable.
+
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering
+equivalent access to copy the source code from the same place counts as distribution of the source code, even though
+third parties are not compelled to copy the source along with the object code.
+
+4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your
+rights under this License. However, parties who have received copies, or rights, from you under this License will not
+have their licenses terminated so long as such parties remain in full compliance.
+
+5. You are not required to accept this License, since you have not signed it. However, nothing else grants you
+permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do
+not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you
+indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or
+modifying the Program or works based on it.
+
+6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a
+license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You
+may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not
+responsible for enforcing compliance by third parties to this License.
+
+7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to
+patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the
+conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as
+to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence
+you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution
+of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy
+both it and this License would be to refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the
+section is intended to apply and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest
+validity of any such claims; this section has the sole purpose of protecting the integrity of the free software
+distribution system, which is implemented by public license practices. Many people have made generous contributions to
+the wide range of software distributed through that system in reliance on consistent application of that system; it is
+up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee
+cannot impose that choice.
+
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.
+
+8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted
+interfaces, the original copyright holder who places the Program under this License may add an explicit geographical
+distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if written in the body of this License.
+
+9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time.
+Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or
+concerns.
+
+Each version is given a distinguishing version number. If the Program specifies a version number of this License which
+applies to it and "any later version", you have the option of following the terms and conditions either of that version
+or of any later version published by the Free Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software Foundation.
+
+10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are
+different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation,
+write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two
+goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of
+software generally.
+
+NO WARRANTY
+
+11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
+"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY
+WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
+SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
+LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF
+THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH DAMAGES.
+
+END OF TERMS AND CONDITIONS
+
+
diff --git a/feed/switch/src/switch_753x.c b/feed/switch/src/switch_753x.c
new file mode 100644
index 0000000..d0e1fc2
--- /dev/null
+++ b/feed/switch/src/switch_753x.c
@@ -0,0 +1,682 @@
+/*
+ * switch_753x.c: set for 753x switch
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include "switch_netlink.h"
+#include "switch_ioctl.h"
+#include "switch_fun.h"
+
+struct mt753x_attr *attres;
+int chip_name;
+bool nl_init_flag;
+
+static void usage(char *cmd)
+{
+	printf("==================Usage===============================================================================================================================\n");
+
+	/* 1. basic operations */
+	printf("1) mt753x switch Basic operations=================================================================================================================>>>>\n");
+	printf(" 1.1) %s devs							- list switch device id and model name  \n", cmd);
+	printf(" 1.2) %s sysctl							- show the ways to access kenerl driver: netlink or ioctl \n", cmd);
+	printf(" 1.3) %s reset							- sw reset switch fsm and registers\n", cmd);
+	printf(" 1.4) %s reg r [offset]						- read the reg with default switch \n", cmd);
+	printf(" 1.5) %s reg w [offset] [value]					- write the reg with default switch \n", cmd);
+	printf(" 1.6) %s reg d [offset]						- dump the reg with default switch\n", cmd);
+	printf(" 1.7) %s dev [devid] reg r [addr]				- read the reg with the switch devid  \n", cmd);
+	printf(" 1.8) %s dev [devid] reg w [addr] [value] 			- write the regs with the switch devid \n", cmd);
+	printf(" 1.9) %s dev [devid] reg d [addr]				- dump the regs with the switch devid \n", cmd);
+	printf("																			\n");
+
+	/* 2. phy operations */
+	printf("2) mt753x switch PHY operations===================================================================================================================>>>>\n");
+	printf(" 2.1) %s phy							- dump all phy registers (clause 22)\n", cmd);
+	printf(" 2.2) %s phy [phy_addr]						- dump phy register of specific port (clause 22)\n", cmd);
+	printf(" 2.3) %s phy cl22 r [port_num] [phy_reg]			- read specific phy register of specific port by clause 22\n", cmd);
+	printf(" 2.4) %s phy cl22 w [port_num] [phy_reg] [value]		- write specific phy register of specific port by clause 22\n", cmd);
+	printf(" 2.5) %s phy cl45 r [port_num] [dev_num] [phy_reg]		- read specific phy register of specific port by clause 45\n", cmd);
+	printf(" 2.6) %s phy cl45 w [port_num] [dev_num] [phy_reg] [value]	- write specific phy register of specific port by clause 45\n", cmd);
+	printf(" 2.7) %s phy fc [port_num] [enable 0|1]				- set switch phy flow control, port is 0~4, enable is 1, disable is 0 \n", cmd);
+	printf(" 2.8) %s phy an [port_num] [enable 0|1]				- set switch phy auto-negotiation, port is 0~4, enable is 1, disable is 0 \n", cmd);
+	printf(" 2.9) %s trreg r [port_num] [ch_addr] [node_addr] [data_addr]	- read phy token-ring of specific port\n", cmd);
+	printf(" 2.10) %s trreg w [port_num] [ch_addr] [node_addr] [data_addr]	- write phy token-ring of specific port\n", cmd);
+	printf("		[high_value] [low_value]									\n");
+	printf(" 2.11) %s crossover [port_num] [mode auto|mdi|mdix]		- switch auto or force mdi/mdix mode for crossover cable\n", cmd);
+	printf("																			\n");
+
+	/* 3. mac operations */
+	printf("3) mt753x switch MAC operations====================================================================================================================>>>>\n");
+	printf(" 3.1) %s dump							- dump switch mac table\n", cmd);
+	printf(" 3.2) %s clear							- clear switch mac table\n", cmd);
+	printf(" 3.3) %s add [mac] [portmap]					- add an entry (with portmap) to switch mac table\n", cmd);
+	printf(" 3.4) %s add [mac] [portmap] [vlan id]				- add an entry (with portmap, vlan id) to switch mac table\n", cmd);
+	printf(" 3.5) %s add [mac] [portmap] [vlan id] [age]			- add an entry (with portmap, vlan id, age out time) to switch mac table\n", cmd);
+	printf(" 3.6) %s del mac [mac] vid [vid]				- delete an entry from switch mac table\n", cmd);
+	printf(" 3.7) %s del mac [mac] fid [fid]				- delete an entry from switch mac table\n", cmd);
+	printf(" 3.8) %s search mac [mac] vid [vid]				- search an entry with specific mac and vid\n", cmd);
+	printf(" 3.9) %s search mac [mac] fid [fid]				- search an entry with specific mac and fid\n", cmd);
+	printf(" 3.10) %s filt [mac]						- add a SA filtering entry (with portmap 1111111) to switch mac table\n", cmd);
+	printf(" 3.11) %s filt [mac] [portmap]					- add a SA filtering entry (with portmap)to switch mac table\n", cmd);
+	printf(" 3.12) %s filt [mac] [portmap] [vlan id				- add a SA filtering entry (with portmap, vlan id)to switch mac table\n", cmd);
+	printf(" 3.13) %s filt [mac] [portmap] [vlan id] [age]			- add a SA filtering entry (with portmap, vlan id, age out time) to switch table\n", cmd);
+	printf(" 3.14) %s arl aging [active:0|1] [time:1~65536]			- set switch arl aging timeout value \n", cmd);
+	printf(" 3.15) %s macctl fc [enable|disable]				- set switch mac global flow control,enable is 1, disable is 0 \n", cmd);
+	printf("																			\n");
+
+	/* 4. mib counter operations */
+	printf("4) mt753x switch mib counter operations============================================================================================================>>>>\n");
+	printf(" 4.1) %s esw_cnt get						-get switch mib counters          \n", cmd);
+	printf(" 4.2) %s esw_cnt clear						-clear switch mib counters         \n", cmd);
+	printf(" 4.3) %s output_queue_cnt get					-get switch output queue counters \n", cmd);
+	printf(" 4.4) %s free_page get						-get switch system free page counters  \n", cmd);
+	printf("																			\n");
+
+	/* 5. acl function operations */
+	printf("5) mt753x switch acl function operations============================================================================================================>>>>\n");
+	printf(" 5.1) %s acl enable [port] [port_enable:0|1]			- set switch acl function enabled, port is 0~6,enable is 1, disable is 0  \n", cmd);
+	printf(" 5.2) %s acl etype add [ethtype] [portmap]			- drop L2 ethertype packets \n", cmd);
+	printf(" 5.3) %s acl dmac add [mac] [portmap]				- drop L2 dest-Mac packets \n", cmd);
+	printf(" 5.4) %s acl dip add [dip] [portmap]				- drop dip packets \n", cmd);
+	printf(" 5.5) %s acl port add [sport] [portmap]				- drop L4 UDP/TCP source port packets\n", cmd);
+	printf(" 5.6) %s acl L4 add [2byes] [portmap]				- drop L4 packets with 2bytes payload\n", cmd);
+	printf(" 5.7) %s acl acltbl-add  [tbl_idx:0~63/255] [vawd1] [vawd2]	- set switch acl table new entry, max index-7530:63,7531:255 \n", cmd);
+	printf(" 5.8) %s acl masktbl-add [tbl_idx:0~31/127] [vawd1] [vawd2]	- set switch acl mask table new entry, max index-7530:31,7531:127   \n", cmd);
+	printf(" 5.9) %s acl ruletbl-add [tbl_idx:0~31/127] [vawd1] [vawd2]	- set switch acl rule table new entry, max index-7530:31,7531:127  \n", cmd);
+	printf(" 5.10) %s acl ratetbl-add [tbl_idx:0~31] [vawd1] [vawd2] 	- set switch acl rate table new entry  \n", cmd);
+	printf(" 5.11) %s acl dip meter [dip] [portmap][meter:kbps]		- rate limit dip packets \n", cmd);
+	printf(" 5.12) %s acl dip trtcm [dip] [portmap][CIR:kbps][CBS][PIR][PBS]- TrTCM dip packets \n", cmd);
+	printf(" 5.13) %s acl dip modup [dip] [portmap][usr_pri]		- modify usr priority from ACL \n", cmd);
+	printf(" 5.14) %s acl dip pppoe [dip] [portmap]				- pppoe header removal \n", cmd);
+	printf("																			\n");
+
+	/* 6. dip table operations */
+	printf("6) mt753x switch dip table operations=================================================================================================================>>>>\n");
+	printf(" 6.1) %s dip dump						- dump switch dip table\n", cmd);
+	printf(" 6.2) %s dip clear						- clear switch dip table\n", cmd);
+	printf(" 6.3) %s dip add [dip] [portmap]				- add a dip entry to switch table\n", cmd);
+	printf(" 6.4) %s dip del [dip]						- del a dip entry to switch table\n", cmd);
+	printf("																			\n");
+
+	/* 7. sip table operations */
+	printf("7) mt753x switch sip table operations=================================================================================================================>>>>\n");
+	printf(" 7.1) %s sip dump						- dump switch sip table\n", cmd);
+	printf(" 7.2) %s sip clear						- clear switch sip table\n", cmd);
+	printf(" 7.3) %s sip add [sip] [dip] [portmap]				- add a sip entry to switch table\n", cmd);
+	printf(" 7.4) %s sip del [sip] [dip]					- del a sip entry to switch table\n", cmd);
+	printf("																			\n");
+
+	/* 8. vlan table operations */
+	printf("8) mt753x switch sip table operations====================================================================================================================>>>>\n");
+	printf(" 8.1) %s vlan dump (egtag)					- dump switch vlan table (with per port eg_tag setting)\n", cmd);
+	printf(" 8.2) %s vlan set [fid:0~7] [vid] [portmap]			- set vlan id and associated member at switch vlan table\n", cmd);
+	printf("			([stag:0~4095] [eg_con:0|1] [egtagPortMap 0:untagged 2:tagged]) \n");
+	printf("			Full Example: %s vlan set 0 3 10000100 0 0 20000200\n", cmd);
+	printf(" 8.3) %s vlan vid [vlan idx] [active:0|1] [vid] [portMap] 	- set switch vlan vid elements  \n", cmd);
+	printf("			[egtagPortMap] [ivl_en] [fid] [stag]							 \n");
+	printf(" 8.4) %s vlan pvid [port] [pvid]				- set switch vlan pvid  \n", cmd);
+	printf(" 8.5) %s vlan acc-frm [port] [acceptable_frame_type:0~3]	- set switch vlan acceptable_frame type : admit all frames: 0, \n", cmd);
+	printf("									admit only vlan-taged frames: 1,admit only untagged or priority-tagged frames: 2, reserved:3 \n");
+	printf(" 8.6) %s vlan port-attr [port] [attr:0~3]			- set switch vlan port attribute: user port: 0, statck port: 1, \n", cmd);
+	printf("									translation port: 2, transparent port:3        \n");
+	printf(" 8.7) %s vlan port-mode [port] [mode:0~3]			- set switch vlan port mode : port matrix mode: 0, fallback mode: 1,  \n", cmd);
+	printf("									check mode: 2, security mode:3                    \n");
+	printf(" 8.8) %s vlan eg-tag-pvc [port] [eg_tag:0~7]			- set switch vlan eg tag pvc : disable: 0, consistent: 1, reserved: 2, \n", cmd);
+	printf("									reserved:3,untagged:4,swap:5,tagged:6, stack:7                 \n");
+	printf(" 8.9) %s vlan eg-tag-pcr [port] [eg_tag:0~3]			- set switch vlan eg tag pcr : untagged: 0, swap: 1, tagged: 2, stack:3 \n", cmd);
+	printf("																			\n");
+
+	/* 9. rate limit operations */
+	printf("9) mt753x switch rate limit operations=================================================================================================================>>>>\n");
+	printf(" 9.1) %s ratectl [in_ex_gress:0|1] [port] [rate]		- set switch port ingress(1) or egress(0) rate  \n", cmd);
+	printf(" 9.2) %s ingress-rate on [port] [Kbps]				- set ingress rate limit on port n (n= 0~ switch max port) \n", cmd);
+	printf(" 9.3) %s egress-rate on [port] [Kbps]				- set egress rate limit on port n (n= 0~ switch max port) \n", cmd);
+	printf(" 9.4) %s ingress-rate off [port]				- disable ingress rate limit on port n (n= 0~ switch max port) \n", cmd);
+	printf(" 9.5) %s egress-rate off [port]					- disable egress rate limit on port n (n= 0~ switch max port)\n", cmd);
+	printf("																			\n");
+
+	/* 10. igmp operations */
+	printf("10) mt753x igmp operations===============================================================================================================================>>>>\n");
+	printf(" 10.1) %s igmpsnoop on [leaky_en] [wan_num]			- turn on IGMP snoop and router port learning\n", cmd);
+	printf("									leaky_en: 1 or 0. default 0; wan_num: 0 or 4. default 4\n");
+	printf(" 10.2) %s igmpsnoop off						- turn off IGMP snoop and router port learning\n", cmd);
+	printf(" 10.3) %s igmpsnoop enable [port#]				- enable IGMP HW leave/join/Squery/Gquery\n", cmd);
+	printf(" 10.4) %s igmpsnoop disable [port#]				- disable IGMP HW leave/join/Squery/Gquery\n", cmd);
+	printf("																			\n");
+
+	/* 11. QoS operations */
+	printf("11) mt753x QoS operations================================================================================================================================>>>>\n");
+	printf(" 11.1) %s qos sch [port:0~6] [queue:0~7] [shaper:min|max] [type:rr:0|sp:1|wfq:2]     - set switch qos sch type\n", cmd);
+	printf(" 11.2) %s qos base [port:0~6] [base]					- set switch qos base(UPW); port-based:0, tag-based:1, \n", cmd);
+	printf("									dscp-based:2, acl-based:3, arl-based:4, stag-based:5   \n");
+	printf(" 11.3) %s qos port-weight [port:0~6] [q0] [q1][q2][q3]		- set switch qos port queue weight; \n", cmd);
+	printf("				[q4][q5][q6][q7]				 [qn]: the weight of queue n, range: 1~16     \n");
+	printf(" 11.4) %s qos port-prio [port:0~6] [prio:0~7]			- set switch port qos user priority;  port is 0~6, priority is 0~7  \n", cmd);
+	printf(" 11.5) %s qos dscp-prio [dscp:0~63] [prio:0~7]			- set switch qos dscp user priority;  dscp is 0~63, priority is 0~7  \n", cmd);
+	printf(" 11.6) %s qos prio-qmap [port:0~6] [prio:0~7]  [queue:0~7]			- set switch qos priority queue map; priority is 0~7,queue is 0~7  \n", cmd);
+	printf("																			\n");
+
+	/*12. port mirror operations*/
+	printf(" 12) mt753x port mirror operations========================================================================================================================>>>>\n");
+	printf(" 12.1) %s mirror monitor [port]					- enable port mirror and indicate monitor port number\n", cmd);
+	printf(" 12.2) %s mirror target  [port]					- set port mirror target\n", cmd);
+	printf("			[direction| 0:off, 1:rx, 2:tx, 3:all]					\n");
+	printf(" 12.3) %s mirror enable [mirror_en:0|1] [mirror_port: 0-6]	- set switch mirror function enable(1) or disabled(0) for port 0~6  \n", cmd);
+	printf(" 12.4) %s mirror port-based [port] [port_tx_mir:0|1]		- set switch mirror port: target tx/rx/acl/vlan/igmp\n", cmd);
+	printf("				[port_rx_mir:0|1] [acl_mir:0|1]						\n");
+	printf("				[vlan_mis:0|1] [igmp_mir:0|1]						\n");
+	printf("																			\n");
+
+	/*13. stp function*/
+	printf(" 13) mt753x stp operations===============================================================================================================================>>>>\n");
+	printf(" 13.1) %s stp [port] [fid] [state]				- set switch spanning tree state, port is 0~6, fid is 0~7,  \n", cmd);
+	printf("									state is 0~3(Disable/Discarding:0,Blocking/Listening/Discarding:1,) \n");
+	printf("									Learning:2,Forwarding:3 \n");
+	printf("																			\n");
+
+	/*14. collision pool operations*/
+	printf("14) mt753x collision pool operations========================================================================================================================>>>>\n");
+	printf(" 14.1) %s collision-pool enable [enable 0|1]			- enable or disable collision pool\n", cmd);
+	printf(" 14.2) %s collision-pool mac dump				- dump collision pool mac table\n", cmd);
+	printf(" 14.3) %s collision-pool dip dump				- dump collision pool dip table\n", cmd);
+	printf(" 14.4) %s collision-pool sip dump				- dump collision pool sip table\n", cmd);
+	printf("																			\n");
+
+	/*15. pfc(priority flow control) operations*/
+	printf("15) mt753x pfc(priority flow control) operations==============================================================================================================>>>>\n");
+	printf(" 15.1) %s pfc enable [port] [enable 0|1]			- enable or disable port's pfc \n", cmd);
+	printf(" 15.2) %s pfc rx_counter [port]					- get port n pfc 8 up rx counter \n", cmd);
+	printf(" 15.3) %s pfc tx_counter [port]					- get port n pfc 8 up rx counter \n", cmd);
+	printf("																			\n");
+
+	/*15. pfc(priority flow control) operations*/
+	printf("16) mt753x EEE(802.3az) operations==============================================================================================================>>>>\n");
+	printf(" 16.1) %s eee enable [enable 0|1] ([portMap])			- enable or disable EEE (by portMap)\n", cmd);
+	printf(" 16.2) %s eee dump ([port])					- dump EEE capability (by port)\n", cmd);
+	printf("																			\n");
+
+	exit_free();
+	exit(0);
+}
+
+static void parse_reg_cmd(int argc, char *argv[], int len)
+{
+	unsigned int val;
+	unsigned int off;
+	int i, j;
+
+	if (!strncmp(argv[len - 3], "reg", 4)) {
+		if (argv[len - 2][0] == 'r') {
+			off = strtoul(argv[len - 1], NULL, 16);
+			reg_read(off, &val);
+			printf(" Read reg=%x, value=%x\n", off, val);
+		} else if (argv[len - 2][0] == 'w') {
+			off = strtoul(argv[len - 1], NULL, 16);
+			if (argc != len + 1)
+				usage(argv[0]);
+			val = strtoul(argv[len], NULL, 16);
+			reg_write(off, val);
+			printf(" Write reg=%x, value=%x\n", off, val);
+		} else if (argv[len - 2][0] == 'd') {
+			off = strtoul(argv[len - 1], NULL, 16);
+			for (i = 0; i < 16; i++) {
+				printf("0x%08x: ", off + 0x10 * i);
+				for (j = 0; j < 4; j++) {
+					reg_read(off + i * 0x10 + j * 0x4, &val);
+					printf(" 0x%08x", val);
+				}
+				printf("\n");
+			}
+		} else
+			usage(argv[0]);
+	} else
+		usage(argv[0]);
+}
+
+static int get_chip_name()
+{
+	unsigned int temp;
+	/*judge 7530*/
+	reg_read((0x7ffc), &temp);
+	temp = temp >> 16;
+	if (temp == 0x7530)
+		return temp;
+	/*judge 7531*/
+	reg_read(0x781c, &temp);
+	temp = temp >> 16;
+	if (temp == 0x7531)
+		return temp;
+	return -1;
+}
+
+static int phy_operate(int argc, char *argv[])
+{
+	unsigned int port_num;
+	unsigned int dev_num;
+	unsigned int value;
+	unsigned int reg;
+	int ret = 0;
+	char op;
+
+	if (strncmp(argv[2], "cl22", 4) && strncmp(argv[2], "cl45", 4))
+		usage(argv[0]);
+
+	op = argv[3][0];
+
+	switch(op) {
+		case 'r':
+			reg = strtoul(argv[argc-1], NULL, 0);
+			if (argc == 6) {
+				port_num = strtoul(argv[argc-2], NULL, 0);
+				ret = mii_mgr_read(port_num, reg, &value);
+				if (ret < 0)
+					printf(" Phy read reg fail\n");
+				else
+					printf(" Phy read reg=0x%x, value=0x%x\n", reg, value);
+			} else if (argc == 7) {
+				dev_num = strtoul(argv[argc-2], NULL, 0);
+				port_num = strtoul(argv[argc-3], NULL, 0);
+				ret = mii_mgr_c45_read(port_num, dev_num, reg, &value);
+				if (ret < 0)
+					printf(" Phy read reg fail\n");
+				else
+					printf(" Phy read reg=0x%x, value=0x%x\n", reg, value);
+			} else
+				ret = phy_dump(32);
+			break;
+		case 'w':
+			reg = strtoul(argv[argc-2], NULL, 0);
+			value = strtoul(argv[argc-1], NULL, 0);
+			if (argc == 7) {
+				port_num = strtoul(argv[argc-3], NULL, 0);
+				ret = mii_mgr_write(port_num, reg, value);
+			}
+			else if (argc == 8) {
+				dev_num = strtoul(argv[argc-3], NULL, 0);
+				port_num = strtoul(argv[argc-4], NULL, 0);
+				ret = mii_mgr_c45_write(port_num, dev_num, reg, value);
+			}
+			else
+				usage(argv[0]);
+			break;
+		default:
+			break;
+	}
+
+	return ret;
+}
+
+
+int main(int argc, char *argv[])
+{
+	int err;
+
+	attres = (struct mt753x_attr *)malloc(sizeof(struct mt753x_attr));
+	attres->dev_id = -1;
+	attres->port_num = -1;
+	attres->phy_dev = -1;
+	nl_init_flag = true;
+
+	err = mt753x_netlink_init(MT753X_DSA_GENL_NAME);
+	if (!err)
+		chip_name = get_chip_name();
+
+	/* dsa netlink family might not be enabled. Try gsw netlink family. */
+	if (err < 0 || chip_name < 0) {
+		err = mt753x_netlink_init(MT753X_GENL_NAME);
+		if (!err)
+			chip_name = get_chip_name();
+	}
+
+	if (err < 0 || chip_name < 0) {
+		nl_init_flag = false;
+
+		switch_ioctl_init();
+		chip_name = get_chip_name();
+		if (chip_name < 0) {
+			printf("no chip unsupport or chip id is invalid!\n");
+			exit_free();
+			exit(0);
+		}
+	}
+
+	if (argc < 2)
+		usage(argv[0]);
+
+	if (!strcmp(argv[1], "dev")) {
+		attres->dev_id = strtoul(argv[2], NULL, 0);
+		argv += 2;
+		argc -= 2;
+		if (argc < 2)
+			usage(argv[0]);
+
+	}
+
+	if (argc == 2) {
+		if (!strcmp(argv[1], "devs")) {
+			attres->type = MT753X_ATTR_TYPE_MESG;
+			mt753x_list_swdev(attres, MT753X_CMD_REQUEST);
+		} else if (!strncmp(argv[1], "dump", 5)) {
+			table_dump();
+		} else if (!strncmp(argv[1], "clear", 6)) {
+			table_clear();
+			printf("done.\n");
+		} else if (!strncmp(argv[1], "reset", 5)) {
+			switch_reset(argc, argv);
+		} else if (!strncmp(argv[1], "phy", 4)) {
+			phy_dump(32); //dump all phy register
+		} else if (!strncmp(argv[1], "sysctl", 7)) {
+			if (nl_init_flag)
+				printf("netlink(%s)\n",MT753X_GENL_NAME);
+			else
+				printf("ioctl(%s)\n",ETH_DEVNAME);
+		} else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "arl", 4)) {
+		if (!strncmp(argv[2], "aging", 6))
+			doArlAging(argc, argv);
+	} else if (!strncmp(argv[1], "esw_cnt", 8)) {
+		if (!strncmp(argv[2], "get", 4))
+			read_mib_counters();
+		else if (!strncmp(argv[2], "clear", 6))
+			clear_mib_counters();
+		else
+			usage(argv[0]);
+	}else if (!strncmp(argv[1], "output_queue_cnt", 17)) {
+		if (!strncmp(argv[2], "get", 4))
+			read_output_queue_counters();
+		else
+			usage(argv[0]);
+	}else if (!strncmp(argv[1], "free_page", 10)) {
+		if (!strncmp(argv[2], "get", 4))
+			read_free_page_counters();
+		else
+			usage(argv[0]);
+	}
+	else if (!strncmp(argv[1], "ratectl", 8))
+		rate_control(argc, argv);
+	else if (!strncmp(argv[1], "add", 4))
+		table_add(argc, argv);
+	else if (!strncmp(argv[1], "filt", 5))
+		table_add(argc, argv);
+	else if (!strncmp(argv[1], "del", 4)) {
+		if (!strncmp(argv[4], "fid", 4))
+			table_del_fid(argc, argv);
+		else if (!strncmp(argv[4], "vid", 4))
+			table_del_vid(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "search", 7)) {
+		if (!strncmp(argv[4], "fid", 4))
+			table_search_mac_fid(argc, argv);
+		else if (!strncmp(argv[4], "vid", 4))
+			table_search_mac_vid(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "phy", 4)) {
+		if (argc == 3) {
+			int phy_addr = strtoul(argv[2], NULL, 0);
+			if (phy_addr < 0 || phy_addr > 31)
+				usage(argv[0]);
+			phy_dump(phy_addr);
+		} else if (argc == 5) {
+			if (!strncmp(argv[2], "fc", 2))
+				phy_set_fc(argc, argv);
+			else if (!strncmp(argv[2], "an", 2))
+				phy_set_an(argc, argv);
+			else
+				phy_dump(32);
+		} else
+			phy_operate(argc, argv);
+	} else if (!strncmp(argv[1], "trreg", 4)) {
+		if (rw_phy_token_ring(argc, argv) < 0)
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "macctl", 7)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "fc", 3))
+			global_set_mac_fc(argc, argv);
+		else if (!strncmp(argv[2], "pfc", 4))
+			set_mac_pfc(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "qos", 4)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "sch", 4))
+			qos_sch_select(argc, argv);
+		else if (!strncmp(argv[2], "base", 5))
+			qos_set_base(argc, argv);
+		else if (!strncmp(argv[2], "port-weight", 12))
+			qos_wfq_set_weight(argc, argv);
+		else if (!strncmp(argv[2], "port-prio", 10))
+			qos_set_portpri(argc, argv);
+		else if (!strncmp(argv[2], "dscp-prio", 10))
+			qos_set_dscppri(argc, argv);
+		else if (!strncmp(argv[2], "prio-qmap", 10))
+			qos_pri_mapping_queue(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "stp", 3)) {
+		if (argc < 3)
+			usage(argv[0]);
+		else
+			doStp(argc, argv);
+	} else if (!strncmp(argv[1], "sip", 5)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "dump", 5))
+			sip_dump();
+		else if (!strncmp(argv[2], "add", 4))
+			sip_add(argc, argv);
+		else if (!strncmp(argv[2], "del", 4))
+			sip_del(argc, argv);
+		else if (!strncmp(argv[2], "clear", 6))
+			sip_clear();
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "dip", 4)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "dump", 5))
+			dip_dump();
+		else if (!strncmp(argv[2], "add", 4))
+			dip_add(argc, argv);
+		else if (!strncmp(argv[2], "del", 4))
+			dip_del(argc, argv);
+		else if (!strncmp(argv[2], "clear", 6))
+			dip_clear();
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "mirror", 7)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "monitor", 8))
+			set_mirror_to(argc, argv);
+		else if (!strncmp(argv[2], "target", 7))
+			set_mirror_from(argc, argv);
+		else if (!strncmp(argv[2], "enable", 7))
+			doMirrorEn(argc, argv);
+		else if (!strncmp(argv[2], "port-based", 11))
+			doMirrorPortBased(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "acl", 4)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "dip", 4)) {
+			if (!strncmp(argv[3], "add", 4))
+				acl_dip_add(argc, argv);
+			else if (!strncmp(argv[3], "modup", 6))
+				acl_dip_modify(argc, argv);
+			else if (!strncmp(argv[3], "pppoe", 6))
+				acl_dip_pppoe(argc, argv);
+			else if (!strncmp(argv[3], "trtcm", 4))
+				acl_dip_trtcm(argc, argv);
+			else if (!strncmp(argv[3], "meter", 6))
+				acl_dip_meter(argc, argv);
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "dmac", 6)) {
+			if (!strncmp(argv[3], "add", 4))
+				acl_mac_add(argc, argv);
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "etype", 6)) {
+			if (!strncmp(argv[3], "add", 4))
+				acl_ethertype(argc, argv);
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "port", 5)) {
+			if (!strncmp(argv[3], "add", 4))
+				acl_sp_add(argc, argv);
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "L4", 5)) {
+			if (!strncmp(argv[3], "add", 4))
+				acl_l4_add(argc, argv);
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "enable", 7))
+			acl_port_enable(argc, argv);
+		else if (!strncmp(argv[2], "acltbl-add", 11))
+			acl_table_add(argc, argv);
+		else if (!strncmp(argv[2], "masktbl-add", 12))
+			acl_mask_table_add(argc, argv);
+		else if (!strncmp(argv[2], "ruletbl-add", 12))
+			acl_rule_table_add(argc, argv);
+		else if (!strncmp(argv[2], "ratetbl-add", 12))
+			acl_rate_table_add(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "vlan", 5)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "dump", 5))
+			vlan_dump(argc, argv);
+		else if (!strncmp(argv[2], "set", 4))
+			vlan_set(argc, argv);
+		else if (!strncmp(argv[2], "clear", 6))
+			vlan_clear(argc, argv);
+		else if (!strncmp(argv[2], "vid", 4))
+			doVlanSetVid(argc, argv);
+		else if (!strncmp(argv[2], "pvid", 5))
+			doVlanSetPvid(argc, argv);
+		else if (!strncmp(argv[2], "acc-frm", 8))
+			doVlanSetAccFrm(argc, argv);
+		else if (!strncmp(argv[2], "port-attr", 10))
+			doVlanSetPortAttr(argc, argv);
+		else if (!strncmp(argv[2], "port-mode", 10))
+			doVlanSetPortMode(argc, argv);
+		else if (!strncmp(argv[2], "eg-tag-pcr", 11))
+			doVlanSetEgressTagPCR(argc, argv);
+		else if (!strncmp(argv[2], "eg-tag-pvc", 11))
+			doVlanSetEgressTagPVC(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "reg", 4)) {
+		parse_reg_cmd(argc, argv, 4);
+	} else if (!strncmp(argv[1], "ingress-rate", 6)) {
+		int port = 0, bw = 0;
+		if (argv[2][1] == 'n') {
+			port = strtoul(argv[3], NULL, 0);
+			bw = strtoul(argv[4], NULL, 0);
+			if (ingress_rate_set(1, port, bw) == 0)
+				printf("switch port=%d, bw=%d\n", port, bw);
+		}
+		else if (argv[2][1] == 'f') {
+			if (argc != 4)
+				usage(argv[0]);
+			port = strtoul(argv[3], NULL, 0);
+			if (ingress_rate_set(0, port, bw) == 0)
+				printf("switch port=%d ingress rate limit off\n", port);
+		} else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "egress-rate", 6)) {
+		int port = 0, bw = 0;
+		if (argv[2][1] == 'n') {
+			port = strtoul(argv[3], NULL, 0);
+			bw = strtoul(argv[4], NULL, 0);
+			if (egress_rate_set(1, port, bw) == 0)
+				printf("switch port=%d, bw=%d\n", port, bw);
+		} else if (argv[2][1] == 'f') {
+			if (argc != 4)
+				usage(argv[0]);
+			port = strtoul(argv[3], NULL, 0);
+			if (egress_rate_set(0, port, bw) == 0)
+				printf("switch port=%d egress rate limit off\n", port);
+		} else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "igmpsnoop", 10)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "on", 3))
+			igmp_on(argc, argv);
+		else if (!strncmp(argv[2], "off", 4))
+			igmp_off();
+		else if (!strncmp(argv[2], "enable", 7))
+			igmp_enable(argc, argv);
+		else if (!strncmp(argv[2], "disable", 8))
+			igmp_disable(argc, argv);
+		else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "collision-pool", 15)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "enable", 7))
+			collision_pool_enable(argc, argv);
+		else if (!strncmp(argv[2], "mac", 4)){
+			if (!strncmp(argv[3], "dump", 5))
+				collision_pool_mac_dump();
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "dip", 4)){
+			if (!strncmp(argv[3], "dump", 5))
+				collision_pool_dip_dump();
+			else
+				usage(argv[0]);
+		} else if (!strncmp(argv[2], "sip", 4)){
+			if (!strncmp(argv[3], "dump", 5))
+				collision_pool_sip_dump();
+			else
+				usage(argv[0]);
+			}
+		else
+			usage(argv[0]);
+	}  else if (!strncmp(argv[1], "pfc", 15)) {
+		if (argc < 4 || argc > 5)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "enable", 7))
+			set_mac_pfc(argc, argv);
+		else if (!strncmp(argv[2], "rx_counter", 11)){
+			pfc_get_rx_counter(argc, argv);
+		} else if (!strncmp(argv[2], "tx_counter", 11)){
+			pfc_get_tx_counter(argc, argv);
+		} else
+			usage(argv[0]);
+	} else if (!strncmp(argv[1], "crossover", 10)) {
+		if (argc < 4)
+			usage(argv[0]);
+		else
+			phy_crossover(argc, argv);
+	} else if (!strncmp(argv[1], "eee", 4)) {
+		if (argc < 3)
+			usage(argv[0]);
+		if (!strncmp(argv[2], "enable", 7) ||
+			 !strncmp(argv[2], "disable", 8))
+			eee_enable(argc, argv);
+		else if (!strncmp(argv[2], "dump", 5))
+			eee_dump(argc, argv);
+		else
+			usage(argv[0]);
+	} else
+		usage(argv[0]);
+
+	exit_free();
+	return 0;
+}
diff --git a/feed/switch/src/switch_extend.h b/feed/switch/src/switch_extend.h
new file mode 100644
index 0000000..c352767
--- /dev/null
+++ b/feed/switch/src/switch_extend.h
@@ -0,0 +1,342 @@
+#define atoi(x)         strtoul(x, NULL,10)
+
+#define EXTEND_SETVID_PARAM	1
+#define SQA_VERIFY		1
+#define ETHCMD_DBG		1
+#define ACTIVED	(1<<0)
+#define SWITCH_MAX_PORT		7
+
+#define GENERAL_TABLE		0
+#define COLLISION_TABLE		1
+
+#define GSW_BASE		0x0
+#define GSW_ARL_BASE		(GSW_BASE + 0x0000)
+#define GSW_BMU_BASE		(GSW_BASE + 0x1000)
+#define GSW_PORT_BASE		(GSW_BASE + 0x2000)
+#define GSW_MAC_BASE		(GSW_BASE + 0x3000)
+#define GSW_MIB_BASE		(GSW_BASE + 0x4000)
+#define GSW_CFG_BASE		(GSW_BASE + 0x7000)
+
+#define GSW_PCR(n)		(GSW_PORT_BASE + (n)*0x100 + 0x04)
+#define GSW_MFC			(GSW_ARL_BASE + 0x10)
+#define GSW_UPW(n)		(GSW_PORT_BASE + (n)*0x100 + 0x40)
+//#define GSW_PEM(n)		(GSW_ARL_BASE + (n)*0x4 + 0x48)
+#define GSW_PEM(n)		(GSW_PORT_BASE + (n)*0x4 + 0x44)
+
+#define GSW_MMSCR0_Q(n)		(GSW_BMU_BASE + (n)*0x8)
+#define GSW_MMSCR1_Q(n)		(GSW_BMU_BASE + (n)*0x8 + 0x04)
+
+#define GSW_PMCR(n)		(GSW_MAC_BASE + (n)*0x100)
+#define GSW_PMSR(n)		(GSW_MAC_BASE + (n)*0x100 + 0x08)
+#define GSW_PINT_EN(n)		(GSW_MAC_BASE + (n)*0x100 + 0x10)
+#define GSW_SMACCR0		(GSW_MAC_BASE + 0xe4)
+#define GSW_SMACCR1		(GSW_MAC_BASE + 0xe8)
+#define GSW_CKGCR		(GSW_MAC_BASE + 0xf0)
+
+#define GSW_ESR(n)		(GSW_MIB_BASE + (n)*0x100 + 0x00)
+#define GSW_INTS(n)		(GSW_MIB_BASE + (n)*0x100 + 0x04)
+#define GSW_TGPC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x10)
+#define GSW_TBOC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x14)
+#define GSW_TGOC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x18)
+#define GSW_TEPC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x1C)
+#define GSW_RGPC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x20)
+#define GSW_RBOC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x24)
+#define GSW_RGOC(n)		(GSW_MIB_BASE + (n)*0x100 + 0x28)
+#define GSW_REPC1(n)		(GSW_MIB_BASE + (n)*0x100 + 0x2C)
+#define GSW_REPC2(n)		(GSW_MIB_BASE + (n)*0x100 + 0x30)
+#define GSW_MIBCNTEN		(GSW_MIB_BASE + 0x800)
+#define GSW_AECNT1		(GSW_MIB_BASE + 0x804)
+#define GSW_AECNT2		(GSW_MIB_BASE + 0x808)
+
+#define GSW_CFG_PPSC		(GSW_CFG_BASE + 0x0)
+#define GSW_CFG_PIAC		(GSW_CFG_BASE + 0x4)
+#define GSW_CFG_GPC		(GSW_CFG_BASE + 0x14)
+
+#define MAX_VID_VALUE			(4095)
+#define MAX_VLAN_RULE			(16)
+
+
+#define REG_MFC_ADDR			(0x0010)
+#define REG_ISC_ADDR			(0x0018)
+
+#define REG_CFC_ADDR			(0x0004)
+#define REG_CFC_MIRROR_PORT_OFFT	(16)
+#define REG_CFC_MIRROR_PORT_LENG	(3)
+#define REG_CFC_MIRROR_PORT_RELMASK	(0x00000007)
+#define REG_CFC_MIRROR_PORT_MASK	(REG_CFC_MIRROR_PORT_RELMASK << REG_CFC_MIRROR_PORT_OFFT)
+#define REG_CFC_MIRROR_EN_OFFT		(19)
+#define REG_CFC_MIRROR_EN_LENG		(1)
+#define REG_CFC_MIRROR_EN_RELMASK	(0x00000001)
+#define REG_CFC_MIRROR_EN_MASK		(REG_CFC_MIRROR_EN_RELMASK << REG_CFC_MIRROR_EN_OFFT)
+
+#define REG_ATA1_ADDR			(0x0074)
+#define REG_ATA2_ADDR			(0x0078)
+
+#define REG_ATWD_ADDR			(0x007C)
+#define REG_ATWD_STATUS_OFFT		(2)
+#define REG_ATWD_STATUS_LENG		(2)
+#define REG_ATWD_STATUS_RELMASK		(0x00000003)
+#define REG_ATWD_STATUS_MASK		(REG_ATWD_STATUS_RELMASK << REG_ATWD_STATUS_OFFT)
+#define REG_ATWD_PORT_OFFT		(4)
+#define REG_ATWD_PORT_LENG		(8)
+#define REG_ATWD_PORT_RELMASK		(0x000000FF)
+#define REG_ATWD_PORT_MASK		(REG_ATWD_PORT_RELMASK << REG_ATWD_PORT_OFFT)
+#define REG_ATWD_LEAKY_EN_OFFT		(12)
+#define REG_ATWD_LEAKY_EN_LENG		(1)
+#define REG_ATWD_LEAKY_EN_RELMASK	(0x00000001)
+#define REG_ATWD_LEAKY_EN_MASK		(REG_ATWD_LEAKY_EN_RELMASK << REG_ATWD_LEAKY_EN_OFFT)
+#define REG_ATWD_EG_TAG_OFFT		(13)
+#define REG_ATWD_EG_TAG_LENG		(3)
+#define REG_ATWD_EG_TAG_RELMASK		(0x00000007)
+#define REG_ATWD_EG_TAG_MASK		(REG_ATWD_EG_TAG_RELMASK << REG_ATWD_EG_TAG_OFFT)
+#define REG_ATWD_USR_PRI_OFFT		(16)
+#define REG_ATWD_USR_PRI_LENG		(3)
+#define REG_ATWD_USR_PRI_RELMASK	(0x00000007)
+#define REG_ATWD_USR_PRI_MASK		(REG_ATWD_USR_PRI_RELMASK << REG_ATWD_USR_PRI_OFFT)
+#define REG_ATWD_SA_MIR_EN_OFFT		(19)
+#define REG_ATWD_SA_MIR_EN_LENG		(1)
+#define REG_ATWD_SA_MIR_EN_RELMASK	(0x00000001)
+#define REG_ATWD_SA_MIR_EN_MASK		(REG_ATWD_SA_MIR_EN_RELMASK << REG_ATWD_SA_MIR_EN_OFFT)
+#define REG_ATWD_SA_PORT_FW_OFFT	(20)
+#define REG_ATWD_SA_PORT_FW_LENG	(3)
+#define REG_ATWD_SA_PORT_FW_RELMASK	(0x00000007)
+#define REG_ATWD_SA_PORT_FW_MASK	(REG_ATWD_SA_PORT_FW_RELMASK << REG_ATWD_SA_PORT_FW_OFFT)
+
+#define REG_ATC_ADDR			(0x0080)
+#define REG_ATC_AC_CMD_OFFT		(0)
+#define REG_ATC_AC_CMD_LENG		(3)
+#define REG_ATC_AC_CMD_RELMASK		(0x00000007)
+#define REG_ATC_AC_CMD_MASK		(REG_ATC_AC_CMD_RELMASK << REG_ATC_AC_CMD_OFFT)
+#define REG_ATC_AC_SAT_OFFT		(4)
+#define REG_ATC_AC_SAT_LENG		(2)
+#define REG_ATC_AC_SAT_RELMASK		(0x00000003)
+#define REG_ATC_AC_SAT_MASK		(REG_ATC_AC_SAT_RELMASK << REG_ATC_AC_SAT_OFFT)
+#define REG_ATC_AC_MAT_OFFT		(8)
+#define REG_ATC_AC_MAT_LENG		(4)
+#define REG_ATC_AC_MAT_RELMASK		(0x0000000F)
+#define REG_ATC_AC_MAT_MASK		(REG_ATC_AC_MAT_RELMASK << REG_ATC_AC_MAT_OFFT)
+#define REG_AT_SRCH_HIT_OFFT		(13)
+#define REG_AT_SRCH_HIT_RELMASK		(0x00000001)
+#define REG_AT_SRCH_HIT_MASK		(REG_AT_SRCH_HIT_RELMASK << REG_AT_SRCH_HIT_OFFT)
+#define REG_AT_SRCH_END_OFFT		(14)
+#define REG_AT_SRCH_END_RELMASK		(0x00000001)
+#define REG_AT_SRCH_END_MASK		(REG_AT_SRCH_END_RELMASK << REG_AT_SRCH_END_OFFT)
+#define REG_ATC_BUSY_OFFT		(15)
+#define REG_ATC_BUSY_LENG		(1)
+#define REG_ATC_BUSY_RELMASK		(0x00000001)
+#define REG_ATC_BUSY_MASK		(REG_ATC_BUSY_RELMASK << REG_ATC_BUSY_OFFT)
+#define REG_AT_ADDR_OFFT		(16)
+#define REG_AT_ADDR_LENG		(12)
+#define REG_AT_ADDR_RELMASK		(0x00000FFF)
+#define REG_AT_ADDR_MASK		(REG_AT_ADDR_RELMASK << REG_AT_ADDR_OFFT)
+
+#define REG_TSRA1_ADDR			(0x0084)
+#define REG_TSRA2_ADDR			(0x0088)
+#define REG_ATRD_ADDR			(0x008C)
+
+#define REG_VTCR_ADDR			(0x0090)
+#define REG_VTCR_VID_OFFT		(0)
+#define REG_VTCR_VID_LENG		(12)
+#define REG_VTCR_VID_RELMASK		(0x00000FFF)
+#define REG_VTCR_VID_MASK		(REG_VTCR_VID_RELMASK << REG_VTCR_VID_OFFT)
+#define REG_VTCR_FUNC_OFFT		(12)
+#define REG_VTCR_FUNC_LENG		(4)
+#define REG_VTCR_FUNC_RELMASK		(0x0000000F)
+#define REG_VTCR_FUNC_MASK		(REG_VTCR_FUNC_RELMASK << REG_VTCR_FUNC_OFFT)
+#define REG_VTCR_IDX_INVLD_OFFT		(16)
+#define REG_VTCR_IDX_INVLD_RELMASK	(0x00000001)
+#define REG_VTCR_IDX_INVLD_MASK		(REG_VTCR_IDX_INVLD_RELMASK << REG_VTCR_IDX_INVLD_OFFT)
+#define REG_VTCR_BUSY_OFFT		(31)
+#define REG_VTCR_BUSY_RELMASK		(0x00000001)
+#define REG_VTCR_BUSY_MASK		(REG_VTCR_BUSY_RELMASK << REG_VTCR_BUSY_OFFT)
+
+#define REG_VAWD1_ADDR			(0x0094)
+#define REG_VAWD2_ADDR			(0x0098)
+#define REG_VLAN_ID_BASE		(0x0100)
+
+#define REG_CPGC_ADDR 			(0xB0)
+#define REG_CPCG_COL_EN_OFFT		(0)
+#define REG_CPCG_COL_EN_RELMASK		(0x00000001)
+#define REG_CPCG_COL_EN_MASK		(REG_CPCG_COL_EN_RELMASK << REG_CPCG_COL_EN_OFFT)
+#define REG_CPCG_COL_CLK_EN_OFFT	(1)
+#define REG_CPCG_COL_CLK_EN_RELMASK	(0x00000001)
+#define REG_CPCG_COL_CLK_EN_MASK	(REG_CPCG_COL_CLK_EN_RELMASK << REG_CPCG_COL_CLK_EN_OFFT)
+#define REG_CPCG_COL_RST_N_OFFT		(2)
+#define REG_CPCG_COL_RST_N_RELMASK	(0x00000001)
+#define REG_CPCG_COL_RST_N_MASK		(REG_CPCG_COL_RST_N_RELMASK << REG_CPCG_COL_RST_N_OFFT)
+
+#define REG_GFCCR0_ADDR			(0x1FE0)
+#define REG_FC_EN_OFFT			(31)
+#define REG_FC_EN_RELMASK		(0x00000001)
+#define REG_FC_EN_MASK			(REG_FC_EN_RELMASK << REG_FC_EN_OFFT)
+
+#define REG_PFC_CTRL_ADDR		(0x30b0)
+#define PFC_RX_COUNTER_L(n)		(0x3030 + (n)*0x100)
+#define PFC_RX_COUNTER_H(n)		(0x3034 + (n)*0x100)
+#define PFC_TX_COUNTER_L(n)		(0x3040 + (n)*0x100)
+#define PFC_TX_COUNTER_H(n)		(0x3044 + (n)*0x100)
+#define PMSR_P(n)			(0x3008 + (n)*0x100)
+
+
+#define REG_SSC_P0_ADDR			(0x2000)
+
+#define REG_PCR_P0_ADDR			(0x2004)
+#define REG_PCR_VLAN_MIS_OFFT		(2)
+#define REG_PCR_VLAN_MIS_LENG		(1)
+#define REG_PCR_VLAN_MIS_RELMASK	(0x00000001)
+#define REG_PCR_VLAN_MIS_MASK		(REG_PCR_VLAN_MIS_RELMASK << REG_PCR_VLAN_MIS_OFFT)
+#define REG_PCR_ACL_MIR_OFFT		(7)
+#define REG_PCR_ACL_MIR_LENG		(1)
+#define REG_PCR_ACL_MIR_RELMASK		(0x00000001)
+#define REG_PCR_ACL_MIR_MASK		(REG_PCR_ACL_MIR_RELMASK << REG_PCR_ACL_MIR_OFFT)
+#define REG_PORT_RX_MIR_OFFT		(8)
+#define REG_PORT_RX_MIR_LENG		(1)
+#define REG_PORT_RX_MIR_RELMASK		(0x00000001)
+#define REG_PORT_RX_MIR_MASK		(REG_PORT_RX_MIR_RELMASK << REG_PORT_RX_MIR_OFFT)
+#define REG_PORT_TX_MIR_OFFT		(9)
+#define REG_PORT_TX_MIR_LENG		(1)
+#define REG_PORT_TX_MIR_RELMASK		(0x00000001)
+#define REG_PORT_TX_MIR_MASK		(REG_PORT_TX_MIR_RELMASK << REG_PORT_TX_MIR_OFFT)
+#define REG_PORT_ACL_EN_OFFT		(10)
+#define REG_PORT_ACL_EN_LENG		(1)
+#define REG_PORT_ACL_EN_RELMASK		(0x00000001)
+#define REG_PORT_ACL_EN_MASK		(REG_PORT_ACL_EN_RELMASK << REG_PORT_ACL_EN_OFFT)
+#define REG_PCR_EG_TAG_OFFT		(28)
+#define REG_PCR_EG_TAG_LENG		(2)
+#define REG_PCR_EG_TAG_RELMASK		(0x00000003)
+#define REG_PCR_EG_TAG_MASK		(REG_PCR_EG_TAG_RELMASK << REG_PCR_EG_TAG_OFFT)
+
+#define REG_PIC_P0_ADDR			(0x2008)
+#define REG_PIC_IGMP_MIR_OFFT		(19)
+#define REG_PIC_IGMP_MIR_LENG		(1)
+#define REG_PIC_IGMP_MIR_RELMASK	(0x00000001)
+#define REG_PIC_IGMP_MIR_MASK		(REG_PIC_IGMP_MIR_RELMASK << REG_PIC_IGMP_MIR_OFFT)
+
+#define REG_PSC_P0_ADDR			(0x200C)
+
+#define REG_PVC_P0_ADDR			(0x2010)
+#define REG_PVC_ACC_FRM_OFFT		(0)
+#define REG_PVC_ACC_FRM_LENG		(2)
+#define REG_PVC_ACC_FRM_RELMASK		(0x00000003)
+#define REG_PVC_ACC_FRM_MASK		(REG_PVC_ACC_FRM_RELMASK << REG_PVC_ACC_FRM_OFFT)
+#define REG_PVC_EG_TAG_OFFT		(8)
+#define REG_PVC_EG_TAG_LENG		(3)
+#define REG_PVC_EG_TAG_RELMASK		(0x00000007)
+#define REG_PVC_EG_TAG_MASK		(REG_PVC_EG_TAG_RELMASK << REG_PVC_EG_TAG_OFFT)
+
+#define REG_PPBV1_P0_ADDR		(0x2014)
+#define REG_PPBV2_P0_ADDR		(0x2018)
+#define REG_BSR_P0_ADDR			(0x201C)
+#define REG_STAG01_P0_ADDR		(0x2020)
+#define REG_STAG23_P0_ADDR		(0x2024)
+#define REG_STAG45_P0_ADDR		(0x2028)
+#define REG_STAG67_P0_ADDR		(0x202C)
+
+#define REG_CMACCR_ADDR			(0x30E0)
+#define REG_MTCC_LMT_OFFT		(9)
+#define REG_MTCC_LMT_LENG		(4)
+#define REG_MTCC_LMT_RELMASK		(0x0000000F)
+#define REG_MTCC_LMT_MASK		(REG_MTCC_LMT_RELMASK << REG_MTCC_LMT_OFFT)
+
+#define ETHCMD_ENABLE	"enable"
+#define ETHCMD_DISABLE	"disable"
+
+#define HELP_VLAN_PVID		"vlan pvid <port> <pvid>"
+
+#if defined(EXTEND_SETVID_PARAM) || defined(SQA_VERIFY)
+#define HELP_VLAN_VID		"vlan vid <index> <active:0|1> <vid> <portMap> <egtagPortMap>\n" \
+							"	 <ivl_en> <fid> <stag>\n"
+#else
+#define HELP_VLAN_VID		"vlan vid <index> <active:0|1> <vid> <portMap> <tagPortMap>\n"
+#endif //SQA_VERIFY
+
+//#if defined(SQA_VERIFY)
+
+#define MT7530_UPW_REG_UPDATE 1
+
+#define HELP_QOS_TYPE		"qos type <rr:0|sp:1|wfq:2>\n"
+#ifdef MT7530_UPW_REG_UPDATE
+#define HELP_QOS_BASE		"qos base <port-based:0|tag-based:1|dscp-based:2|acl-based:3|arl-based:4|stag-based:5>\n"
+#else
+#define HELP_QOS_BASE		"qos base <port-based:0|tag-based:1|dscp-based:2|acl-based:3|arl-based:4>\n"
+#endif
+#define HELP_QOS_PRIO_QMAP	"qos prio-qmap <prio:0~7> <queue:0~7>\n"
+#define HELP_QOS_PRIO_TAGMAP	"qos prio-tagmap <prio:0~7> <tag:0~7>\n"
+#define HELP_QOS_PRIO_DSCPMAP	"qos prio-dscpmap <prio:0~7> <dscp:0~63>\n"
+//#define HELP_QOS_VPRI_QMAP	"qos vprio-qmap <prio:0~7> <queue:0~7>\n"
+#define HELP_QOS_PORT_PRIO	"qos port-prio <port> <prio:0~7>\n"
+#define HELP_QOS_PORT_WEIGHT	"qos port-weight <port:0~7> <q0> <q1> <q2> <q3> <q4> <q5> <q6> <q7>\n" \
+							 " <qn>: the weight of queue n, range: 1~16\n"
+#define HELP_QOS_DSCP_PRIO	"qos dscp-prio <dscp:0~63> <prio:0~7> : for ingress\n"
+
+#define HELP_ARL_L2LEN_CHK	"arl l2len-chk <active:0|1>\n"
+
+#define HELP_ARL_AGING		"arl aging <active:0|1> <time:1~65536>\n"
+
+#define HELP_ARL_MAC_TBL_ADD	"arl mactbl-add <MacAddr> <DestPortMap>\n"\
+	                        " ** optional : <leaky_en:0|1> <eg_tag:0~7> <usr_pri:0~7> <sa_mir_en:0|1> <sa_port_fw:0~7>\n"
+
+#define HELP_ARL_DIP_TBL_ADD	"arl diptbl-add <DIP> <DestPortMap> <leaky_en:0|1> <eg_tag:0~7> <usr_pri:0~7> <status:0~3>\n"
+
+#define HELP_ARL_SIP_TBL_ADD	"arl siptbl-add <DIP> <SIP> <DestPortMap> <status:0~3>\n"
+
+#define HELP_ACL_SETPORTEN	"acl enable <port> <port_enable:0|1>\n"
+#define HELP_ACL_ACL_TBL_ADD	"arl acltbl-add <tbl_idx:0~63/255> <vawd1> <vawd2>\n"
+#define HELP_ACL_MASK_TBL_ADD	"arl masktbl-add <tbl_idx:0~31/127> <vawd1> <vawd2>\n"
+#define HELP_ACL_RULE_TBL_ADD	"arl ruletbl-add <tbl_idx:0~31/127> <vawd1> <vawd2>\n"
+#define HELP_ACL_RATE_TBL_ADD	"arl ratetbl-add <tbl_idx:0~31> <vawd1> <vawd2>\n"
+#define HELP_ACL_TRTCM_TBL_ADD	"arl trTCMtbl-add <tbl_idx:0~31> <vawd1> <vawd2>\n"
+
+
+#define HELP_VLAN_PORT_MODE	"vlan port-mode <port> <mode:0~3>\n" \
+							"<mode>: 0: port matrix mode\n" \
+							"        1: fallback mode\n" \
+							"        2: check mode\n" \
+							"        3: security mode\n"\
+
+#define HELP_VLAN_PORT_ATTR	"vlan port-attr <port> <attr:0~3>\n" \
+							"<attr>: 0: user port\n" \
+							"        1: statck port\n" \
+							"        2: translation port\n" \
+							"        3: transparent port\n"
+
+#define HELP_VLAN_EGRESS_TAG_PVC	"vlan eg-tag-pvc <port> <eg_tag:0~7>\n" \
+							 "<eg_tag>: 0: disable\n" \
+							 "          1: consistent\n" \
+							 "          2: reserved\n" \
+							 "          3: reserved\n" \
+							 "          4: untagged\n" \
+							 "          5: swap\n" \
+							 "          6: tagged\n" \
+							 "          7: stack\n"
+
+#define HELP_VLAN_EGRESS_TAG_PCR	"vlan eg-tag-pcr <port> <eg_tag:0~3>\n" \
+							 "<eg_tag>: 0: untagged\n" \
+							 "          1: swap\n" \
+							 "          2: tagged\n" \
+							 "          3: stack\n"
+
+#define HELP_VLAN_ACC_FRM	"vlan acc-frm <port> <acceptable_frame_type:0~3>\n" \
+							"<type>: 0: admit all frames\n" \
+							"        1: admit only vlan-taged frames\n" \
+							"        2: admit only untagged or priority-tagged frames\n" \
+							"        3: reserved\n"
+
+
+#define HELP_SWITCH_RESET	"switch software reset\n"
+#define HELP_MACCTL_FC		"macctl fc <enable:0|1>\n"
+#define HELP_MIRROR_EN		"mirror enable <mirror_en:0|1> <mirror_port: 0-6>\n"
+#define HELP_MIRROR_PORTBASED	"mirror port-based <port> <port_tx_mir:0|1> <port_rx_mir:0|1> <acl_mir:0|1> <vlan_mis:0|1> <igmp_mir:0|1>\n"
+
+#define HELP_PHY_AN_EN		"phyctl an <port> <auto_negotiation_en:0|1>\n"
+#define HELP_PHY_FC_EN		"phyctl fc <port> <full_duplex_pause_capable:0|1>\n"
+
+#define HELP_STP		"stp <port> <fid> <state>\n" \
+						 "<state>: 0: Disable/Discarding\n" \
+						 "         1: Blocking/Listening/Discarding\n" \
+						 "         2: Learning\n" \
+						 "         3: Forwarding\n"
+#define HELP_COLLISION_POOL_EN	"collision-pool enable [enable 0|1] \n"
+#define HELP_EEE_EN		"eee [enable|disable] ([port|portMap]) \n"
+
+//#endif //SQA_VERIFY
diff --git a/feed/switch/src/switch_fun.c b/feed/switch/src/switch_fun.c
new file mode 100755
index 0000000..aefb927
--- /dev/null
+++ b/feed/switch/src/switch_fun.c
@@ -0,0 +1,3753 @@
+/*
+* switch_fun.c: switch function sets
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <stdbool.h>
+#include <time.h>
+
+#include "switch_extend.h"
+#include "switch_netlink.h"
+#include "switch_ioctl.h"
+#include "switch_fun.h"
+
+#define leaky_bucket 0
+
+static int getnext(char *src, int separator, char *dest)
+{
+	char *c;
+	int len;
+
+	if ((src == NULL) || (dest == NULL))
+		return -1;
+
+	c = strchr(src, separator);
+	if (c == NULL)
+		return -1;
+
+	len = c - src;
+	strncpy(dest, src, len);
+	dest[len] = '\0';
+	return len + 1;
+}
+
+static int str_to_ip(unsigned int *ip, char *str)
+{
+	int i;
+	int len;
+	char *ptr = str;
+	char buf[128];
+	unsigned char c[4];
+
+	for (i = 0; i < 3; ++i) {
+		if ((len = getnext(ptr, '.', buf)) == -1)
+			return 1;
+		c[i] = atoi(buf);
+		ptr += len;
+	}
+	c[3] = atoi(ptr);
+	*ip = (c[0] << 24) + (c[1] << 16) + (c[2] << 8) + c[3];
+	return 0;
+}
+
+/*convert IP address from number to string */
+static void ip_to_str(char *str, unsigned int ip)
+{
+	unsigned char *ptr = (unsigned char *)&ip;
+	unsigned char c[4];
+
+	c[0] = *(ptr);
+	c[1] = *(ptr + 1);
+	c[2] = *(ptr + 2);
+	c[3] = *(ptr + 3);
+	/*sprintf(str, "%d.%d.%d.%d", c[0], c[1], c[2], c[3]);*/
+	sprintf(str, "%d.%d.%d.%d", c[3], c[2], c[1], c[0]);
+}
+
+int reg_read(unsigned int offset, unsigned int *value)
+{
+	int ret = -1;
+
+	if (nl_init_flag == true) {
+		ret = reg_read_netlink(attres, offset, value);
+	} else {
+		if (attres->dev_id == -1)
+			ret = reg_read_ioctl(offset, value);
+	}
+	if (ret < 0) {
+		printf("Read fail\n");
+		*value = 0;
+		return ret;
+	}
+
+	return 0;
+}
+
+int reg_write(unsigned int offset, unsigned int value)
+{
+	int ret = -1;
+
+	if (nl_init_flag == true) {
+		ret = reg_write_netlink(attres, offset, value);
+	} else {
+		if (attres->dev_id == -1)
+			ret = reg_write_ioctl(offset, value);
+	}
+	if (ret < 0) {
+		printf("Write fail\n");
+		exit_free();
+		exit(0);
+	}
+	return 0;
+}
+
+int mii_mgr_read(unsigned int port_num, unsigned int reg, unsigned int *value)
+{
+	int ret;
+
+	if (port_num > 31) {
+		printf("Invalid Port or PHY addr \n");
+		return -1;
+	}
+
+	if (nl_init_flag == true)
+		ret = phy_cl22_read_netlink(attres, port_num, reg, value);
+	else
+		ret = mii_mgr_cl22_read_ioctl(port_num, reg, value);
+
+	if (ret < 0) {
+		printf("Phy read fail\n");
+		exit_free();
+		exit(0);
+	}
+
+	return 0;
+}
+
+int mii_mgr_write(unsigned int port_num, unsigned int reg, unsigned int value)
+{
+	int ret;
+
+	if (port_num > 31) {
+		printf("Invalid Port or PHY addr \n");
+		return -1;
+	}
+
+	if (nl_init_flag == true)
+		ret = phy_cl22_write_netlink(attres, port_num, reg, value);
+	else
+		ret = mii_mgr_cl22_write_ioctl(port_num, reg, value);
+
+	if (ret < 0) {
+		printf("Phy write fail\n");
+		exit_free();
+		exit(0);
+	}
+
+	return 0;
+}
+
+int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int *value)
+{
+	int ret;
+
+	if (port_num > 31) {
+		printf("Invalid Port or PHY addr \n");
+		return -1;
+	}
+
+	if (nl_init_flag == true)
+		ret = phy_cl45_read_netlink(attres, port_num, dev, reg, value);
+	else
+		ret = mii_mgr_cl45_read_ioctl(port_num, dev, reg, value);
+
+	if (ret < 0) {
+		printf("Phy read fail\n");
+		exit_free();
+		exit(0);
+	}
+
+	return 0;
+}
+
+int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int value)
+{
+	int ret;
+
+	if (port_num > 31) {
+		printf("Invalid Port or PHY addr \n");
+		return -1;
+	}
+
+	if (nl_init_flag == true)
+		ret = phy_cl45_write_netlink(attres, port_num, dev, reg, value);
+	else
+		ret = mii_mgr_cl45_write_ioctl(port_num, dev, reg, value);
+
+	if (ret < 0) {
+		printf("Phy write fail\n");
+		exit_free();
+		exit(0);
+	}
+
+	return 0;
+}
+
+
+int phy_dump(int phy_addr)
+{
+	int ret;
+
+	if (nl_init_flag == true)
+		ret = phy_dump_netlink(attres, phy_addr);
+	else
+		ret = phy_dump_ioctl(phy_addr);
+
+	if (ret < 0) {
+		printf("Phy dump fail\n");
+		exit_free();
+		exit(0);
+	}
+
+	return 0;
+}
+
+void phy_crossover(int argc, char *argv[])
+{
+	unsigned int port_num = strtoul(argv[2], NULL, 10);
+	unsigned int value;
+	int ret;
+
+	if (port_num > 4) {
+		printf("invaild value, port_name:0~4\n");
+		return;
+	}
+
+	if (nl_init_flag == true)
+		ret = phy_cl45_read_netlink(attres, port_num, 0x1E, MT7530_T10_TEST_CONTROL, &value);
+	else
+		ret = mii_mgr_cl45_read_ioctl(port_num, 0x1E, MT7530_T10_TEST_CONTROL, &value);
+	if (ret < 0) {
+		printf("phy_cl45 read fail\n");
+		exit_free();
+		exit(0);
+	}
+
+	printf("mii_mgr_cl45:");
+	printf("Read:  port#=%d, device=0x%x, reg=0x%x, value=0x%x\n", port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+
+	if (!strncmp(argv[3], "auto", 5))
+	{
+		value &= (~(0x3 << 3));
+	} else if (!strncmp(argv[3], "mdi", 4)) {
+		value &= (~(0x3 << 3));
+		value |= (0x2 << 3);
+	} else if (!strncmp(argv[3], "mdix", 5)) {
+		value |= (0x3 << 3);
+	} else {
+		printf("invaild parameter\n");
+		return;
+	}
+	printf("Write: port#=%d, device=0x%x, reg=0x%x. value=0x%x\n", port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+
+	if (nl_init_flag == true)
+		ret = phy_cl45_write_netlink(attres, port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+	else
+		ret = mii_mgr_cl45_write_ioctl(port_num, 0x1E, MT7530_T10_TEST_CONTROL, value);
+
+	if (ret < 0) {
+		printf("phy_cl45 write fail\n");
+		exit_free();
+		exit(0);
+	}
+}
+
+int rw_phy_token_ring(int argc, char *argv[])
+{
+	int ch_addr, node_addr, data_addr;
+	unsigned int tr_reg_control;
+	unsigned int val_l = 0;
+	unsigned int val_h = 0;
+	unsigned int port_num;
+
+	if (argc < 4)
+		return -1;
+
+	if (argv[2][0] == 'r') {
+		if (argc != 7)
+			return -1;
+		mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
+		port_num = strtoul(argv[3], NULL, 0);
+		if (port_num > MAX_PORT) {
+			printf("Illegal port index and port:0~6\n");
+			return -1;
+		}
+		ch_addr = strtoul(argv[4], NULL, 0);
+		node_addr = strtoul(argv[5], NULL, 0);
+		data_addr = strtoul(argv[6], NULL, 0);
+		printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n", port_num, ch_addr, node_addr, data_addr);
+		tr_reg_control = (1 << 15) | (1 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1);
+		mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
+		mii_mgr_read(port_num, 17, &val_l);
+		mii_mgr_read(port_num, 18, &val_h);
+		printf("switch trreg read tr_reg_control=%x, value_H=%x, value_L=%x\n", tr_reg_control, val_h, val_l);
+	} else if (argv[2][0] == 'w') {
+		if (argc != 9)
+			return -1;
+		mii_mgr_write(0, 0x1f, 0x52b5); // r31 = 0x52b5
+		port_num = strtoul(argv[3], NULL, 0);
+		if (port_num > MAX_PORT) {
+			printf("\n**Illegal port index and port:0~6\n");
+			return -1;
+		}
+		ch_addr = strtoul(argv[4], NULL, 0);
+		node_addr = strtoul(argv[5], NULL, 0);
+		data_addr = strtoul(argv[6], NULL, 0);
+		val_h = strtoul(argv[7], NULL, 0);
+		val_l = strtoul(argv[8], NULL, 0);
+		printf("port = %x, ch_addr = %x, node_addr=%x, data_addr=%x\n", port_num, ch_addr, node_addr, data_addr);
+		tr_reg_control = (1 << 15) | (0 << 13) | (ch_addr << 11) | (node_addr << 7) | (data_addr << 1);
+		mii_mgr_write(port_num, 17, val_l);
+		mii_mgr_write(port_num, 18, val_h);
+		mii_mgr_write(port_num, 16, tr_reg_control); // r16 = tr_reg_control
+		printf("switch trreg Write tr_reg_control=%x, value_H=%x, value_L=%x\n", tr_reg_control, val_h, val_l);
+	} else
+		return -1;
+	return 0;
+}
+
+void write_acl_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+	unsigned int value, reg;
+	unsigned int max_index;
+
+	if (chip_name == 0x7531)
+		max_index = 256;
+	else
+		max_index = 64;
+
+	printf("Pattern_acl_tbl_idx:%d\n", tbl_idx);
+
+	if (tbl_idx >= max_index) {
+		printf(HELP_ACL_ACL_TBL_ADD);
+		return;
+	}
+
+	reg = REG_VTCR_ADDR;
+	while (1)
+	{ // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0) {
+			break;
+		}
+	}
+	reg_write(REG_VAWD1_ADDR, vawd1);
+	printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+	reg_write(REG_VAWD2_ADDR, vawd2);
+	printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+	reg = REG_VTCR_ADDR;
+	value = REG_VTCR_BUSY_MASK | (0x05 << REG_VTCR_FUNC_OFFT) | tbl_idx;
+	reg_write(reg, value);
+	printf("write reg: %x, value: %x\n", reg, value);
+
+	while (1)
+	{ 	// wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+}
+
+void acl_table_add(int argc, char *argv[])
+{
+	unsigned int vawd1, vawd2;
+	unsigned char tbl_idx;
+
+	tbl_idx = atoi(argv[3]);
+	vawd1 = strtoul(argv[4], (char **)NULL, 16);
+	vawd2 = strtoul(argv[5], (char **)NULL, 16);
+	write_acl_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_acl_mask_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+	unsigned int value, reg;
+	unsigned int max_index;
+
+	if (chip_name == 0x7531)
+		max_index = 128;
+	else
+		max_index = 32;
+
+	printf("Rule_mask_tbl_idx:%d\n", tbl_idx);
+
+	if (tbl_idx >= max_index) {
+		printf(HELP_ACL_MASK_TBL_ADD);
+		return;
+	}
+	reg = REG_VTCR_ADDR;
+	while (1)
+	{ // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+	reg_write(REG_VAWD1_ADDR, vawd1);
+	printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+	reg_write(REG_VAWD2_ADDR, vawd2);
+	printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+	reg = REG_VTCR_ADDR;
+	value = REG_VTCR_BUSY_MASK | (0x09 << REG_VTCR_FUNC_OFFT) | tbl_idx;
+	reg_write(reg, value);
+	printf("write reg: %x, value: %x\n", reg, value);
+	while (1)
+	{ // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+}
+
+void acl_mask_table_add(int argc, char *argv[])
+{
+	unsigned int vawd1, vawd2;
+	unsigned char tbl_idx;
+
+	tbl_idx = atoi(argv[3]);
+	vawd1 = strtoul(argv[4], (char **)NULL, 16);
+	vawd2 = strtoul(argv[5], (char **)NULL, 16);
+	write_acl_mask_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_acl_rule_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+	unsigned int value, reg;
+	unsigned int max_index;
+
+	if (chip_name == 0x7531)
+		max_index = 128;
+	else
+		max_index = 32;
+
+	printf("Rule_control_tbl_idx:%d\n", tbl_idx);
+
+	if (tbl_idx >= max_index) { /*Check the input parameters is right or not.*/
+		printf(HELP_ACL_RULE_TBL_ADD);
+		return;
+	}
+	reg = REG_VTCR_ADDR;
+
+	while (1)
+	{ // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0) {
+			break;
+		}
+	}
+	reg_write(REG_VAWD1_ADDR, vawd1);
+	printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+	reg_write(REG_VAWD2_ADDR, vawd2);
+	printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+	reg = REG_VTCR_ADDR;
+	value = REG_VTCR_BUSY_MASK | (0x0B << REG_VTCR_FUNC_OFFT) | tbl_idx;
+	reg_write(reg, value);
+	printf("write reg: %x, value: %x\n", reg, value);
+
+	while (1)
+	{ // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0) {
+			break;
+		}
+	}
+}
+
+void acl_rule_table_add(int argc, char *argv[])
+{
+	unsigned int vawd1, vawd2;
+	unsigned char tbl_idx;
+
+	tbl_idx = atoi(argv[3]);
+	vawd1 = strtoul(argv[4], (char **)NULL, 16);
+	vawd2 = strtoul(argv[5], (char **)NULL, 16);
+	write_acl_rule_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_rate_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+	unsigned int value, reg;
+	unsigned int max_index = 32;
+
+	printf("Rule_action_tbl_idx:%d\n", tbl_idx);
+
+	if (tbl_idx >= max_index) {
+		printf(HELP_ACL_RATE_TBL_ADD);
+		return;
+	}
+
+	reg = REG_VTCR_ADDR;
+	while (1) { 	// wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+
+	reg_write(REG_VAWD1_ADDR, vawd1);
+	printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+	reg_write(REG_VAWD2_ADDR, vawd2);
+	printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+	reg = REG_VTCR_ADDR;
+	value = REG_VTCR_BUSY_MASK | (0x0D << REG_VTCR_FUNC_OFFT) | tbl_idx;
+	reg_write(reg, value);
+	printf("write reg: %x, value: %x\n", reg, value);
+
+	while (1) { // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+}
+
+void acl_rate_table_add(int argc, char *argv[])
+{
+	unsigned int vawd1, vawd2;
+	unsigned char tbl_idx;
+
+	tbl_idx = atoi(argv[3]);
+	vawd1 = strtoul(argv[4], (char **)NULL, 16);
+	vawd2 = strtoul(argv[5], (char **)NULL, 16);
+
+	write_rate_table(tbl_idx, vawd1, vawd2);
+}
+
+void write_trTCM_table(unsigned char tbl_idx, unsigned int vawd1, unsigned int vawd2)
+{
+	unsigned int value, reg;
+	unsigned int max_index = 32;
+
+	printf("trTCM_tbl_idx:%d\n", tbl_idx);
+
+	if (tbl_idx >= max_index) {
+		printf(HELP_ACL_TRTCM_TBL_ADD);
+		return;
+	}
+
+	reg = REG_VTCR_ADDR;
+	while (1) { 	// wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+
+	reg_write(REG_VAWD1_ADDR, vawd1);
+	printf("write reg: %x, value: %x\n", REG_VAWD1_ADDR, vawd1);
+	reg_write(REG_VAWD2_ADDR, vawd2);
+	printf("write reg: %x, value: %x\n", REG_VAWD2_ADDR, vawd2);
+	reg = REG_VTCR_ADDR;
+	value = REG_VTCR_BUSY_MASK | (0x07 << REG_VTCR_FUNC_OFFT) | tbl_idx;
+	reg_write(reg, value);
+	printf("write reg: %x, value: %x\n", reg, value);
+
+	while (1) { // wait until not busy
+		reg_read(reg, &value);
+		if ((value & REG_VTCR_BUSY_MASK) == 0)
+			break;
+	}
+}
+
+int acl_parameters_pre_del(int len1, int len2, int argc, char *argv[], int *port)
+{
+	int i;
+
+	*port = 0;
+	if (argc < len1) {
+		printf("insufficient arguments!\n");
+		return -1;
+	}
+
+	if (len2 == 12)
+	{
+		if (!argv[4] || strlen(argv[4]) != len2) {
+			printf("The [%s] format error, should be of length %d\n",argv[4], len2);
+			return -1;
+		}
+	}
+
+	if (!argv[5] || strlen(argv[5]) != 8) {
+		printf("portsmap format error, should be of length 7\n");
+		return -1;
+	}
+
+	for (i = 0; i < 7; i++) {
+		if (argv[5][i] != '0' && argv[5][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return -1;
+		}
+		*port += (argv[5][i] - '0') * (1 << i);
+	}
+	return 0;
+}
+
+void acl_compare_pattern(int ports, int comparion, int base, int word, unsigned char table_index)
+{
+	unsigned int value;
+
+	comparion |= 0xffff0000; //compare mask
+
+	value = ports << 8; //w_port_map
+	value |= 0x1 << 19; //enable
+	value |= base << 16; //mac header
+	value |= word << 1;  //word offset
+
+	write_acl_table(table_index, comparion, value);
+}
+
+void acl_mac_add(int argc, char *argv[])
+{
+	unsigned int value;
+	int ports;
+	char tmpstr[5];
+	int ret;
+
+	ret = acl_parameters_pre_del(6, 12, argc, argv, &ports);
+	if (ret < 0)
+		return;
+	//set pattern
+	strncpy(tmpstr, argv[4], 4);
+	tmpstr[4] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	acl_compare_pattern(ports, value, 0x0, 0, 0);
+
+	strncpy(tmpstr, argv[4] + 4, 4);
+	tmpstr[4] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	acl_compare_pattern(ports, value, 0x0, 1, 1);
+
+	strncpy(tmpstr, argv[4] + 8, 4);
+	tmpstr[4] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	acl_compare_pattern(ports, value, 0x0, 2, 2);
+
+	//set mask
+	write_acl_mask_table(0,0x7,0);
+
+	//set action
+	value = 0x7;      //drop
+	value |= 1 << 28; //acl intterupt enable
+	value |= 1 << 27; //acl hit count
+	value |= 2 << 24; //acl hit count group index (0~3)
+	write_acl_rule_table(0,value,0);
+}
+
+void acl_dip_meter(int argc, char *argv[])
+{
+	unsigned int value, ip_value, meter;
+	int ports;
+	int ret;
+
+	ip_value = 0;
+	ret = acl_parameters_pre_del(7, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+
+	str_to_ip(&ip_value, argv[4]);
+	//set pattern
+	value = (ip_value >> 16);
+	acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+	//set pattern
+	value = (ip_value & 0xffff);
+	acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+	//set mask
+	write_acl_mask_table(0,0x3,0);
+
+	//set action
+	meter = strtoul(argv[6], NULL, 0);
+	if (((chip_name == 0x7530) && (meter > 1000000)) ||
+		((chip_name == 0x7531) && (meter > 2500000))) {
+		printf("\n**Illegal meter input, and 7530: 0~1000000Kpbs, 7531: 0~2500000Kpbs**\n");
+		return;
+	}
+	if (((chip_name == 0x7531) && (meter > 1000000))) {
+		reg_read(0xc,&value);
+		value |= 0x1 << 30;
+		reg_write(0xC,value);
+		printf("AGC: 0x%x\n",value);
+		value = meter / 1000; //uint is 1Mbps
+	} else {
+		reg_read(0xc,&value);
+		value &= ~(0x1 << 30);
+		reg_write(0xC,value);
+		printf("AGC: 0x%x\n",value);
+		value = meter >> 6; //uint is 64Kbps
+	}
+	value |= 0x1 << 15; //enable rate control
+	printf("Acl rate control:0x%x\n",value);
+	write_rate_table(0, value, 0);
+}
+
+void acl_dip_trtcm(int argc, char *argv[])
+{
+	unsigned int value, value2, ip_value;
+	unsigned int CIR, CBS, PIR, PBS;
+	int ports;
+	int ret;
+
+	ip_value = 0;
+	ret = acl_parameters_pre_del(10, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+
+	str_to_ip(&ip_value, argv[4]);
+	//set pattern
+	value = (ip_value >> 16);
+	acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+	//set pattern
+	value = (ip_value & 0xffff);
+	acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+	//set CBS PBS
+	CIR = strtoul(argv[6], NULL, 0);
+	CBS = strtoul(argv[7], NULL, 0);
+	PIR = strtoul(argv[8], NULL, 0);
+	PBS = strtoul(argv[9], NULL, 0);
+
+	if (CIR > 65535*64 || CBS > 65535 || PIR > 65535*64  || PBS > 65535) {
+		printf("\n**Illegal input parameters**\n");
+		return;
+	}
+
+	value = CBS << 16; //bit16~31
+	value |= PBS;      //bit0~15
+			   //value |= 1;//valid
+	CIR = CIR >> 6;
+	PIR = PIR >> 6;
+
+	value2 = CIR << 16; //bit16~31
+	value2 |= PIR;      //bit0~15
+	write_trTCM_table(0,value,value2);
+
+	//set pattern
+	write_acl_mask_table(0,0x3,0);
+
+	//set action
+	value = 0x1 << (11 + 1); //TrTCM green  meter#0 Low drop
+	value |= 0x2 << (8 + 1); //TrTCM yellow  meter#0 Med drop
+	value |= 0x3 << (5 + 1); //TrTCM red  meter#0    Hig drop
+	value |= 0x1 << 0;       //TrTCM drop pcd select
+	write_acl_rule_table(0,0,value);
+}
+
+void acl_ethertype(int argc, char *argv[])
+{
+	unsigned int value, ethertype;
+	int ports;
+	int ret;
+
+	ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+	printf("ports:0x%x\n",ports);
+	ethertype = strtoul(argv[4], NULL, 16);
+	//set pattern
+	value = ethertype;
+	acl_compare_pattern(ports, value, 0x0, 0x6, 0);
+
+	//set pattern
+	write_acl_mask_table(0,0x1,0);
+
+	//set action(drop)
+	value = 0x7;      //default. Nodrop
+	value |= 1 << 28; //acl intterupt enable
+	value |= 1 << 27; //acl hit count
+
+	write_acl_rule_table(0,value,0);
+}
+
+void acl_dip_modify(int argc, char *argv[])
+{
+	unsigned int value, ip_value;
+	int ports;
+	int priority;
+	int ret;
+
+	ip_value = 0;
+	priority = strtoul(argv[6], NULL, 16);
+	if (priority < 0 || priority > 7) {
+		printf("\n**Illegal priority value!**\n");
+		return;
+	}
+
+	ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+
+	str_to_ip(&ip_value, argv[4]);
+	//set pattern
+	value = (ip_value >> 16);
+	acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+	//set pattern
+	value = (ip_value & 0xffff);
+	acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+	//set pattern
+	write_acl_mask_table(0,0x3,0);
+
+	//set action
+	value = 0x0;      //default. Nodrop
+	value |= 1 << 28; //acl intterupt enable
+	value |= 1 << 27; //acl hit count
+	value |= priority << 4;  //acl UP
+	write_acl_rule_table(0,value,0);
+}
+
+void acl_dip_pppoe(int argc, char *argv[])
+{
+	unsigned int value, ip_value;
+	int ports;
+	int ret;
+
+	ip_value = 0;
+	ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+
+	str_to_ip(&ip_value, argv[4]);
+	//set pattern
+	value = (ip_value >> 16);
+	acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+	//set pattern
+	value = (ip_value & 0xffff);
+	acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+	//set pattern
+	write_acl_mask_table(0,0x3,0);
+
+	//set action
+	value = 0x0;      //default. Nodrop
+	value |= 1 << 28; //acl intterupt enable
+	value |= 1 << 27; //acl hit count
+	value |= 1 << 20; //pppoe header remove
+	value |= 1 << 21; //SA MAC SWAP
+	value |= 1 << 22; //DA MAC SWAP
+	write_acl_rule_table(0,value,7);
+}
+
+void acl_dip_add(int argc, char *argv[])
+{
+	unsigned int value, ip_value;
+	int ports;
+	int ret;
+
+	ip_value = 0;
+	ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+
+	str_to_ip(&ip_value, argv[4]);
+	//set pattern
+	value = (ip_value >> 16);
+	acl_compare_pattern(ports, value, 0x2, 0x8, 0);
+
+	//set pattern
+	value = (ip_value & 0xffff);
+	acl_compare_pattern(ports, value, 0x2, 0x9, 1);
+
+	//set pattern
+	write_acl_mask_table(0,0x3,0);
+
+	//set action
+	//value = 0x0; //default
+	value = 0x7;      //drop
+	value |= 1 << 28; //acl intterupt enable
+	value |= 1 << 27; //acl hit count
+	value |= 2 << 24; //acl hit count group index (0~3)
+	write_acl_rule_table(0,value,0);
+}
+
+void acl_l4_add(int argc, char *argv[])
+{
+	unsigned int value;
+	int ports;
+	int ret;
+
+	ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+
+	//set pattern
+	value = strtoul(argv[4], NULL, 16);
+	acl_compare_pattern(ports, value, 0x5, 0x0, 0);
+
+	//set rue mask
+	write_acl_mask_table(0,0x1,0);
+	//set action
+	value = 0x7; //drop
+		     //value |= 1;//valid
+	write_acl_rule_table(0,value,0);
+}
+
+void acl_sp_add(int argc, char *argv[])
+{
+	unsigned int value;
+	int ports;
+	int ret;
+
+	ret = acl_parameters_pre_del(6, -1, argc, argv, &ports);
+	if (ret < 0)
+		return;
+	//set pattern
+	value = strtoul(argv[4], NULL, 0);
+	acl_compare_pattern(ports, value, 0x4, 0x0, 0);
+
+	//set rue mask
+	write_acl_mask_table(0,0x1,0);
+
+	//set action
+	value = 0x7; //drop
+		     //value |= 1;//valid
+	write_acl_rule_table(0,value,0);
+}
+
+void acl_port_enable(int argc, char *argv[])
+{
+	unsigned int value, reg;
+	unsigned char acl_port, acl_en;
+
+	acl_port = atoi(argv[3]);
+	acl_en = atoi(argv[4]);
+
+	printf("acl_port:%d, acl_en:%d\n", acl_port, acl_en);
+
+	/*Check the input parameters is right or not.*/
+	if ((acl_port > SWITCH_MAX_PORT) || (acl_en > 1)) {
+		printf(HELP_ACL_SETPORTEN);
+		return;
+	}
+
+	reg = REG_PCR_P0_ADDR + (0x100 * acl_port); // 0x2004[10]
+	reg_read(reg, &value);
+	value &= (~REG_PORT_ACL_EN_MASK);
+	value |= (acl_en << REG_PORT_ACL_EN_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+}
+
+static void dip_dump_internal(int type)
+{
+	unsigned int i, j, value, mac, mac2, value2;
+	char tmpstr[16];
+	int table_size = 0;
+	int hit_value1 = 0;
+	int hit_value2 = 0;
+
+	if(type == GENERAL_TABLE) {
+		table_size = 0x800;
+		reg_write(REG_ATC_ADDR, 0x8104); //dip search command
+		} else {
+		table_size = 0x40;
+		reg_write(REG_ATC_ADDR, 0x811c); //dip search command
+	}
+	printf("hash   port(0:6)   rsp_cnt  flag  timer    dip-address       ATRD\n");
+	for (i = 0; i < table_size; i++) {
+		while (1)
+		{
+			reg_read(REG_ATC_ADDR, &value);
+			if(type == GENERAL_TABLE) {
+				hit_value1 = value & (0x1 << 13);
+				hit_value2 = 1;
+			}else {
+				hit_value1 = value & (0x1 << 13);
+				hit_value2 = value & (0x1 << 28);
+			}
+
+			if (hit_value1 && hit_value2 ) { //search_rdy
+				reg_read(REG_ATRD_ADDR, &value2);
+				//printf("REG_ATRD_ADDR=0x%x\n\r",value2);
+
+				printf("%03x:   ", (value >> 16) & 0xfff); //hash_addr_lu
+				j = (value2 >> 4) & 0xff;		   //r_port_map
+				printf("%c", (j & 0x01) ? '1' : '-');
+				printf("%c", (j & 0x02) ? '1' : '-');
+				printf("%c", (j & 0x04) ? '1' : '-');
+				printf("%c ", (j & 0x08) ? '1' : '-');
+				printf("%c", (j & 0x10) ? '1' : '-');
+				printf("%c", (j & 0x20) ? '1' : '-');
+				printf("%c", (j & 0x40) ? '1' : '-');
+
+				reg_read(REG_TSRA2_ADDR, &mac2);
+
+				printf("     0x%4x", (mac2 & 0xffff));    //RESP_CNT
+				printf("  0x%2x", ((mac2 >> 16) & 0xff)); //RESP_FLAG
+				printf("  %3d", ((mac2 >> 24) & 0xff));   //RESP_TIMER
+									  //printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+				reg_read(REG_TSRA1_ADDR, &mac);
+				ip_to_str(tmpstr, mac);
+				printf("     %s", tmpstr);
+				printf("  0x%8x\n", value2); //ATRD
+							     //printf("%04x", ((mac2 >> 16) & 0xffff));
+							     //printf("     %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
+				if (value & 0x4000) {
+					printf("end of table %d\n", i);
+					return;
+				}
+				break;
+			}
+			else if (value & 0x4000) { //at_table_end
+				printf("found the last entry %d (not ready)\n", i);
+				return;
+			}
+			usleep(5000);
+		}
+
+		if(type == GENERAL_TABLE)
+			reg_write(REG_ATC_ADDR, 0x8105); //search for next dip address
+		else
+			reg_write(REG_ATC_ADDR, 0x811d); //search for next dip address
+		usleep(5000);
+	}
+}
+
+void dip_dump(void)
+{
+	dip_dump_internal(GENERAL_TABLE);
+
+}
+
+void dip_add(int argc, char *argv[])
+{
+	unsigned int value = 0;
+	unsigned int i, j;
+
+	value = 0;
+
+	str_to_ip(&value, argv[3]);
+
+	reg_write(REG_ATA1_ADDR, value);
+	printf("REG_ATA1_ADDR is 0x%x\n\r", value);
+
+#if 0
+	reg_write(REG_ATA2_ADDR, value);
+	printf("REG_ATA2_ADDR is 0x%x\n\r", value);
+#endif
+	if (!argv[4] || strlen(argv[4]) != 8) {
+		printf("portmap format error, should be of length 7\n");
+		return;
+	}
+	j = 0;
+	for (i = 0; i < 7; i++) {
+		if (argv[4][i] != '0' && argv[4][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return;
+		}
+		j += (argv[4][i] - '0') * (1 << i);
+	}
+	value = j << 4;      //w_port_map
+	value |= (0x3 << 2); //static
+
+	reg_write(REG_ATWD_ADDR, value);
+
+	usleep(5000);
+	reg_read(REG_ATWD_ADDR, &value);
+	printf("REG_ATWD_ADDR is 0x%x\n\r", value);
+
+	value = 0x8011; //single w_dip_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	usleep(1000);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void dip_del(int argc, char *argv[])
+{
+	unsigned int i, value;
+
+	value = 0;
+	str_to_ip(&value, argv[3]);
+
+	reg_write(REG_ATA1_ADDR, value);
+
+	value = 0;
+	reg_write(REG_ATA2_ADDR, value);
+
+	value = 0; //STATUS=0, delete dip
+	reg_write(REG_ATWD_ADDR, value);
+
+	value = 0x8011; //w_dip_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			if (argv[1] != NULL)
+				printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void dip_clear(void)
+{
+
+	unsigned int value;
+
+	reg_write(REG_ATC_ADDR, 0x8102); //clear all dip
+	usleep(5000);
+	reg_read(REG_ATC_ADDR, &value);
+	printf("REG_ATC_ADDR is 0x%x\n\r", value);
+}
+
+static void sip_dump_internal(int type)
+{
+	unsigned int i, j, value, mac, mac2, value2;
+	int table_size = 0;
+	int hit_value1 = 0;
+	int hit_value2 = 0;
+	char tmpstr[16];
+
+	if (type == GENERAL_TABLE) {
+		table_size = 0x800;
+		reg_write(REG_ATC_ADDR, 0x8204); //sip search command
+		}else {
+		table_size = 0x40;
+		reg_write(REG_ATC_ADDR, 0x822c); //sip search command
+	}
+	printf("hash  port(0:6)   dip-address    sip-address      ATRD\n");
+	for (i = 0; i < table_size; i++) {
+		while (1)
+		{
+			reg_read(REG_ATC_ADDR, &value);
+			if(type == GENERAL_TABLE) {
+				hit_value1 = value & (0x1 << 13);
+				hit_value2 = 1;
+			} else {
+				hit_value1 = value & (0x1 << 13);
+				hit_value2 = value & (0x1 << 28);
+			}
+
+			if (hit_value1 && hit_value2) { //search_rdy
+				reg_read(REG_ATRD_ADDR, &value2);
+				//printf("REG_ATRD_ADDR=0x%x\n\r",value2);
+
+				printf("%03x:  ", (value >> 16) & 0xfff); //hash_addr_lu
+				j = (value2 >> 4) & 0xff;		  //r_port_map
+				printf("%c", (j & 0x01) ? '1' : '-');
+				printf("%c", (j & 0x02) ? '1' : '-');
+				printf("%c", (j & 0x04) ? '1' : '-');
+				printf("%c", (j & 0x08) ? '1' : '-');
+				printf(" %c", (j & 0x10) ? '1' : '-');
+				printf("%c", (j & 0x20) ? '1' : '-');
+				printf("%c", (j & 0x40) ? '1' : '-');
+
+				reg_read(REG_TSRA2_ADDR, &mac2);
+
+				ip_to_str(tmpstr, mac2);
+				printf("   %s", tmpstr);
+
+				//printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+				reg_read(REG_TSRA1_ADDR, &mac);
+				ip_to_str(tmpstr, mac);
+				printf("    %s", tmpstr);
+				printf("      0x%x\n", value2);
+				//printf("%04x", ((mac2 >> 16) & 0xffff));
+				//printf("     %c\n", (((value2 >> 20) & 0x03)== 0x03)? 'y':'-');
+				if (value & 0x4000) {
+					printf("end of table %d\n", i);
+					return;
+				}
+				break;
+			} else if (value & 0x4000) { //at_table_end
+				printf("found the last entry %d (not ready)\n", i);
+				return;
+			}
+			usleep(5000);
+		}
+
+	if(type == GENERAL_TABLE)
+		reg_write(REG_ATC_ADDR, 0x8205); //search for next sip address
+	else
+		reg_write(REG_ATC_ADDR, 0x822d); //search for next sip address
+	usleep(5000);
+	}
+}
+
+void sip_dump(void)
+{
+
+	sip_dump_internal(GENERAL_TABLE);
+
+}
+
+
+void sip_add(int argc, char *argv[])
+{
+	unsigned int i, j, value;
+
+	value = 0;
+	str_to_ip(&value, argv[3]); //SIP
+
+	reg_write(REG_ATA2_ADDR, value);
+	printf("REG_ATA2_ADDR is 0x%x\n\r", value);
+
+	value = 0;
+
+	str_to_ip(&value, argv[4]); //DIP
+	reg_write(REG_ATA1_ADDR, value);
+	printf("REG_ATA1_ADDR is 0x%x\n\r", value);
+
+	if (!argv[5] || strlen(argv[5]) != 8) {
+		printf("portmap format error, should be of length 7\n");
+		return;
+	}
+	j = 0;
+	for (i = 0; i < 7; i++) {
+		if (argv[5][i] != '0' && argv[5][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return;
+		}
+		j += (argv[5][i] - '0') * (1 << i);
+	}
+	value = j << 4;      //w_port_map
+	value |= (0x3 << 2); //static
+
+	reg_write(REG_ATWD_ADDR, value);
+
+	usleep(5000);
+	reg_read(REG_ATWD_ADDR, &value);
+	printf("REG_ATWD_ADDR is 0x%x\n\r", value);
+
+	value = 0x8021; //single w_sip_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	usleep(1000);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void sip_del(int argc, char *argv[])
+{
+	unsigned int i, value;
+
+	value = 0;
+	str_to_ip(&value, argv[3]);
+
+	reg_write(REG_ATA2_ADDR, value); //SIP
+
+	str_to_ip(&value, argv[4]);
+	reg_write(REG_ATA1_ADDR, value); //DIP
+
+	value = 0; //STATUS=0, delete sip
+	reg_write(REG_ATWD_ADDR, value);
+
+	value = 0x8021; //w_sip_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			if (argv[1] != NULL)
+				printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void sip_clear(void)
+{
+	unsigned int value;
+
+	reg_write(REG_ATC_ADDR, 0x8202); //clear all sip
+	usleep(5000);
+	reg_read(REG_ATC_ADDR, &value);
+	printf("REG_ATC_ADDR is 0x%x\n\r", value);
+}
+
+static void table_dump_internal(int type)
+{
+	unsigned int i, j, value, mac, mac2, value2;
+	int table_size = 0;
+	int table_end = 0;
+	int hit_value1 = 0;
+	int hit_value2 = 0;
+
+	if (type == GENERAL_TABLE){
+		table_size = 0x800;
+		table_end = 0x7FF;
+		reg_write(REG_ATC_ADDR, 0x8004);
+	} else {
+		table_size = 0x40;
+		table_end = 0x3F;
+		reg_write(REG_ATC_ADDR, 0x800C);
+	}
+	printf("hash  port(0:6)   fid   vid  age(s)   mac-address     filter my_mac\n");
+	for (i = 0; i < table_size; i++) {
+		while (1)
+		{
+			reg_read(REG_ATC_ADDR, &value);
+			//printf("ATC =  0x%x\n", value);
+			if(type == GENERAL_TABLE) {
+				hit_value1 = value & (0x1 << 13);
+				hit_value2 = 1;
+			} else {
+				hit_value1 = value & (0x1 << 13);
+				hit_value2 = value & (0x1 << 28);
+			}
+
+			if (hit_value1 && hit_value2 && (((value >> 15) & 0x1) == 0)) {
+				printf("%03x:   ", (value >> 16) & 0xfff);
+				reg_read(REG_ATRD_ADDR, &value2);
+				j = (value2 >> 4) & 0xff; //r_port_map
+				printf("%c", (j & 0x01) ? '1' : '-');
+				printf("%c", (j & 0x02) ? '1' : '-');
+				printf("%c", (j & 0x04) ? '1' : '-');
+				printf("%c", (j & 0x08) ? '1' : '-');
+				printf("%c", (j & 0x10) ? '1' : '-');
+				printf("%c", (j & 0x20) ? '1' : '-');
+				printf("%c", (j & 0x40) ? '1' : '-');
+				printf("%c", (j & 0x80) ? '1' : '-');
+
+				reg_read(REG_TSRA2_ADDR, &mac2);
+
+				printf("   %2d", (mac2 >> 12) & 0x7); //FID
+				printf("  %4d", (mac2 & 0xfff));
+				if (((value2 >> 24) & 0xff) == 0xFF)
+					printf("   --- "); //r_age_field:static
+				else
+					printf(" %5d ", (((value2 >> 24) & 0xff)+1)*2); //r_age_field
+				reg_read(REG_TSRA1_ADDR, &mac);
+				printf("  %08x", mac);
+				printf("%04x", ((mac2 >> 16) & 0xffff));
+				printf("     %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
+				printf("     %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
+				if ((value & 0x4000) && (((value >> 16) & 0xfff) == table_end)) {
+					printf("end of table %d\n", i);
+					return;
+				}
+				break;
+			}
+			else if ((value & 0x4000) && (((value >> 15) & 0x1) == 0) && (((value >> 16) & 0xfff) == table_end)) { //at_table_end
+				printf("found the last entry %d (not ready)\n", i);
+				return;
+			}
+			else
+				usleep(5);
+		}
+
+	if(type == GENERAL_TABLE)
+		reg_write(REG_ATC_ADDR, 0x8005);//search for next address
+	else
+		reg_write(REG_ATC_ADDR, 0x800d);//search for next address
+		usleep(5);
+	}
+}
+
+void table_dump(void)
+{
+	table_dump_internal(GENERAL_TABLE);
+
+}
+
+
+void table_add(int argc, char *argv[])
+{
+	unsigned int i, j, value, is_filter, is_mymac;
+	char tmpstr[9];
+
+	is_filter = (argv[1][0] == 'f') ? 1 : 0;
+	is_mymac = (argv[1][0] == 'm') ? 1 : 0;
+	if (!argv[2] || strlen(argv[2]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[2], 8);
+	tmpstr[8] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	reg_write(REG_ATA1_ADDR, value);
+	printf("REG_ATA1_ADDR is 0x%x\n\r", value);
+
+	strncpy(tmpstr, argv[2] + 8, 4);
+	tmpstr[4] = '\0';
+
+	value = strtoul(tmpstr, NULL, 16);
+	value = (value << 16);
+	value |= (1 << 15); //IVL=1
+
+	if (argc > 4) {
+		j = strtoul(argv[4], NULL, 0);
+		if (4095 < j) {
+			printf("wrong vid range, should be within 0~4095\n");
+			return;
+		}
+		value |= j; //vid
+	}
+
+	reg_write(REG_ATA2_ADDR, value);
+	printf("REG_ATA2_ADDR is 0x%x\n\r", value);
+
+	if (!argv[3] || strlen(argv[3]) != 8) {
+		if (is_filter)
+			argv[3] = "11111111";
+		else {
+			printf("portmap format error, should be of length 8\n");
+			return;
+		}
+	}
+	j = 0;
+	for (i = 0; i < 7; i++) {
+		if (argv[3][i] != '0' && argv[3][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return;
+		}
+		j += (argv[3][i] - '0') * (1 << i);
+	}
+	value = j << 4; //w_port_map
+
+	if (argc > 5) {
+		j = strtoul(argv[5], NULL, 0);
+		if (j < 1 || 255 < j) {
+			printf("wrong age range, should be within 1~255\n");
+			return;
+		}
+		value |= (j << 24);  //w_age_field
+		value |= (0x1 << 2); //dynamic
+	} else {
+		value |= (0xff << 24); //w_age_field
+		value |= (0x3 << 2);   //static
+	}
+
+	if (argc > 6) {
+		j = strtoul(argv[6], NULL, 0);
+		if (7 < j) {
+			printf("wrong eg-tag range, should be within 0~7\n");
+			return;
+		}
+		value |= (j << 13); //EG_TAG
+	}
+
+	if (is_filter)
+		value |= (7 << 20); //sa_filter
+
+	if (is_mymac)
+		value |= (1 << 23);
+
+	reg_write(REG_ATWD_ADDR, value);
+
+	usleep(5000);
+	reg_read(REG_ATWD_ADDR, &value);
+	printf("REG_ATWD_ADDR is 0x%x\n\r", value);
+
+	value = 0x8001; //w_mac_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	usleep(1000);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void table_search_mac_vid(int argc, char *argv[])
+{
+	unsigned int i, j, value, mac, mac2, value2;
+	char tmpstr[9];
+
+	if (!argv[3] || strlen(argv[3]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[3], 8);
+	tmpstr[8] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	reg_write(REG_ATA1_ADDR, value);
+	//printf("REG_ATA1_ADDR is 0x%x\n\r",value);
+
+	strncpy(tmpstr, argv[3] + 8, 4);
+	tmpstr[4] = '\0';
+
+	value = strtoul(tmpstr, NULL, 16);
+	value = (value << 16);
+	value |= (1 << 15); //IVL=1
+
+	j = strtoul(argv[5], NULL, 0);
+	if (4095 < j) {
+		printf("wrong vid range, should be within 0~4095\n");
+		return;
+	}
+	value |= j; //vid
+
+	reg_write(REG_ATA2_ADDR, value);
+	//printf("REG_ATA2_ADDR is 0x%x\n\r",value);
+
+	value = 0x8000; //w_mac_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	usleep(1000);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			break;
+		}
+		usleep(1000);
+	}
+	if (i == 20) {
+		printf("search timeout.\n");
+		return;
+	}
+
+	if (value & 0x1000) {
+		printf("search no entry.\n");
+		return;
+	}
+
+	printf("search done.\n");
+	printf("hash  port(0:6)   fid   vid  age   mac-address     filter my_mac\n");
+
+	printf("%03x:   ", (value >> 16) & 0xfff); //hash_addr_lu
+	reg_read(REG_ATRD_ADDR, &value2);
+	j = (value2 >> 4) & 0xff; //r_port_map
+	printf("%c", (j & 0x01) ? '1' : '-');
+	printf("%c", (j & 0x02) ? '1' : '-');
+	printf("%c", (j & 0x04) ? '1' : '-');
+	printf("%c ", (j & 0x08) ? '1' : '-');
+	printf("%c", (j & 0x10) ? '1' : '-');
+	printf("%c", (j & 0x20) ? '1' : '-');
+	printf("%c", (j & 0x40) ? '1' : '-');
+	printf("%c", (j & 0x80) ? '1' : '-');
+
+	reg_read(REG_TSRA2_ADDR, &mac2);
+
+	printf("   %2d", (mac2 >> 12) & 0x7); //FID
+	printf("  %4d", (mac2 & 0xfff));
+	printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+	reg_read(REG_TSRA1_ADDR, &mac);
+	printf("  %08x", mac);
+	printf("%04x", ((mac2 >> 16) & 0xffff));
+	printf("     %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
+	printf("     %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
+}
+
+void table_search_mac_fid(int argc, char *argv[])
+{
+	unsigned int i, j, value, mac, mac2, value2;
+	char tmpstr[9];
+
+	if (!argv[3] || strlen(argv[3]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[3], 8);
+	tmpstr[8] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	reg_write(REG_ATA1_ADDR, value);
+	//printf("REG_ATA1_ADDR is 0x%x\n\r",value);
+
+	strncpy(tmpstr, argv[3] + 8, 4);
+	tmpstr[4] = '\0';
+
+	value = strtoul(tmpstr, NULL, 16);
+	value = (value << 16);
+	value &= ~(1 << 15); //IVL=0
+
+	j = strtoul(argv[5], NULL, 0);
+	if (7 < j) {
+		printf("wrong fid range, should be within 0~7\n");
+		return;
+	}
+	value |= (j << 12); //vid
+
+	reg_write(REG_ATA2_ADDR, value);
+	//printf("REG_ATA2_ADDR is 0x%x\n\r",value);
+
+	value = 0x8000; //w_mac_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	usleep(1000);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			break;
+		}
+		usleep(1000);
+	}
+	if (i == 20) {
+		printf("search timeout.\n");
+		return;
+	}
+
+	if (value & 0x1000) {
+		printf("search no entry.\n");
+		return;
+	}
+
+	printf("search done.\n");
+	printf("hash  port(0:6)   fid   vid  age   mac-address     filter my_mac\n");
+
+	printf("%03x:   ", (value >> 16) & 0xfff); //hash_addr_lu
+	reg_read(REG_ATRD_ADDR, &value2);
+	j = (value2 >> 4) & 0xff; //r_port_map
+	printf("%c", (j & 0x01) ? '1' : '-');
+	printf("%c", (j & 0x02) ? '1' : '-');
+	printf("%c", (j & 0x04) ? '1' : '-');
+	printf("%c ", (j & 0x08) ? '1' : '-');
+	printf("%c", (j & 0x10) ? '1' : '-');
+	printf("%c", (j & 0x20) ? '1' : '-');
+	printf("%c", (j & 0x40) ? '1' : '-');
+	printf("%c", (j & 0x80) ? '1' : '-');
+
+	reg_read(REG_TSRA2_ADDR, &mac2);
+
+	printf("   %2d", (mac2 >> 12) & 0x7); //FID
+	printf("  %4d", (mac2 & 0xfff));
+	printf(" %4d", (value2 >> 24) & 0xff); //r_age_field
+	reg_read(REG_TSRA1_ADDR, &mac);
+	printf("  %08x", mac);
+	printf("%04x", ((mac2 >> 16) & 0xffff));
+	printf("     %c", (((value2 >> 20) & 0x03) == 0x03) ? 'y' : '-');
+	printf("     %c\n", (((value2 >> 23) & 0x01) == 0x01) ? 'y' : '-');
+}
+
+void table_del_fid(int argc, char *argv[])
+{
+	unsigned int i, j, value;
+	char tmpstr[9];
+
+	if (!argv[3] || strlen(argv[3]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[3], 8);
+	tmpstr[8] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	reg_write(REG_ATA1_ADDR, value);
+	strncpy(tmpstr, argv[3] + 8, 4);
+	tmpstr[4] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	value = (value << 16);
+
+	if (argc > 5) {
+		j = strtoul(argv[5], NULL, 0);
+		if (j > 7) {
+			printf("wrong fid range, should be within 0~7\n");
+			return;
+		}
+		value |= (j << 12); //fid
+	}
+
+	reg_write(REG_ATA2_ADDR, value);
+
+	value = 0; //STATUS=0, delete mac
+	reg_write(REG_ATWD_ADDR, value);
+
+	value = 0x8001; //w_mac_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			if (argv[1] != NULL)
+				printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void table_del_vid(int argc, char *argv[])
+{
+	unsigned int i, j, value;
+	char tmpstr[9];
+
+	if (!argv[3] || strlen(argv[3]) != 12) {
+		printf("MAC address format error, should be of length 12\n");
+		return;
+	}
+	strncpy(tmpstr, argv[3], 8);
+	tmpstr[8] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	reg_write(REG_ATA1_ADDR, value);
+
+	strncpy(tmpstr, argv[3] + 8, 4);
+	tmpstr[4] = '\0';
+	value = strtoul(tmpstr, NULL, 16);
+	value = (value << 16);
+
+	j = strtoul(argv[5], NULL, 0);
+	if (j > 4095) {
+		printf("wrong fid range, should be within 0~4095\n");
+		return;
+	}
+	value |= j; //vid
+	value |= 1 << 15;
+	reg_write(REG_ATA2_ADDR, value);
+
+	value = 0; //STATUS=0, delete mac
+	reg_write(REG_ATWD_ADDR, value);
+
+	value = 0x8001; //w_mac_cmd
+	reg_write(REG_ATC_ADDR, value);
+
+	for (i = 0; i < 20; i++) {
+		reg_read(REG_ATC_ADDR, &value);
+		if ((value & 0x8000) == 0) { //mac address busy
+			if (argv[1] != NULL)
+				printf("done.\n");
+			return;
+		}
+		usleep(1000);
+	}
+	if (i == 20)
+		printf("timeout.\n");
+}
+
+void table_clear(void)
+{
+	unsigned int value;
+	reg_write(REG_ATC_ADDR, 0x8002);
+	usleep(5000);
+	reg_read(REG_ATC_ADDR, &value);
+
+	printf("REG_ATC_ADDR is 0x%x\n\r", value);
+}
+
+void set_mirror_to(int argc, char *argv[])
+{
+	unsigned int value;
+	int idx;
+
+	idx = strtoul(argv[3], NULL, 0);
+	if (idx < 0 || MAX_PORT < idx) {
+		printf("wrong port member, should be within 0~%d\n", MAX_PORT);
+		return;
+	}
+	if (chip_name == 0x7530) {
+
+		reg_read(REG_MFC_ADDR, &value);
+		value |= 0x1 << 3;
+		value &= 0xfffffff8;
+		value |= idx << 0;
+
+		reg_write(REG_MFC_ADDR, value);
+	} else {
+
+		reg_read(REG_CFC_ADDR, &value);
+		value &= (~REG_CFC_MIRROR_EN_MASK);
+		value |= (1 << REG_CFC_MIRROR_EN_OFFT);
+		value &= (~REG_CFC_MIRROR_PORT_MASK);
+		value |= (idx << REG_CFC_MIRROR_PORT_OFFT);
+		reg_write(REG_CFC_ADDR, value);
+	}
+}
+
+void set_mirror_from(int argc, char *argv[])
+{
+	unsigned int offset, value;
+	int idx, mirror;
+
+	idx = strtoul(argv[3], NULL, 0);
+	mirror = strtoul(argv[4], NULL, 0);
+
+	if (idx < 0 || MAX_PORT < idx) {
+		printf("wrong port member, should be within 0~%d\n", MAX_PORT);
+		return;
+	}
+
+	if (mirror < 0 || 3 < mirror) {
+		printf("wrong mirror setting, should be within 0~3\n");
+		return;
+	}
+
+	offset = (0x2004 | (idx << 8));
+	reg_read(offset, &value);
+
+	value &= 0xfffffcff;
+	value |= mirror << 8;
+
+	reg_write(offset, value);
+}
+
+void vlan_dump(int argc, char *argv[])
+{
+	unsigned int i, j, value, value2;
+	int eg_tag = 0;
+
+	if (argc == 4) {
+		if (!strncmp(argv[3], "egtag", 6))
+			eg_tag = 1;
+	}
+
+	if (eg_tag)
+		printf("  vid  fid  portmap    s-tag\teg_tag(0:untagged 2:tagged)\n");
+	else
+		printf("  vid  fid  portmap    s-tag\n");
+
+	for (i = 1; i < 4095; i++) {
+		value = (0x80000000 + i); //r_vid_cmd
+		reg_write(REG_VTCR_ADDR, value);
+
+		for (j = 0; j < 20; j++) {
+			reg_read(REG_VTCR_ADDR, &value);
+			if ((value & 0x80000000) == 0) { //mac address busy
+				break;
+			}
+			usleep(1000);
+		}
+		if (j == 20)
+			printf("timeout.\n");
+
+		reg_read(REG_VAWD1_ADDR, &value);
+		reg_read(REG_VAWD2_ADDR, &value2);
+		//printf("REG_VAWD1_ADDR value%d is 0x%x\n\r", i, value);
+		//printf("REG_VAWD2_ADDR value%d is 0x%x\n\r", i, value2);
+
+		if ((value & 0x01) != 0) {
+			printf(" %4d  ", i);
+			printf(" %2d ", ((value & 0xe) >> 1));
+			printf(" %c", (value & 0x00010000) ? '1' : '-');
+			printf("%c", (value & 0x00020000) ? '1' : '-');
+			printf("%c", (value & 0x00040000) ? '1' : '-');
+			printf("%c", (value & 0x00080000) ? '1' : '-');
+			printf("%c", (value & 0x00100000) ? '1' : '-');
+			printf("%c", (value & 0x00200000) ? '1' : '-');
+			printf("%c", (value & 0x00400000) ? '1' : '-');
+			printf("%c", (value & 0x00800000) ? '1' : '-');
+			printf("    %4d", ((value & 0xfff0) >> 4));
+			if (eg_tag) {
+				printf("\t");
+				if ((value & (0x3 << 28)) == (0x3 << 28)) {
+					/* VTAG_EN=1 and EG_CON=1 */
+					printf("CONSISTENT");
+				} else if (value & (0x1 << 28)) {
+					/* VTAG_EN=1 */
+					printf("%d", (value2 & 0x0003) >> 0);
+					printf("%d", (value2 & 0x000c) >> 2);
+					printf("%d", (value2 & 0x0030) >> 4);
+					printf("%d", (value2 & 0x00c0) >> 6);
+					printf("%d", (value2 & 0x0300) >> 8);
+					printf("%d", (value2 & 0x0c00) >> 10);
+					printf("%d", (value2 & 0x3000) >> 12);
+					printf("%d", (value2 & 0xc000) >> 14);
+				} else {
+					/* VTAG_EN=0 */
+					printf("DISABLED");
+				}
+			}
+			printf("\n");
+		} else {
+			/*print 16 vid for reference information*/
+			if (i <= 16) {
+				printf(" %4d  ", i);
+				printf(" %2d ", ((value & 0xe) >> 1));
+				printf(" invalid\n");
+			}
+		}
+	}
+}
+
+
+static long timespec_diff_us(struct timespec start, struct timespec end)
+{
+	struct timespec temp;
+	unsigned long duration = 0;
+
+	if ((end.tv_nsec - start.tv_nsec) < 0) {
+		temp.tv_sec = end.tv_sec - start.tv_sec - 1;
+		temp.tv_nsec = 1000000000 + end.tv_nsec - start.tv_nsec;
+	} else {
+		temp.tv_sec = end.tv_sec - start.tv_sec;
+		temp.tv_nsec = end.tv_nsec - start.tv_nsec;
+	}
+	/* calculate second part*/
+	duration += temp.tv_sec * 1000000;
+	/* calculate ns part*/
+	duration += temp.tv_nsec >> 10;
+
+	return duration;
+}
+
+
+void vlan_clear(int argc, char *argv[])
+{
+	unsigned int value;
+	int vid;
+	unsigned long duration_us = 0;
+	struct timespec start, end;
+
+	for (vid = 0; vid < 4096; vid++) {
+		clock_gettime(CLOCK_REALTIME, &start);
+		value = 0; //invalid
+		reg_write(REG_VAWD1_ADDR, value);
+
+		value = (0x80001000 + vid); //w_vid_cmd
+		reg_write(REG_VTCR_ADDR, value);
+		while (duration_us <= 1000) {
+			reg_read(REG_VTCR_ADDR, &value);
+			if ((value & 0x80000000) == 0) { //table busy
+				break;
+			}
+			clock_gettime(CLOCK_REALTIME, &end);
+			duration_us = timespec_diff_us(start, end);
+		}
+		if (duration_us > 1000)
+			printf("config vlan timeout: %ld.\n", duration_us);
+	}
+}
+
+void vlan_set(int argc, char *argv[])
+{
+	unsigned int vlan_mem = 0;
+	unsigned int value = 0;
+	unsigned int value2 = 0;
+	int i, vid, fid;
+	int stag = 0;
+	unsigned long eg_con = 0;
+	unsigned int eg_tag = 0;
+
+	if (argc < 5) {
+		printf("insufficient arguments!\n");
+		return;
+	}
+
+	fid = strtoul(argv[3], NULL, 0);
+	if (fid < 0 || fid > 7) {
+		printf("wrong filtering db id range, should be within 0~7\n");
+		return;
+	}
+	value |= (fid << 1);
+
+	vid = strtoul(argv[4], NULL, 0);
+	if (vid < 0 || 0xfff < vid) {
+		printf("wrong vlan id range, should be within 0~4095\n");
+		return;
+	}
+
+	if (strlen(argv[5]) != 8) {
+		printf("portmap format error, should be of length 7\n");
+		return;
+	}
+
+	vlan_mem = 0;
+	for (i = 0; i < 8; i++) {
+		if (argv[5][i] != '0' && argv[5][i] != '1') {
+			printf("portmap format error, should be of combination of 0 or 1\n");
+			return;
+		}
+		vlan_mem += (argv[5][i] - '0') * (1 << i);
+	}
+
+	/* VLAN stag */
+	if (argc > 6) {
+		stag = strtoul(argv[6], NULL, 16);
+		if (stag < 0 || 0xfff < stag) {
+			printf("wrong stag id range, should be within 0~4095\n");
+			return;
+		}
+		//printf("STAG is 0x%x\n", stag);
+	}
+
+	/* set vlan member */
+	value |= (vlan_mem << 16);
+	value |= (1 << 30);		//IVL=1
+	value |= ((stag & 0xfff) << 4); //stag
+	value |= 1;			//valid
+
+	if (argc > 7) {
+		eg_con = strtoul(argv[7], NULL, 2);
+		eg_con = !!eg_con;
+		value |= (eg_con << 29); //eg_con
+		value |= (1 << 28);      //eg tag control enable
+	}
+
+	if (argc > 8 && !eg_con) {
+		if (strlen(argv[8]) != 8) {
+			printf("egtag portmap format error, should be of length 7\n");
+			return;
+		}
+
+		for (i = 0; i < 8; i++) {
+			if (argv[8][i] < '0' || argv[8][i] > '3') {
+				printf("egtag portmap format error, should be of combination of 0 or 3\n");
+				return;
+			}
+			//eg_tag += (argv[8][i] - '0') * (1 << i * 2);
+			eg_tag |= (argv[8][i] - '0') << (i * 2);
+		}
+
+		value |= (1 << 28);    //eg tag control enable
+		value2 &= ~(0xffff);
+		value2 |= eg_tag;
+	}
+	reg_write(REG_VAWD1_ADDR, value);
+	reg_write(REG_VAWD2_ADDR, value2);
+	//printf("VAWD1=0x%08x VAWD2=0x%08x ", value, value2);
+
+	value = (0x80001000 + vid); //w_vid_cmd
+	reg_write(REG_VTCR_ADDR, value);
+	//printf("VTCR=0x%08x\n", value);
+
+	for (i = 0; i < 300; i++) {
+		usleep(1000);
+		reg_read(REG_VTCR_ADDR, &value);
+		if ((value & 0x80000000) == 0) //table busy
+			break;
+	}
+
+	if (i == 300)
+		printf("config vlan timeout.\n");
+}
+
+void igmp_on(int argc, char *argv[])
+{
+	unsigned int leaky_en = 0;
+	unsigned int wan_num = 4;
+	unsigned int port, offset, value;
+	char cmd[80];
+	int ret;
+
+	if (argc > 3)
+		leaky_en = strtoul(argv[3], NULL, 10);
+	if (argc > 4)
+		wan_num = strtoul(argv[4], NULL, 10);
+
+	if (leaky_en == 1) {
+		if (wan_num == 4) {
+			/* reg_write(0x2410, 0x810000c8); */
+			reg_read(0x2410, &value);
+			reg_write(0x2410, value | (1 << 3));
+			/* reg_write(0x2010, 0x810000c0); */
+			reg_read(0x2010, &value);
+			reg_write(0x2010, value & (~(1 << 3)));
+			reg_write(REG_ISC_ADDR, 0x10027d10);
+		} else {
+			/* reg_write(0x2010, 0x810000c8); */
+			reg_read(0x2010, &value);
+			reg_write(0x2010, value | (1 << 3));
+			/* reg_write(0x2410, 0x810000c0); */
+			reg_read(0x2410, &value);
+			reg_write(0x2410, value & (~(1 << 3)));
+			reg_write(REG_ISC_ADDR, 0x01027d01);
+		}
+	}
+	else
+		reg_write(REG_ISC_ADDR, 0x10027d60);
+
+	reg_write(0x1c, 0x08100810);
+	reg_write(0x2008, 0xb3ff);
+	reg_write(0x2108, 0xb3ff);
+	reg_write(0x2208, 0xb3ff);
+	reg_write(0x2308, 0xb3ff);
+	reg_write(0x2408, 0xb3ff);
+	reg_write(0x2608, 0xb3ff);
+	/* Enable Port ACL
+	* reg_write(0x2P04, 0xff0403);
+	*/
+	for (port = 0; port <= 6; port++) {
+		offset = 0x2004 + port * 0x100;
+		reg_read(offset, &value);
+		reg_write(offset, value | (1 << 10));
+	}
+
+	/*IGMP query only p4 -> p5*/
+	reg_write(0x94, 0x00ff0002);
+	if (wan_num == 4)
+		reg_write(0x98, 0x000a1008);
+	else
+		reg_write(0x98, 0x000a0108);
+	reg_write(0x90, 0x80005000);
+	reg_write(0x94, 0xff001100);
+	if (wan_num == 4)
+		reg_write(0x98, 0x000B1000);
+	else
+		reg_write(0x98, 0x000B0100);
+	reg_write(0x90, 0x80005001);
+	reg_write(0x94, 0x3);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x80009000);
+	reg_write(0x94, 0x1a002080);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x8000b000);
+
+	/*IGMP p5 -> p4*/
+	reg_write(0x94, 0x00ff0002);
+	reg_write(0x98, 0x000a2008);
+	reg_write(0x90, 0x80005002);
+	reg_write(0x94, 0x4);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x80009001);
+	if (wan_num == 4)
+		reg_write(0x94, 0x1a001080);
+	else
+		reg_write(0x94, 0x1a000180);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x8000b001);
+
+	/*IGMP p0~p3 -> p6*/
+	reg_write(0x94, 0x00ff0002);
+	if (wan_num == 4)
+		reg_write(0x98, 0x000a0f08);
+	else
+		reg_write(0x98, 0x000a1e08);
+	reg_write(0x90, 0x80005003);
+	reg_write(0x94, 0x8);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x80009002);
+	reg_write(0x94, 0x1a004080);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x8000b002);
+
+	/*IGMP query only p6 -> p0~p3*/
+	reg_write(0x94, 0x00ff0002);
+	reg_write(0x98, 0x000a4008);
+	reg_write(0x90, 0x80005004);
+	reg_write(0x94, 0xff001100);
+	reg_write(0x98, 0x000B4000);
+	reg_write(0x90, 0x80005005);
+	reg_write(0x94, 0x30);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x80009003);
+	if (wan_num == 4)
+		reg_write(0x94, 0x1a000f80);
+	else
+		reg_write(0x94, 0x1a001e80);
+	reg_write(0x98, 0x0);
+	reg_write(0x90, 0x8000b003);
+
+	/*Force eth2 to receive all igmp packets*/
+	snprintf(cmd, sizeof(cmd), "echo 2 > /sys/devices/virtual/net/%s/brif/%s/multicast_router", BR_DEVNAME, ETH_DEVNAME);
+	ret = system(cmd);
+	if (ret)
+		printf("Failed to set /sys/devices/virtual/net/%s/brif/%s/multicast_router\n",
+		       BR_DEVNAME, ETH_DEVNAME);
+}
+
+void igmp_disable(int argc, char *argv[])
+{
+	unsigned int reg_offset, value;
+	int port_num;
+
+	if (argc < 4) {
+		printf("insufficient arguments!\n");
+		return;
+	}
+	port_num = strtoul(argv[3], NULL, 0);
+	if (port_num < 0 || 6 < port_num) {
+		printf("wrong port range, should be within 0~6\n");
+		return;
+	}
+
+	//set ISC: IGMP Snooping Control Register (offset: 0x0018)
+	reg_offset = 0x2008;
+	reg_offset |= (port_num << 8);
+	value = 0x8000;
+
+	reg_write(reg_offset, value);
+}
+
+void igmp_enable(int argc, char *argv[])
+{
+	unsigned int reg_offset, value;
+	int port_num;
+
+	if (argc < 4) {
+		printf("insufficient arguments!\n");
+		return;
+	}
+	port_num = strtoul(argv[3], NULL, 0);
+	if (port_num < 0 || 6 < port_num) {
+		printf("wrong port range, should be within 0~6\n");
+		return;
+	}
+
+	//set ISC: IGMP Snooping Control Register (offset: 0x0018)
+	reg_offset = 0x2008;
+	reg_offset |= (port_num << 8);
+	value = 0x9755;
+	reg_write(reg_offset, value);
+}
+
+void igmp_off()
+{
+	unsigned int value;
+	//set ISC: IGMP Snooping Control Register (offset: 0x0018)
+	reg_read(REG_ISC_ADDR, &value);
+	value &= ~(1 << 18); //disable
+	reg_write(REG_ISC_ADDR, value);
+
+	/*restore wan port multicast leaky vlan function: default disabled*/
+	reg_read(0x2010, &value);
+	reg_write(0x2010, value & (~(1 << 3)));
+	reg_read(0x2410, &value);
+	reg_write(0x2410, value & (~(1 << 3)));
+
+	printf("config igmpsnoop off.\n");
+}
+
+void switch_reset(int argc, char *argv[])
+{
+	unsigned int value = 0;
+	/*Software Register Reset  and Software System Reset */
+	reg_write(0x7000, 0x3);
+	reg_read(0x7000, &value);
+	printf("SYS_CTRL(0x7000) register value =0x%x  \n", value);
+	if (chip_name == 0x7531) {
+		reg_write(0x7c0c, 0x11111111);
+		reg_read(0x7c0c, &value);
+		printf("GPIO Mode (0x7c0c) select value =0x%x  \n", value);
+	}
+	printf("Switch Software Reset !!! \n");
+}
+
+int phy_set_fc(int argc, char *argv[])
+{
+	unsigned int port, pause_capable;
+	unsigned int phy_value;
+
+	port = atoi(argv[3]);
+	pause_capable = atoi(argv[4]);
+
+	/*Check the input parameters is right or not.*/
+	if (port > MAX_PORT - 2 || pause_capable > 1) {
+		printf("Illegal parameter (port:0~4, full_duplex_pause_capable:0|1)\n");
+		return -1;
+	}
+	printf("port=%d, full_duplex_pause_capable:%d\n", port, pause_capable);
+	mii_mgr_read(port, 4, &phy_value);
+	printf("read phy_value:0x%x\r\n", phy_value);
+	phy_value &= (~(0x1 << 10));
+	phy_value &= (~(0x1 << 11));
+	if (pause_capable == 1) {
+		phy_value |= (0x1 << 10);
+		phy_value |= (0x1 << 11);
+	}
+	mii_mgr_write(port, 4, phy_value);
+	printf("write phy_value:0x%x\r\n", phy_value);
+	return 0;
+} /*end phy_set_fc*/
+
+int phy_set_an(int argc, char *argv[])
+{
+	unsigned int port, auto_negotiation_en;
+	unsigned int phy_value;
+
+	port = atoi(argv[3]);
+	auto_negotiation_en = atoi(argv[4]);
+
+	/*Check the input parameters is right or not.*/
+	if (port > MAX_PORT - 2 || auto_negotiation_en > 1) {
+		printf("Illegal parameter (port:0~4, auto_negotiation_en:0|1)\n");
+		return -1;
+	}
+	printf("port=%d, auto_negotiation_en:%d\n", port, auto_negotiation_en);
+	mii_mgr_read(port, 0, &phy_value);
+	printf("read phy_value:0x%x\r\n", phy_value);
+	phy_value &= (~(1 << 12));
+	phy_value |= (auto_negotiation_en << 12);
+	mii_mgr_write(port, 0, phy_value);
+	printf("write phy_value:0x%x\r\n", phy_value);
+	return 0;
+} /*end phy_set_an*/
+
+int set_mac_pfc(int argc, char *argv[])
+{
+	unsigned int value;
+	int port, enable = 0;
+
+	port = atoi(argv[3]);
+	enable = atoi(argv[4]);
+	printf("enable: %d\n", enable);
+	if (port < 0 || port > 6 || enable < 0 || enable > 1) {
+		printf("Illegal parameter (port:0~6, enable|diable:0|1) \n");
+		return -1;
+	}
+	if (chip_name == 0x7531) {
+		reg_read(REG_PFC_CTRL_ADDR, &value);
+		value &= ~(1 << port);
+		value |= (enable << port);
+		printf("write reg: %x, value: %x\n", REG_PFC_CTRL_ADDR, value);
+		reg_write(REG_PFC_CTRL_ADDR, value);
+	}
+	else
+		printf("\nCommand not support by this chip.\n");
+	return 0;
+}
+
+int global_set_mac_fc(int argc, char *argv[])
+{
+	unsigned char enable = 0;
+	unsigned int value, reg;
+
+	if (chip_name == 0x7530) {
+		enable = atoi(argv[3]);
+		printf("enable: %d\n", enable);
+
+		/*Check the input parameters is right or not.*/
+		if (enable > 1) {
+			printf(HELP_MACCTL_FC);
+			return -1;
+		}
+		reg_write(0x7000, 0x3);
+		reg = REG_GFCCR0_ADDR;
+		reg_read(REG_GFCCR0_ADDR, &value);
+		value &= (~REG_FC_EN_MASK);
+		value |= (enable << REG_FC_EN_OFFT);
+		printf("write reg: %x, value: %x\n", reg, value);
+		reg_write(REG_GFCCR0_ADDR, value);
+	} else
+		printf("\r\nCommand not support by this chip.\n");
+	return 0;
+} /*end mac_set_fc*/
+
+int qos_sch_select(int argc, char *argv[])
+{
+	unsigned char port, queue;
+	unsigned char type = 0;
+	unsigned int value, reg;
+
+	if (argc < 7)
+		return -1;
+
+	port = atoi(argv[3]);
+	queue = atoi(argv[4]);
+	type = atoi(argv[6]);
+
+	if (port > 6 || queue > 7) {
+		printf("\n Illegal input parameters\n");
+		return -1;
+	}
+
+	if ((type != 0 && type != 1 && type != 2)) {
+		printf(HELP_QOS_TYPE);
+		return -1;
+	}
+
+	printf("\r\nswitch qos type: %d.\n",type);
+
+	if (!strncmp(argv[5], "min", 4)) {
+
+		if (type == 0) {
+			/*min sharper-->round roubin, disable min sharper rate limit*/
+			reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
+			reg_read(reg, &value);
+			value = 0x0;
+			reg_write(reg, value);
+		} else if (type == 1) {
+			/*min sharper-->sp, disable min sharper rate limit*/
+			reg = GSW_MMSCR0_Q(queue) + 0x100 * port;
+			reg_read(reg, &value);
+			value = 0x0;
+			value |= (1 << 31);
+			reg_write(reg, value);
+		} else {
+			printf("min sharper only support: rr or sp\n");
+			return -1;
+		}
+	} else if (!strncmp(argv[5], "max", 4)) {
+		if (type == 1) {
+			/*max sharper-->sp, disable max sharper rate limit*/
+			reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
+			reg_read(reg, &value);
+			value = 0x0;
+			value |= (1 << 31);
+			reg_write(reg, value);
+		} else if (type == 2) {
+			/*max sharper-->wfq, disable max sharper rate limit*/
+			reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
+			reg_read(reg, &value);
+			value = 0x0;
+			reg_write(reg, value);
+		} else {
+			printf("max sharper only support: wfq or sp\n");
+			return -1;
+		}
+	} else {
+		printf("\r\nIllegal sharper:%s\n",argv[5]);
+		return -1;
+	}
+	printf("reg:0x%x--value:0x%x\n",reg,value);
+
+	return 0;
+}
+
+void get_upw(unsigned int *value, unsigned char base)
+{
+	*value &= (~((0x7 << 0) | (0x7 << 4) | (0x7 << 8) | (0x7 << 12) |
+		     (0x7 << 16) | (0x7 << 20)));
+	switch (base)
+	{
+		case 0: /* port-based 0x2x40[18:16] */
+			*value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+				(0x2 << 12) | (0x7 << 16) | (0x2 << 20));
+			break;
+		case 1: /* tagged-based 0x2x40[10:8] */
+			*value |= ((0x2 << 0) | (0x2 << 4) | (0x7 << 8) |
+				(0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+			break;
+		case 2: /* DSCP-based 0x2x40[14:12] */
+			*value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+				(0x7 << 12) | (0x2 << 16) | (0x2 << 20));
+			break;
+		case 3: /* acl-based 0x2x40[2:0] */
+			*value |= ((0x7 << 0) | (0x2 << 4) | (0x2 << 8) |
+				(0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+			break;
+		case 4: /* arl-based 0x2x40[22:20] */
+			*value |= ((0x2 << 0) | (0x2 << 4) | (0x2 << 8) |
+				(0x2 << 12) | (0x2 << 16) | (0x7 << 20));
+			break;
+		case 5: /* stag-based 0x2x40[6:4] */
+			*value |= ((0x2 << 0) | (0x7 << 4) | (0x2 << 8) |
+				(0x2 << 12) | (0x2 << 16) | (0x2 << 20));
+			break;
+		default:
+			break;
+	}
+}
+
+void qos_set_base(int argc, char *argv[])
+{
+	unsigned char base = 0;
+	unsigned char port;
+	unsigned int value;
+
+	if (argc < 5)
+		return;
+
+	port = atoi(argv[3]);
+	base = atoi(argv[4]);
+
+	if (base > 6) {
+		printf(HELP_QOS_BASE);
+		return;
+	}
+
+	if (port > 6) {
+		printf("Illegal port index:%d\n",port);
+		return;
+	}
+
+	printf("\r\nswitch qos base : %d. (port-based:0, tag-based:1,\
+		dscp-based:2, acl-based:3, arl-based:4, stag-based:5)\n",
+	       base);
+	if (chip_name == 0x7530) {
+
+		reg_read(0x44, &value);
+		get_upw(&value, base);
+		reg_write(0x44, value);
+		printf("reg: 0x44, value: 0x%x\n", value);
+
+	} else if (chip_name == 0x7531) {
+
+		reg_read(GSW_UPW(port), &value);
+		get_upw(&value, base);
+		reg_write(GSW_UPW(port), value);
+		printf("reg:0x%x, value: 0x%x\n",GSW_UPW(port),value);
+
+	} else {
+		printf("unknown switch device");
+		return;
+	}
+}
+
+void qos_wfq_set_weight(int argc, char *argv[])
+{
+	int port, weight[8], i;
+	unsigned char queue;
+	unsigned int reg, value;
+
+	port = atoi(argv[3]);
+
+	for (i = 0; i < 8; i++) {
+		weight[i] = atoi(argv[i + 4]);
+	}
+
+	/* MT7530 total 7 port */
+	if (port < 0 || port > 6) {
+		printf(HELP_QOS_PORT_WEIGHT);
+		return;
+	}
+
+	for (i = 0; i < 8; i++) {
+		if (weight[i] < 1 || weight[i] > 16) {
+			printf(HELP_QOS_PORT_WEIGHT);
+			return;
+		}
+	}
+	printf("port: %x, q0: %x, q1: %x, q2: %x, q3: %x, \
+		q4: %x, q5: %x, q6: %x, q7: %x\n",
+	       port, weight[0], weight[1], weight[2], weight[3], weight[4],
+	       weight[5], weight[6], weight[7]);
+
+	for (queue = 0; queue < 8; queue++) {
+		reg = GSW_MMSCR1_Q(queue) + 0x100 * port;
+		reg_read(reg, &value);
+		value &= (~(0xf << 24)); //bit24~27
+		value |= (((weight[queue] - 1) & 0xf) << 24);
+		printf("reg: %x, value: %x\n", reg, value);
+		reg_write(reg, value);
+	}
+}
+
+void qos_set_portpri(int argc, char *argv[])
+{
+	unsigned char port, prio;
+	unsigned int value;
+
+	port = atoi(argv[3]);
+	prio = atoi(argv[4]);
+
+	if (port >= 7 || prio > 7) {
+		printf(HELP_QOS_PORT_PRIO);
+		return;
+	}
+
+	reg_read(GSW_PCR(port), &value);
+	value &= (~(0x7 << 24));
+	value |= (prio << 24);
+	reg_write(GSW_PCR(port), value);
+	printf("write reg: %x, value: %x\n", GSW_PCR(port), value);
+}
+
+void qos_set_dscppri(int argc, char *argv[])
+{
+	unsigned char prio, dscp, pim_n, pim_offset;
+	unsigned int reg, value;
+
+	dscp = atoi(argv[3]);
+	prio = atoi(argv[4]);
+
+	if (dscp > 63 || prio > 7) {
+		printf(HELP_QOS_DSCP_PRIO);
+		return;
+	}
+
+	pim_n = dscp / 10;
+	pim_offset = (dscp - pim_n * 10) * 3;
+	reg = 0x0058 + pim_n * 4;
+	reg_read(reg, &value);
+	value &= (~(0x7 << pim_offset));
+	value |= ((prio & 0x7) << pim_offset);
+	reg_write(reg, value);
+	printf("write reg: %x, value: %x\n", reg, value);
+}
+
+void qos_pri_mapping_queue(int argc, char *argv[])
+{
+	unsigned char prio, queue, pem_n, port;
+	unsigned int reg, value;
+
+	if (argc < 6)
+		return;
+
+	port = atoi(argv[3]);
+	prio = atoi(argv[4]);
+	queue = atoi(argv[5]);
+
+	if (prio > 7 || queue > 7) {
+		printf(HELP_QOS_PRIO_QMAP);
+		return;
+	}
+	if (chip_name == 0x7530) {
+		pem_n = prio / 2;
+		reg = pem_n * 0x4 + 0x48;
+		reg_read(reg, &value);
+		if (prio % 2) {
+			value &= (~(0x7 << 24));
+			value |= ((queue & 0x7) << 24);
+		} else {
+			value &= (~(0x7 << 8));
+			value |= ((queue & 0x7) << 8);
+		}
+		reg_write(reg, value);
+		printf("write reg: %x, value: %x\n", reg, value);
+	} else if (chip_name == 0x7531) {
+		pem_n = prio / 2;
+		reg = GSW_PEM(pem_n) + 0x100 * port;
+		reg_read(reg, &value);
+		if (prio % 2) { // 1 1
+			value &= (~(0x7 << 25));
+			value |= ((queue & 0x7) << 25);
+		} else { // 0 0
+			value &= (~(0x7 << 9));
+			value |= ((queue & 0x7) << 9);
+		}
+		reg_write(reg, value);
+		printf("write reg: %x, value: %x\n", reg, value);
+	}
+	else {
+		printf("unknown switch device");
+		return;
+	}
+}
+
+static int macMT753xVlanSetVid(unsigned char index, unsigned char active,
+			       unsigned short vid, unsigned char portMap, unsigned char tagPortMap,
+			       unsigned char ivl_en, unsigned char fid, unsigned short stag)
+{
+	unsigned int value = 0;
+	unsigned int value2 = 0;
+	unsigned int reg;
+	int i;
+
+	printf("index: %x, active: %x, vid: %x, portMap: %x, \
+		tagPortMap: %x, ivl_en: %x, fid: %x, stag: %x\n",
+	       index, active, vid, portMap, tagPortMap, ivl_en, fid, stag);
+
+	value = (portMap << 16);
+	value |= (stag << 4);
+	value |= (ivl_en << 30);
+	value |= (fid << 1);
+	value |= (active ? 1 : 0);
+
+	// total 7 ports
+	for (i = 0; i < 7; i++) {
+		if (tagPortMap & (1 << i))
+			value2 |= 0x2 << (i * 2);
+	}
+
+	if (value2)
+		value |= (1 << 28); // eg_tag
+
+	reg = 0x98; // VAWD2
+	reg_write(reg, value2);
+
+	reg = 0x94; // VAWD1
+	reg_write(reg, value);
+
+	reg = 0x90; // VTCR
+	value = (0x80001000 + vid);
+	reg_write(reg, value);
+
+	reg = 0x90; // VTCR
+	while (1) {
+		reg_read(reg, &value);
+		if ((value & 0x80000000) == 0) //table busy
+			break;
+	}
+
+	/* switch clear */
+	reg = 0x80;
+	reg_write(reg, 0x8002);
+	usleep(5000);
+	reg_read(reg, &value);
+
+	printf("SetVid: index:%d active:%d vid:%d portMap:%x tagPortMap:%x\r\n",
+	       index, active, vid, portMap, tagPortMap);
+	return 0;
+
+} /*end macMT753xVlanSetVid*/
+/*
+static int macMT753xVlanGetVtbl(unsigned short index)
+{
+	unsigned int reg, value, vawd1, vawd2;
+
+	reg = 0x90; // VTCR
+	value = (0x80000000 + index);
+
+	reg_write(reg, value);
+
+	reg = 0x90; // VTCR
+	while (1) {
+		reg_read(reg, &value);
+		if ((value & 0x80000000) == 0) //table busy
+			break;
+	}
+
+	reg = 0x94; // VAWD1
+	reg_read(reg, &vawd1);
+
+	reg = 0x98; // VAWD2
+	reg_read(reg, &vawd2);
+
+	if (vawd1 & 0x1) {
+		fprintf(stderr, "%d.%s vid:%d fid:%d portMap:0x%x \
+				tagMap:0x%x stag:0x%x ivl_en:0x%x\r\n",
+			index, (vawd1 & 0x1) ? "on" : "off", index, ((vawd1 & 0xe) >> 1),
+			(vawd1 & 0xff0000) >> 16, vawd2, (vawd1 & 0xfff0) >> 0x4, (vawd1 >> 30) & 0x1);
+	}
+	return 0;
+} */ /*end macMT753xVlanGetVtbl*/
+
+static int macMT753xVlanSetPvid(unsigned char port, unsigned short pvid)
+{
+	unsigned int value;
+	unsigned int reg;
+
+	/*Parameters is error*/
+	if (port > 6)
+		return -1;
+
+	reg = 0x2014 + (port * 0x100);
+	reg_read(reg, &value);
+	value &= ~0xfff;
+	value |= pvid;
+	reg_write(reg, value);
+
+	/* switch clear */
+	reg = 0x80;
+	reg_write(reg, 0x8002);
+	usleep(5000);
+	reg_read(reg, &value);
+
+	printf("SetPVID: port:%d pvid:%d\r\n", port, pvid);
+	return 0;
+}
+/*
+static int macMT753xVlanGetPvid(unsigned char port)
+{
+	unsigned int value;
+	unsigned int reg;
+
+	if (port > 6)
+		return -1;
+	reg = 0x2014 + (port * 0x100);
+	reg_read(reg, &value);
+	return (value & 0xfff);
+} */
+/*
+static int macMT753xVlanDisp(void)
+{
+	unsigned int i = 0;
+	unsigned int reg, value;
+
+	reg = 0x2604;
+	reg_read(reg, &value);
+	value &= 0x30000000;
+
+	fprintf(stderr, "VLAN function is %s\n", value ? ETHCMD_ENABLE : ETHCMD_DISABLE);
+	fprintf(stderr, "PVID e0:%02d e1:%02d e2:%02d e3:%02d e4:%02d e5:%02d e6:%02d\n",
+		macMT753xVlanGetPvid(0), macMT753xVlanGetPvid(1), macMT753xVlanGetPvid(2),
+		macMT753xVlanGetPvid(3), macMT753xVlanGetPvid(4), macMT753xVlanGetPvid(5), macMT753xVlanGetPvid(6));
+
+	for (i = 0; i < MAX_VID_VALUE; i++)
+		macMT753xVlanGetVtbl(i);
+
+	return 0;
+}*/ /*end macMT753xVlanDisp*/
+
+void doVlanSetPvid(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned short pvid = 0;
+
+	port = atoi(argv[3]);
+	pvid = atoi(argv[4]);
+	/*Check the input parameters is right or not.*/
+	if ((port >= SWITCH_MAX_PORT) || (pvid > MAX_VID_VALUE)) {
+		printf(HELP_VLAN_PVID);
+		return;
+	}
+
+	macMT753xVlanSetPvid(port, pvid);
+
+	printf("port:%d pvid:%d,vlancap: max_port:%d maxvid:%d\r\n",
+	       port, pvid, SWITCH_MAX_PORT, MAX_VID_VALUE);
+} /*end doVlanSetPvid*/
+
+void doVlanSetVid(int argc, char *argv[])
+{
+	unsigned char index = 0;
+	unsigned char active = 0;
+	unsigned char portMap = 0;
+	unsigned char tagPortMap = 0;
+	unsigned short vid = 0;
+
+	unsigned char ivl_en = 0;
+	unsigned char fid = 0;
+	unsigned short stag = 0;
+
+	index = atoi(argv[3]);
+	active = atoi(argv[4]);
+	vid = atoi(argv[5]);
+
+	/*Check the input parameters is right or not.*/
+	if ((index >= MAX_VLAN_RULE) || (vid >= 4096) || (active > ACTIVED)) {
+		printf(HELP_VLAN_VID);
+		return;
+	}
+
+	/*CPU Port is always the membership*/
+	portMap = atoi(argv[6]);
+	tagPortMap = atoi(argv[7]);
+
+	printf("subcmd parameter argc = %d\r\n", argc);
+	if (argc >= 9) {
+		ivl_en = atoi(argv[8]);
+		if (argc >= 10) {
+			fid = atoi(argv[9]);
+			if (argc >= 11)
+				stag = atoi(argv[10]);
+		}
+	}
+	macMT753xVlanSetVid(index, active, vid, portMap, tagPortMap,
+			    ivl_en, fid, stag);
+	printf("index:%d active:%d vid:%d\r\n", index, active, vid);
+} /*end doVlanSetVid*/
+
+void doVlanSetAccFrm(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned char type = 0;
+	unsigned int value;
+	unsigned int reg;
+
+	port = atoi(argv[3]);
+	type = atoi(argv[4]);
+
+	printf("port: %d, type: %d\n", port, type);
+
+	/*Check the input parameters is right or not.*/
+	if ((port > SWITCH_MAX_PORT) || (type > REG_PVC_ACC_FRM_RELMASK)) {
+		printf(HELP_VLAN_ACC_FRM);
+		return;
+	}
+
+	reg = REG_PVC_P0_ADDR + port * 0x100;
+	reg_read(reg, &value);
+	value &= (~REG_PVC_ACC_FRM_MASK);
+	value |= ((unsigned int)type << REG_PVC_ACC_FRM_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+} /*end doVlanSetAccFrm*/
+
+void doVlanSetPortAttr(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned char attr = 0;
+	unsigned int value;
+	unsigned int reg;
+
+	port = atoi(argv[3]);
+	attr = atoi(argv[4]);
+
+	printf("port: %x, attr: %x\n", port, attr);
+
+	/*Check the input parameters is right or not.*/
+	if (port > SWITCH_MAX_PORT || attr > 3) {
+		printf(HELP_VLAN_PORT_ATTR);
+		return;
+	}
+
+	reg = 0x2010 + port * 0x100;
+	reg_read(reg, &value);
+	value &= (0xffffff3f);
+	value |= (attr << 6);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+}
+
+void doVlanSetPortMode(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned char mode = 0;
+	unsigned int value;
+	unsigned int reg;
+	port = atoi(argv[3]);
+	mode = atoi(argv[4]);
+	printf("port: %x, mode: %x\n", port, mode);
+
+	/*Check the input parameters is right or not.*/
+	if (port > SWITCH_MAX_PORT || mode > 3) {
+		printf(HELP_VLAN_PORT_MODE);
+		return;
+	}
+
+	reg = 0x2004 + port * 0x100;
+	reg_read(reg, &value);
+	value &= (~((1 << 0) | (1 << 1)));
+	value |= (mode & 0x3);
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+}
+
+void doVlanSetEgressTagPCR(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned char eg_tag = 0;
+	unsigned int value;
+	unsigned int reg;
+
+	port = atoi(argv[3]);
+	eg_tag = atoi(argv[4]);
+
+	printf("port: %d, eg_tag: %d\n", port, eg_tag);
+
+	/*Check the input parameters is right or not.*/
+	if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PCR_EG_TAG_RELMASK)) {
+		printf(HELP_VLAN_EGRESS_TAG_PCR);
+		return;
+	}
+
+	reg = REG_PCR_P0_ADDR + port * 0x100;
+	reg_read(reg, &value);
+	value &= (~REG_PCR_EG_TAG_MASK);
+	value |= ((unsigned int)eg_tag << REG_PCR_EG_TAG_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+
+} /*end doVlanSetEgressTagPCR*/
+
+void doVlanSetEgressTagPVC(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned char eg_tag = 0;
+	unsigned int value;
+	unsigned int reg;
+
+	port = atoi(argv[3]);
+	eg_tag = atoi(argv[4]);
+
+	printf("port: %d, eg_tag: %d\n", port, eg_tag);
+
+	/*Check the input parameters is right or not.*/
+	if ((port > SWITCH_MAX_PORT) || (eg_tag > REG_PVC_EG_TAG_RELMASK)) {
+		printf(HELP_VLAN_EGRESS_TAG_PVC);
+		return;
+	}
+
+	reg = REG_PVC_P0_ADDR + port * 0x100;
+	reg_read(reg, &value);
+	value &= (~REG_PVC_EG_TAG_MASK);
+	value |= ((unsigned int)eg_tag << REG_PVC_EG_TAG_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+} /*end doVlanSetEgressTagPVC*/
+
+void doArlAging(int argc, char *argv[])
+{
+	unsigned char aging_en = 0;
+	unsigned int time = 0, aging_cnt = 0, aging_unit = 0, value, reg;
+	;
+
+	aging_en = atoi(argv[3]);
+	time = atoi(argv[4]);
+	printf("aging_en: %x, aging time: %x\n", aging_en, time);
+
+	/*Check the input parameters is right or not.*/
+	if ((aging_en != 0 && aging_en != 1) || (time <= 0 || time > 65536)) {
+		printf(HELP_ARL_AGING);
+		return;
+	}
+
+	reg = 0xa0;
+	reg_read(reg, &value);
+	value &= (~(1 << 20));
+	if (!aging_en) {
+		value |= (1 << 20);
+	}
+
+	aging_unit = (time / 0x100) + 1;
+	aging_cnt = (time / aging_unit);
+	aging_unit--;
+	aging_cnt--;
+
+	value &= (0xfff00000);
+	value |= ((aging_cnt << 12) | aging_unit);
+
+	printf("aging_unit: %x, aging_cnt: %x\n", aging_unit, aging_cnt);
+	printf("write reg: %x, value: %x\n", reg, value);
+
+	reg_write(reg, value);
+}
+
+void doMirrorEn(int argc, char *argv[])
+{
+	unsigned char mirror_en;
+	unsigned char mirror_port;
+	unsigned int value, reg;
+
+	mirror_en = atoi(argv[3]);
+	mirror_port = atoi(argv[4]);
+
+	printf("mirror_en: %d, mirror_port: %d\n", mirror_en, mirror_port);
+
+	/*Check the input parameters is right or not.*/
+	if ((mirror_en > 1) || (mirror_port > REG_CFC_MIRROR_PORT_RELMASK)) {
+		printf(HELP_MIRROR_EN);
+		return;
+	}
+
+	reg = REG_CFC_ADDR;
+	reg_read(reg, &value);
+	value &= (~REG_CFC_MIRROR_EN_MASK);
+	value |= (mirror_en << REG_CFC_MIRROR_EN_OFFT);
+	value &= (~REG_CFC_MIRROR_PORT_MASK);
+	value |= (mirror_port << REG_CFC_MIRROR_PORT_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+
+} /*end doMirrorEn*/
+
+void doMirrorPortBased(int argc, char *argv[])
+{
+	unsigned char port, port_tx_mir, port_rx_mir, vlan_mis, acl_mir, igmp_mir;
+	unsigned int value, reg;
+
+	port = atoi(argv[3]);
+	port_tx_mir = atoi(argv[4]);
+	port_rx_mir = atoi(argv[5]);
+	acl_mir = atoi(argv[6]);
+	vlan_mis = atoi(argv[7]);
+	igmp_mir = atoi(argv[8]);
+
+	printf("port:%d, port_tx_mir:%d, port_rx_mir:%d, acl_mir:%d, vlan_mis:%d, igmp_mir:%d\n", port, port_tx_mir, port_rx_mir, acl_mir, vlan_mis, igmp_mir);
+
+	/*Check the input parameters is right or not.*/
+	//if((port >= vlanCap->max_port_no) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)){
+	if ((port >= 7) || (port_tx_mir > 1) || (port_rx_mir > 1) || (acl_mir > 1) || (vlan_mis > 1)) { // also allow CPU port (port6)
+		printf(HELP_MIRROR_PORTBASED);
+		return;
+	}
+
+	reg = REG_PCR_P0_ADDR + port * 0x100;
+	reg_read(reg, &value);
+	value &= ~(REG_PORT_TX_MIR_MASK | REG_PORT_RX_MIR_MASK | REG_PCR_ACL_MIR_MASK | REG_PCR_VLAN_MIS_MASK);
+	value |= (port_tx_mir << REG_PORT_TX_MIR_OFFT) + (port_rx_mir << REG_PORT_RX_MIR_OFFT);
+	value |= (acl_mir << REG_PCR_ACL_MIR_OFFT) + (vlan_mis << REG_PCR_VLAN_MIS_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+
+	reg = REG_PIC_P0_ADDR + port * 0x100;
+	reg_read(reg, &value);
+	value &= ~(REG_PIC_IGMP_MIR_MASK);
+	value |= (igmp_mir << REG_PIC_IGMP_MIR_OFFT);
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+
+} /*end doMirrorPortBased*/
+
+void doStp(int argc, char *argv[])
+{
+	unsigned char port = 0;
+	unsigned char fid = 0;
+	unsigned char state = 0;
+	unsigned int value;
+	unsigned int reg;
+
+	port = atoi(argv[2]);
+	fid = atoi(argv[3]);
+	state = atoi(argv[4]);
+
+	printf("port: %d, fid: %d, state: %d\n", port, fid, state);
+
+	/*Check the input parameters is right or not.*/
+	if ((port > MAX_PORT + 1) || (fid > 7) || (state > 3)) {
+		printf(HELP_STP);
+		return;
+	}
+
+	reg = REG_SSC_P0_ADDR + port * 0x100;
+	reg_read(reg, &value);
+	value &= (~(3 << (fid << 2)));
+	value |= ((unsigned int)state << (fid << 2));
+
+	printf("write reg: %x, value: %x\n", reg, value);
+	reg_write(reg, value);
+}
+
+int ingress_rate_set(int on_off, unsigned int port, unsigned int bw)
+{
+	unsigned int reg, value;
+
+	reg = 0x1800 + (0x100 * port);
+	value = 0;
+	/*token-bucket*/
+	if (on_off == 1) {
+		if (chip_name == 0x7530) {
+			if (bw > 1000000) {
+				printf("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",bw);
+				return -1;
+			}
+			value = ((bw / 32) << 16) + (1 << 15) + (7 << 8) + (1 << 7) + 0x0f;
+		} else if (chip_name == 0x7531) {
+			if (bw > 2500000) {
+				printf("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",bw);
+				return -1;
+			}
+		        if (bw/32 >= 65536) //supoort 2.5G case
+                                value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (1 << 12) + (7 << 8) + 0xf;
+                        else
+                                value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (7 << 8) + 0xf;
+			}
+		else
+			printf("unknow chip\n");
+	}
+
+#if leaky_bucket
+	reg_read(reg, &value);
+	value &= 0xffff0000;
+	if (on_off == 1)
+	{
+		value |= on_off << 15;
+		//7530 same as 7531
+		if (bw < 100) {
+			value |= (0x0 << 8);
+			value |= bw;
+		} else if (bw < 1000) {
+			value |= (0x1 << 8);
+			value |= bw / 10;
+		} else if (bw < 10000) {
+			value |= (0x2 << 8);
+			value |= bw / 100;
+		} else if (bw < 100000) {
+			value |= (0x3 << 8);
+			value |= bw / 1000;
+		} else {
+			value |= (0x4 << 8);
+			value |= bw / 10000;
+		}
+	}
+#endif
+	reg_write(reg, value);
+	reg = 0x1FFC;
+	reg_read(reg, &value);
+	value = 0x110104;
+	reg_write(reg, value);
+	return 0;
+}
+
+int egress_rate_set(int on_off, int port, int bw)
+{
+	unsigned int reg, value;
+
+	reg = 0x1040 + (0x100 * port);
+	value = 0;
+	/*token-bucket*/
+	if (on_off == 1) {
+		if (chip_name == 0x7530) {
+			if (bw < 0 || bw > 1000000) {
+				printf("\n**Charge rate(%d) is larger than line rate(1000000kbps)**\n",bw);
+				return -1;
+			}
+			value = ((bw / 32) << 16) + (1 << 15) + (7 << 8) + (1 << 7) + 0xf;
+		} else if (chip_name == 0x7531) {
+			if (bw < 0 || bw > 2500000) {
+				printf("\n**Charge rate(%d) is larger than line rate(2500000kbps)**\n",bw);
+				return -1;
+			}
+		        if (bw/32 >= 65536)	//support 2.5G cases
+                                value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (1 << 12) + (7 << 8) + 0xf;
+                        else
+                                value = ((bw / 32) << 16) + (1 << 15) + (1 << 14) + (7 << 8) + 0xf;
+		}
+		else
+			printf("unknow chip\n");
+	}
+	reg_write(reg, value);
+	reg = 0x10E0;
+	reg_read(reg, &value);
+	value &= 0x18;
+	reg_write(reg, value);
+
+	return 0;
+}
+
+void rate_control(int argc, char *argv[])
+{
+	unsigned char dir = 0;
+	unsigned char port = 0;
+	unsigned int rate = 0;
+
+	dir = atoi(argv[2]);
+	port = atoi(argv[3]);
+	rate = atoi(argv[4]);
+
+	if (port > 6)
+		return;
+
+	if (dir == 1) //ingress
+		ingress_rate_set(1, port, rate);
+	else if (dir == 0) //egress
+		egress_rate_set(1, port, rate);
+	else
+		return;
+}
+
+int collision_pool_enable(int argc, char *argv[])
+{
+
+	unsigned char enable;
+	unsigned int value, reg;
+
+	enable = atoi(argv[3]);
+
+
+	printf("collision pool enable: %d \n", enable);
+
+	/*Check the input parameters is right or not.*/
+	if (enable > 1) {
+		printf(HELP_COLLISION_POOL_EN);
+		return -1;
+	}
+
+	if (chip_name == 0x7531) {
+		reg = REG_CPGC_ADDR;
+		if(enable == 1) {
+			/* active reset */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_RST_N_MASK);
+			reg_write(reg, value);
+
+			/* enanble clock */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_CLK_EN_MASK);
+			value |= (1 << REG_CPCG_COL_CLK_EN_OFFT);
+			reg_write(reg, value);
+
+			/* inactive reset */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_RST_N_MASK);
+			value |= (1 << REG_CPCG_COL_RST_N_OFFT);
+			reg_write(reg, value);
+
+			/* enable collision pool */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_EN_MASK);
+			value |= (1 << REG_CPCG_COL_EN_OFFT);
+			reg_write(reg, value);
+
+			reg_read(reg, &value);
+			printf("write reg: %x, value: %x\n", reg, value);
+		}else {
+
+			/* disable collision pool */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_EN_MASK);
+			reg_write(reg, value);
+
+			/* active reset */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_RST_N_MASK);
+			reg_write(reg, value);
+
+			/* inactive reset */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_RST_N_MASK);
+			value |= (1 << REG_CPCG_COL_RST_N_OFFT);
+			reg_write(reg, value);
+
+			/* disable clock */
+			reg_read(reg, &value);
+			value &= (~REG_CPCG_COL_CLK_EN_MASK);
+			reg_write(reg, value);
+
+			reg_read(reg, &value);
+			printf("write reg: %x, value: %x\n", reg, value);
+
+		}
+	}else{
+		printf("\nCommand not support by this chip.\n");
+}
+
+ return 0;
+}
+
+void collision_pool_mac_dump()
+{
+	unsigned int value, reg;
+
+	if (chip_name == 0x7531) {
+		reg = REG_CPGC_ADDR;
+		reg_read(reg, &value);
+		if(value & REG_CPCG_COL_EN_MASK)
+			table_dump_internal(COLLISION_TABLE);
+		else
+			printf("\ncollision pool is disabled, please enable it before use this command.\n");
+	}else {
+		printf("\nCommand not support by this chip.\n");
+	}
+}
+
+void collision_pool_dip_dump()
+{
+	unsigned int value, reg;
+
+	if (chip_name == 0x7531) {
+		reg = REG_CPGC_ADDR;
+		reg_read(reg, &value);
+		if(value & REG_CPCG_COL_EN_MASK)
+			dip_dump_internal(COLLISION_TABLE);
+		else
+			printf("\ncollision pool is disabled, please enable it before use this command.\n");
+		}else {
+		printf("\nCommand not support by this chip.\n");
+	}
+
+
+}
+
+void collision_pool_sip_dump()
+{
+	unsigned int value, reg;
+
+	if (chip_name == 0x7531) {
+		reg = REG_CPGC_ADDR;
+		reg_read(reg, &value);
+		if(value & REG_CPCG_COL_EN_MASK)
+			sip_dump_internal(COLLISION_TABLE);
+		else
+			printf("\ncollision pool is disabled, please enable it before use this command.\n");
+	}else {
+		printf("\nCommand not support by this chip.\n");
+	}
+
+
+}
+
+void pfc_get_rx_counter(int argc, char *argv[])
+{
+	int port;
+	unsigned int value, reg;
+	unsigned int user_pri;
+
+	port = strtoul(argv[3], NULL, 0);
+	if (port < 0 || 6 < port) {
+		printf("wrong port range, should be within 0~6\n");
+		return;
+	}
+
+	if (chip_name == 0x7531) {
+		reg= PFC_RX_COUNTER_L(port);
+		reg_read(reg, &value);
+		user_pri = value & 0xff;
+		printf("\n port %d rx pfc (up=0)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff00) >> 8;
+		printf("\n port %d rx pfc (up=1)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff0000) >> 16;
+		printf("\n port %d rx pfc (up=2)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff000000) >> 24;
+		printf("\n port %d rx pfc (up=3)pause on counter is %d.\n", port,user_pri);
+
+		reg= PFC_RX_COUNTER_H(port);
+		reg_read(reg, &value);
+		user_pri = value & 0xff;
+		printf("\n port %d rx pfc (up=4)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff00) >> 8;
+		printf("\n port %d rx pfc (up=5)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff0000) >> 16;
+		printf("\n port %d rx pfc (up=6)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff000000) >> 24;
+		printf("\n port %d rx pfc (up=7)pause on counter is %d.\n", port,user_pri);
+
+		/* for rx counter could be updated successfully */
+		reg_read(PMSR_P(port), &value);
+		reg_read(PMSR_P(port), &value);
+	}else {
+		printf("\nCommand not support by this chip.\n");
+	}
+
+}
+
+void pfc_get_tx_counter(int argc, char *argv[])
+{
+	int port;
+	unsigned int value, reg;
+	unsigned int user_pri;
+
+	port = strtoul(argv[3], NULL, 0);
+	if (port < 0 || 6 < port) {
+		printf("wrong port range, should be within 0~6\n");
+		return;
+	}
+
+	if (chip_name == 0x7531) {
+		reg= PFC_TX_COUNTER_L(port);
+		reg_read(reg, &value);
+		user_pri = value & 0xff;
+		printf("\n port %d tx pfc (up=0)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff00) >> 8;
+		printf("\n port %d tx pfc (up=1)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff0000) >> 16;
+		printf("\n port %d tx pfc (up=2)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff000000) >> 24;
+		printf("\n port %d tx pfc (up=3)pause on counter is %d.\n", port,user_pri);
+
+		reg= PFC_TX_COUNTER_H(port);
+		reg_read(reg, &value);
+		user_pri = value & 0xff;
+		printf("\n port %d tx pfc (up=4)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff00) >> 8;
+		printf("\n port %d tx pfc (up=5)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff0000) >> 16;
+		printf("\n port %d tx pfc (up=6)pause on counter is %d.\n", port,user_pri);
+		user_pri = (value & 0xff000000) >> 24;
+		printf("\n port %d tx pfc (up=7)pause on counter is %d.\n", port,user_pri);
+
+		/* for tx counter could be updated successfully */
+		reg_read(PMSR_P(port), &value);
+		reg_read(PMSR_P(port), &value);
+	}else {
+		 printf("\nCommand not support by this chip.\n");
+	}
+}
+
+void read_output_queue_counters()
+{
+	unsigned int port=0;
+	unsigned int value, output_queue;
+	unsigned int base=0x220;
+
+	for (port = 0; port < 7; port++) {
+		reg_write(0x7038, base + (port *4));
+		reg_read(0x7034, &value);
+		output_queue = value & 0xff;
+		printf("\n port %d  output queue 0 counter is %d.\n", port,output_queue);
+		output_queue = (value & 0xff00) >> 8;
+		printf("\n port %d  output queue 1 counter is %d.\n", port,output_queue);
+
+		reg_write(0x7038, base + (port *4) + 1);
+		reg_read(0x7034, &value);
+		output_queue = value & 0xff;
+		printf("\n port %d  output queue 2 counter is %d.\n", port,output_queue);
+		output_queue = (value & 0xff00) >> 8;
+		printf("\n port %d  output queue 3 counter is %d.\n", port,output_queue);
+
+		reg_write(0x7038, base + (port *4) + 2);
+		reg_read(0x7034, &value);
+		output_queue = value & 0xff;
+		printf("\n port %d  output queue 4 counter is %d.\n", port,output_queue);
+		output_queue = (value & 0xff00) >> 8;
+		printf("\n port %d  output queue 5 counter is %d.\n", port,output_queue);
+
+		reg_write(0x7038, base + (port *4) + 3);
+		reg_read(0x7034, &value);
+		output_queue = value & 0xff;
+		printf("\n port %d  output queue 6 counter is %d.\n", port,output_queue);
+		output_queue = (value & 0xff00) >> 8;
+		printf("\n port %d  output queue 7 counter is %d.\n", port,output_queue);
+	}
+}
+
+void read_free_page_counters()
+{
+	unsigned int value;
+	unsigned int free_page,free_page_last_read;
+	unsigned int fc_free_blk_lothd,fc_free_blk_hithd;
+	unsigned int fc_port_blk_thd,fc_port_blk_hi_thd;
+	unsigned int queue[8]={0};
+
+	if (chip_name == 0x7531) {
+		/* get system free page link counter*/
+		reg_read(0x1fc0, &value);
+		free_page = value & 0xFFF;
+		free_page_last_read = (value & 0xFFF0000) >> 16;
+
+		/* get system flow control waterwark */
+		reg_read(0x1fe0, &value);
+		fc_free_blk_lothd = value & 0x3FF;
+		fc_free_blk_hithd = (value & 0x3FF0000) >> 16;
+
+		/* get port flow control waterwark */
+		reg_read(0x1fe4, &value);
+		fc_port_blk_thd = value & 0x3FF;
+		fc_port_blk_hi_thd = (value & 0x3FF0000) >> 16;
+
+		/* get queue flow control waterwark */
+		reg_read(0x1fe8, &value);
+		queue[0]= value & 0x3F;
+		queue[1]= (value & 0x3F00) >> 8;
+		queue[2]= (value & 0x3F0000) >> 16;
+		queue[3]= (value & 0x3F000000) >> 24;
+		reg_read(0x1fec, &value);
+		queue[4]= value & 0x3F;
+		queue[5]= (value & 0x3F00) >> 8;
+		queue[6]= (value & 0x3F0000) >> 16;
+		queue[7]= (value & 0x3F000000) >> 24;
+	} else {
+		/* get system free page link counter*/
+		reg_read(0x1fc0, &value);
+		free_page = value & 0x3FF;
+		free_page_last_read = (value & 0x3FF0000) >> 16;
+
+		/* get system flow control waterwark */
+		reg_read(0x1fe0, &value);
+		fc_free_blk_lothd = value & 0xFF;
+		fc_free_blk_hithd = (value & 0xFF00) >> 8;
+
+		/* get port flow control waterwark */
+		reg_read(0x1fe0, &value);
+		fc_port_blk_thd = (value & 0xFF0000) >> 16;
+		reg_read(0x1ff4, &value);
+		fc_port_blk_hi_thd = (value & 0xFF00) >> 8;
+
+		/* get queue flow control waterwark */
+		reg_read(0x1fe4, &value);
+		queue[0]= value & 0xF;
+		queue[1]= (value & 0xF0) >> 4;
+		queue[2]= (value & 0xF00) >> 8;
+		queue[3]= (value & 0xF000) >>12;
+		queue[4]= (value & 0xF0000) >>16;
+		queue[5]= (value & 0xF00000) >> 20;
+		queue[6]= (value & 0xF000000) >> 24;
+		queue[7]= (value & 0xF0000000) >> 28;
+	}
+
+	printf("<===Free Page=======Current=======Last Read access=====> \n ");
+	printf("	                                                 \n ");
+	printf(" page counter      %u                %u               \n ",free_page,free_page_last_read);
+	printf("                                                        \n ");
+	printf("========================================================= \n ");
+	printf("<===Type=======High threshold======Low threshold=========\n ");
+	printf("                                                        \n ");
+	printf("  system:         %u                 %u               \n", fc_free_blk_hithd*2,  fc_free_blk_lothd*2);
+	printf("    port:         %u                 %u               \n", fc_port_blk_hi_thd*2, fc_port_blk_thd*2);
+	printf(" queue 0:         %u                 NA                \n", queue[0]);
+	printf(" queue 1:         %u                 NA                \n", queue[1]);
+	printf(" queue 2:         %u                 NA                 \n", queue[2]);
+	printf(" queue 3:         %u                 NA                \n", queue[3]);
+	printf(" queue 4:         %u                 NA                \n", queue[4]);
+	printf(" queue 5:         %u                 NA                \n", queue[5]);
+	printf(" queue 6:         %u                 NA                \n", queue[6]);
+	printf(" queue 7:         %u                 NA                \n", queue[7]);
+	printf("=========================================================\n ");
+}
+
+void eee_enable(int argc, char *argv[])
+{
+	unsigned long enable;
+	unsigned int value;
+	unsigned int eee_cap;
+	unsigned int eee_en_bitmap = 0;
+	unsigned long port_map;
+	long port_num = -1;
+	int p;
+
+	if (argc < 3)
+		goto error;
+
+	/*Check the input parameters is right or not.*/
+	if (!strncmp(argv[2], "enable", 7))
+		enable = 1;
+	else if (!strncmp(argv[2], "disable", 8))
+		enable = 0;
+	else
+		goto error;
+
+	if (argc > 3) {
+		if (strlen(argv[3]) == 1) {
+			port_num = strtol(argv[3], (char **)NULL, 10);
+			if (port_num < 0 || port_num > MAX_PHY_PORT - 1) {
+				printf("Illegal port index and port:0~4\n");
+				goto error;
+			}
+			port_map = 1 << port_num;
+		} else if (strlen(argv[3]) == 5) {
+			port_map = 0;
+			for (p = 0; p < MAX_PHY_PORT; p++) {
+				if (argv[3][p] != '0' && argv[3][p] != '1') {
+					printf("portmap format error, should be combination of 0 or 1\n");
+					goto error;
+				}
+				port_map |= ((argv[3][p] - '0') << p);
+			}
+		} else {
+			printf("port_no or portmap format error, should be length of 1 or 5\n");
+			goto error;
+		}
+	} else {
+		port_map = 0x1f;
+	}
+
+	eee_cap = (enable)? 6: 0;
+	for (p = 0; p < MAX_PHY_PORT; p++) {
+		/* port_map describe p0p1p2p3p4 from left to rignt */
+		if(!!(port_map & (1 << p)))
+			mii_mgr_c45_write(p, 0x7, 0x3c, eee_cap);
+
+		mii_mgr_c45_read(p, 0x7, 0x3c, &value);
+		/* mt7531: Always readback eee_cap = 0 when global EEE switch
+		 * is turned off.
+		 */
+		if (value | eee_cap)
+			eee_en_bitmap |= (1 << (MAX_PHY_PORT - 1 - p));
+	}
+
+	/* Turn on/off global EEE switch */
+	if (chip_name == 0x7531) {
+		mii_mgr_c45_read(0, 0x1f, 0x403, &value);
+		if (eee_en_bitmap)
+			value |= (1 << 6);
+		else
+			value &= ~(1 << 6);
+		mii_mgr_c45_write(0, 0x1f, 0x403, value);
+	} else {
+		printf("\nCommand not support by this chip.\n");
+	}
+
+	printf("EEE(802.3az) %s", (enable)? "enable": "disable");
+	if (argc == 4) {
+		if (port_num >= 0)
+			printf(" port%ld", port_num);
+		else
+			printf(" port_map: %s", argv[3]);
+	} else {
+		printf(" all ports");
+	}
+	printf("\n");
+
+	return;
+error:
+	printf(HELP_EEE_EN);
+	return;
+}
+
+void eee_dump(int argc, char *argv[])
+{
+	unsigned int cap, lp_cap;
+	long port = -1;
+	int p;
+
+	if (argc > 3) {
+		if (strlen(argv[3]) > 1) {
+			printf("port# format error, should be of length 1\n");
+			return;
+		}
+
+		port = strtol(argv[3], (char **)NULL, 0);
+		if (port < 0 || port > MAX_PHY_PORT) {
+			printf("port# format error, should be 0 to %d\n",
+				       MAX_PHY_PORT);
+			return;
+		}
+	}
+
+	for (p = 0; p < MAX_PHY_PORT; p++) {
+		if (port >= 0 && p != port)
+			continue;
+
+		mii_mgr_c45_read(p, 0x7, 0x3c, &cap);
+		mii_mgr_c45_read(p, 0x7, 0x3d, &lp_cap);
+		printf("port%d EEE cap=0x%02x, link partner EEE cap=0x%02x",
+		       p, cap, lp_cap);
+
+		if (port >= 0 && p == port) {
+			mii_mgr_c45_read(p, 0x3, 0x1, &cap);
+			printf(", st=0x%03x", cap);
+		}
+		printf("\n");
+	}
+}
+
+void dump_each_port(unsigned int base)
+{
+	unsigned int pkt_cnt = 0;
+	int i = 0;
+
+	for (i = 0; i < 7; i++) {
+		reg_read((base) + (i * 0x100), &pkt_cnt);
+		printf("%8u ", pkt_cnt);
+	}
+	printf("\n");
+}
+
+void read_mib_counters()
+{
+	printf("===================== %8s %8s %8s %8s %8s %8s %8s\n",
+	       "Port0", "Port1", "Port2", "Port3", "Port4", "Port5", "Port6");
+	printf("Tx Drop Packet      :");
+	dump_each_port(0x4000);
+	printf("Tx CRC Error        :");
+	dump_each_port(0x4004);
+	printf("Tx Unicast Packet   :");
+	dump_each_port(0x4008);
+	printf("Tx Multicast Packet :");
+	dump_each_port(0x400C);
+	printf("Tx Broadcast Packet :");
+	dump_each_port(0x4010);
+	printf("Tx Collision Event  :");
+	dump_each_port(0x4014);
+	printf("Tx Pause Packet     :");
+	dump_each_port(0x402C);
+	printf("Rx Drop Packet      :");
+	dump_each_port(0x4060);
+	printf("Rx Filtering Packet :");
+	dump_each_port(0x4064);
+	printf("Rx Unicast Packet   :");
+	dump_each_port(0x4068);
+	printf("Rx Multicast Packet :");
+	dump_each_port(0x406C);
+	printf("Rx Broadcast Packet :");
+	dump_each_port(0x4070);
+	printf("Rx Alignment Error  :");
+	dump_each_port(0x4074);
+	printf("Rx CRC Error	    :");
+	dump_each_port(0x4078);
+	printf("Rx Undersize Error  :");
+	dump_each_port(0x407C);
+	printf("Rx Fragment Error   :");
+	dump_each_port(0x4080);
+	printf("Rx Oversize Error   :");
+	dump_each_port(0x4084);
+	printf("Rx Jabber Error     :");
+	dump_each_port(0x4088);
+	printf("Rx Pause Packet     :");
+	dump_each_port(0x408C);
+}
+
+void clear_mib_counters()
+{
+	reg_write(0x4fe0, 0xf0);
+	read_mib_counters();
+	reg_write(0x4fe0, 0x800000f0);
+}
+
+
+void exit_free()
+{
+	free(attres);
+	attres = NULL;
+	switch_ioctl_fini();
+	mt753x_netlink_free();
+}
diff --git a/feed/switch/src/switch_fun.h b/feed/switch/src/switch_fun.h
new file mode 100644
index 0000000..95ff4b3
--- /dev/null
+++ b/feed/switch/src/switch_fun.h
@@ -0,0 +1,144 @@
+/*
+* switch_fun.h: switch function sets
+*/
+#ifndef SWITCH_FUN_H
+#define SWITCH_FUN_H
+
+#include <stdbool.h>
+
+#define MT7530_T10_TEST_CONTROL 0x145
+
+#define MAX_PORT 6
+#define MAX_PHY_PORT 5
+#define CONFIG_MTK_7531_DVT 1
+
+extern int chip_name;
+extern struct mt753x_attr *attres;
+extern bool nl_init_flag;
+
+/*basic operation*/
+int reg_read(unsigned int offset, unsigned int *value);
+int reg_write(unsigned int offset, unsigned int value);
+int mii_mgr_read(unsigned int port_num, unsigned int reg, unsigned int *value);
+int mii_mgr_write(unsigned int port_num, unsigned int reg, unsigned int value);
+int mii_mgr_c45_read(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int *value);
+int mii_mgr_c45_write(unsigned int port_num, unsigned int dev, unsigned int reg, unsigned int value);
+
+/*phy setting*/
+int phy_dump(int phy_addr);
+void phy_crossover(int argc, char *argv[]);
+int rw_phy_token_ring(int argc, char *argv[]);
+/*arl setting*/
+void doArlAging(int argc, char *argv[]);
+
+/*acl setting*/
+void acl_mac_add(int argc, char *argv[]);
+void acl_dip_meter(int argc, char *argv[]);
+void acl_dip_trtcm(int argc, char *argv[]);
+void acl_ethertype(int argc, char *argv[]);
+void acl_ethertype(int argc, char *argv[]);
+void acl_dip_modify(int argc, char *argv[]);
+void acl_dip_pppoe(int argc, char *argv[]);
+void acl_dip_add(int argc, char *argv[]);
+void acl_l4_add(int argc, char *argv[]);
+void acl_sp_add(int argc, char *argv[]);
+
+void acl_port_enable(int argc, char *argv[]);
+void acl_table_add(int argc, char *argv[]);
+void acl_mask_table_add(int argc, char *argv[]);
+void acl_rule_table_add(int argc, char *argv[]);
+void acl_rate_table_add(int argc, char *argv[]);
+
+/*dip table*/
+void dip_dump(void);
+void dip_add(int argc, char *argv[]);
+void dip_del(int argc, char *argv[]);
+void dip_clear(void);
+
+/*sip table*/
+void sip_dump(void);
+void sip_add(int argc, char *argv[]);
+void sip_del(int argc, char *argv[]);
+void sip_clear(void);
+
+/*stp*/
+void doStp(int argc, char *argv[]);
+
+/*mac table*/
+void table_dump(void);
+void table_add(int argc, char *argv[]);
+void table_search_mac_vid(int argc, char *argv[]);
+void table_search_mac_fid(int argc, char *argv[]);
+void table_del_fid(int argc, char *argv[]);
+void table_del_vid(int argc, char *argv[]);
+void table_clear(void);
+
+/*vlan table*/
+void vlan_dump(int argc, char *argv[]);
+void vlan_clear(int argc, char *argv[]);
+void vlan_set(int argc, char *argv[]);
+
+void doVlanSetPvid(int argc, char *argv[]);
+void doVlanSetVid(int argc, char *argv[]);
+void doVlanSetAccFrm(int argc, char *argv[]);
+void doVlanSetPortAttr(int argc, char *argv[]);
+void doVlanSetPortMode(int argc, char *argv[]);
+void doVlanSetEgressTagPCR(int argc, char *argv[]);
+void doVlanSetEgressTagPVC(int argc, char *argv[]);
+
+/*igmp function*/
+void igmp_on(int argc, char *argv[]);
+void igmp_off();
+void igmp_disable(int argc, char *argv[]);
+void igmp_enable(int argc, char *argv[]);
+
+/*mirror function*/
+void set_mirror_to(int argc, char *argv[]);
+void set_mirror_from(int argc, char *argv[]);
+void doMirrorPortBased(int argc, char *argv[]);
+void doMirrorEn(int argc, char *argv[]);
+
+/*rate control*/
+void rate_control(int argc, char *argv[]);
+int ingress_rate_set(int on_off, unsigned int port, unsigned int bw);
+int egress_rate_set(int on_off, int port, int bw);
+
+/*QoS*/
+int qos_sch_select(int argc, char *argv[]);
+void qos_set_base(int argc, char *argv[]);
+void qos_wfq_set_weight(int argc, char *argv[]);
+void qos_set_portpri(int argc, char *argv[]);
+void qos_set_dscppri(int argc, char *argv[]);
+void qos_pri_mapping_queue(int argc, char *argv[]);
+
+/*flow control*/
+int global_set_mac_fc(int argc, char *argv[]);
+int phy_set_fc(int argc, char *argv[]);
+int phy_set_an(int argc, char *argv[]);
+
+/* collision pool functions */
+int collision_pool_enable(int argc, char *argv[]);
+void collision_pool_mac_dump();
+void collision_pool_dip_dump();
+void collision_pool_sip_dump();
+
+/*pfc functions*/
+int set_mac_pfc(int argc, char *argv[]);
+void pfc_get_rx_counter(int argc, char *argv[]);
+void pfc_get_tx_counter(int argc, char *argv[]);
+
+/*switch reset*/
+void switch_reset(int argc, char *argv[]);
+
+/* EEE(802.3az) function  */
+void eee_enable(int argc, char *argv[]);
+void eee_dump(int argc, char *argv[]);
+
+void read_mib_counters();
+void clear_mib_counters();
+void read_output_queue_counters();
+void read_free_page_counters();
+
+void phy_crossover(int argc, char *argv[]);
+void exit_free();
+#endif
diff --git a/feed/switch/src/switch_ioctl.c b/feed/switch/src/switch_ioctl.c
new file mode 100644
index 0000000..082eab1
--- /dev/null
+++ b/feed/switch/src/switch_ioctl.c
@@ -0,0 +1,346 @@
+/*
+ * switch_ioctl.c: switch(ioctl) set API
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+
+#include "switch_fun.h"
+#include "switch_ioctl.h"
+
+static int esw_fd;
+
+void switch_ioctl_init(void)
+{
+	esw_fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (esw_fd < 0) {
+		perror("socket");
+		exit(0);
+	}
+}
+
+void switch_ioctl_fini(void)
+{
+	close(esw_fd);
+}
+
+int reg_read_ioctl(unsigned int offset, unsigned int *value)
+{
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+
+	mii.phy_id = 0x1f;
+	mii.reg_num = offset;
+
+	if (-1 == ioctl(esw_fd, RAETH_MII_READ, &ifr)) {
+		perror("ioctl");
+		close(esw_fd);
+		exit(0);
+	}
+	*value = mii.val_out;
+	return 0;
+}
+
+int reg_read_tr(int offset, int *value)
+{
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+
+	mii.phy_id = 0;
+	mii.reg_num = offset;
+
+	if (-1 == ioctl(esw_fd, RAETH_MII_READ, &ifr)) {
+		perror("ioctl");
+		close(esw_fd);
+		exit(0);
+	}
+	*value = mii.val_out;
+	return 0;
+}
+
+int reg_write_ioctl(unsigned int offset, unsigned int value)
+{
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+
+	mii.phy_id = 0x1f;
+	mii.reg_num = offset;
+	mii.val_in = value;
+
+	if (-1 == ioctl(esw_fd, RAETH_MII_WRITE, &ifr)) {
+		perror("ioctl");
+		close(esw_fd);
+		exit(0);
+	}
+	return 0;
+}
+
+int reg_write_tr(int offset, int value)
+{
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+
+	mii.phy_id = 0;
+	mii.reg_num = offset;
+	mii.val_in = value;
+
+	if (-1 == ioctl(esw_fd, RAETH_MII_WRITE, &ifr)) {
+		perror("ioctl");
+		close(esw_fd);
+		exit(0);
+	}
+	return 0;
+}
+
+int phy_dump_ioctl(unsigned int phy_addr)
+{
+	struct ifreq ifr;
+	struct esw_reg reg;
+
+	reg.val = phy_addr;
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &reg;
+	if (-1 == ioctl(esw_fd, RAETH_ESW_PHY_DUMP, &ifr)) {
+		perror("ioctl");
+		close(esw_fd);
+		exit(0);
+	}
+	return 0;
+}
+
+int mii_mgr_cl22_read_ioctl(unsigned int port_num, unsigned int reg, unsigned int *value)
+{
+	unsigned int reg_value;
+	int loop_cnt;
+	int op_busy;
+
+	loop_cnt = 0;
+
+	/*Change to indirect access mode*/
+	/*if you need to use direct access mode, please change back manually by reset bit5*/
+	reg_read(0x7804, &reg_value);
+	if (((reg_value >> 5) & 0x1) == 0) {
+		reg_value |= 1 << 5;
+		reg_write(0x7804, reg_value);
+		printf("Change to indirect access mode:0x%x\n", reg_value);
+	}
+	reg_value = 0x80090000 | (port_num << 20) | (reg << 25);
+	reg_write(0x701c, reg_value);
+	while (1)
+	{
+		reg_read(0x701c, &reg_value);
+		op_busy = reg_value & (1 << 31);
+		if (!op_busy) {
+			reg_value = reg_value & 0xFFFF;
+			break;
+		} else if (loop_cnt < 10)
+			loop_cnt++;
+		else {
+			printf("MDIO read opeartion timeout\n");
+			reg_value = 0;
+			break;
+		}
+	}
+	printf(" PHY Indirect Access Control(0x701c) register read value =0x%x  \n", reg_value);
+	*value = reg_value;
+
+	return 0;
+}
+
+int mii_mgr_cl22_write_ioctl(unsigned int port_num, unsigned int reg, unsigned int value)
+{
+	unsigned int reg_value;
+	int loop_cnt;
+	int op_busy;
+
+	loop_cnt = 0;
+	/*Change to indirect access mode*/
+	/*if you need to use direct access mode, please change back manually by reset bit5*/
+	reg_read(0x7804, &reg_value);
+	if (((reg_value >> 5) & 0x1) == 0) {
+		reg_value |= 1 << 5;
+		reg_write(0x7804, reg_value);
+		printf("Change to indirect access mode:0x%x\n", reg_value);
+	}
+
+	reg_value = 0x80050000 | (port_num << 20) | (reg << 25) | value;
+	reg_write(0x701c, reg_value);
+	while (1)
+	{
+		reg_read(0x701c, &reg_value);
+		op_busy = reg_value & (1 << 31);
+		if (!op_busy)
+			break;
+		else if (loop_cnt < 10)
+			loop_cnt++;
+		else {
+			printf("MDIO write opeartion timeout\n");
+			break;
+		}
+	}
+
+	printf(" PHY Indirect Access Control(0x701c) register write value =0x%x  \n", reg_value);
+
+	return 0;
+}
+
+int mii_mgr_cl45_read_ioctl(unsigned int port_num, unsigned int dev,
+			    unsigned int reg, unsigned int *value)
+{
+	int sk, method, ret;
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	if (!value)
+		return -1;
+
+	sk = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		printf("Open socket failed\n");
+
+		return -1;
+	}
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 13;
+	mii.val_in = dev;
+	ret = ioctl(sk, method, &ifr);
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 14;
+	mii.val_in = reg;
+	ret = ioctl(sk, method, &ifr);
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 13;
+	mii.val_in = (0x6000 | dev);
+	ret = ioctl(sk, method, &ifr);
+
+	usleep(1000);
+
+	method = RAETH_MII_READ;
+	mii.phy_id = port_num;
+	mii.reg_num = 14;
+	ret = ioctl(sk, method, &ifr);
+
+	close(sk);
+	*value = mii.val_out;
+
+	return ret;
+}
+
+int mii_mgr_cl45_write_ioctl(unsigned int port_num, unsigned int dev,
+			     unsigned int reg, unsigned int value)
+{
+	int sk, method, ret;
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	sk = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		printf("Open socket failed\n");
+
+		return -1;
+	}
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 13;
+	mii.val_in = dev;
+	ret = ioctl(sk, method, &ifr);
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 14;
+	mii.val_in = reg;
+	ret = ioctl(sk, method, &ifr);
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 13;
+	mii.val_in = (0x6000 | dev);
+	ret = ioctl(sk, method, &ifr);
+
+	usleep(1000);
+
+	method = RAETH_MII_WRITE;
+	mii.phy_id = port_num;
+	mii.reg_num = 14;
+	mii.val_in = value;
+	ret = ioctl(sk, method, &ifr);
+
+	close(sk);
+
+	return ret;
+}
+
+int dump_gphy(void)
+{
+	int cl22_reg[6] = {0x00, 0x01, 0x04, 0x05, 0x09, 0x0A};
+	int cl45_start_reg = 0x9B;
+	int cl45_end_reg = 0xA2;
+	unsigned int value;
+	int port_num = 5;
+	int i, j, ret;
+
+	int sk, method;
+	struct ifreq ifr;
+	struct ra_mii_ioctl_data mii;
+
+	sk = socket(AF_INET, SOCK_DGRAM, 0);
+	if (sk < 0) {
+		printf("Open socket failed\n");
+		return -1;
+	}
+
+	strncpy(ifr.ifr_name, ETH_DEVNAME, 5);
+	ifr.ifr_data = &mii;
+	/* dump CL45 reg first*/
+	for (i = 0; i < port_num; i++) {
+		printf("== Port %d ==\n", i);
+		for (j = cl45_start_reg; j < (cl45_end_reg + 1); j++) {
+			ret = mii_mgr_cl45_read_ioctl(i, 0x1E, j, &value);
+			if (ret)
+				continue;
+			printf("dev1Eh_reg%xh = 0x%x\n", j, value);
+		}
+	}
+	printf("== Global ==\n");
+	for (i = 0; i < sizeof(cl22_reg) / sizeof(cl22_reg[0]); i++) {
+		method = RAETH_MII_READ;
+		mii.phy_id = 0;
+		mii.reg_num = cl22_reg[i];
+		ret = ioctl(sk, method, &ifr);
+		printf("Reg%xh = 0x%x\n", cl22_reg[i], mii.val_out);
+	}
+
+	close(sk);
+
+	return ret;
+}
diff --git a/feed/switch/src/switch_ioctl.h b/feed/switch/src/switch_ioctl.h
new file mode 100644
index 0000000..97946af
--- /dev/null
+++ b/feed/switch/src/switch_ioctl.h
@@ -0,0 +1,68 @@
+/*
+ * switch_ioctl.h: switch(ioctl) set API
+ */
+
+#ifndef SWITCH_IOCTL_H
+#define SWITCH_IOCTL_H
+
+#define ETH_DEVNAME "eth0"
+#define BR_DEVNAME "br-lan"
+
+#define RAETH_MII_READ                  0x89F3
+#define RAETH_MII_WRITE                 0x89F4
+#define RAETH_ESW_PHY_DUMP              0x89F7
+
+struct esw_reg {
+        unsigned int off;
+        unsigned int val;
+};
+
+struct ra_mii_ioctl_data {
+        __u32 phy_id;
+        __u32 reg_num;
+        __u32 val_in;
+        __u32 val_out;
+        __u32 port_num;
+        __u32 dev_addr;
+        __u32 reg_addr;
+};
+
+struct ra_switch_ioctl_data {
+        unsigned int cmd;
+        unsigned int on_off;
+        unsigned int port;
+        unsigned int bw;
+        unsigned int vid;
+        unsigned int fid;
+        unsigned int port_map;
+        unsigned int rx_port_map;
+        unsigned int tx_port_map;
+        unsigned int igmp_query_interval;
+        unsigned int reg_addr;
+        unsigned int reg_val;
+        unsigned int mode;
+        unsigned int qos_queue_num;
+        unsigned int qos_type;
+        unsigned int qos_pri;
+        unsigned int qos_dscp;
+        unsigned int qos_table_idx;
+        unsigned int qos_weight;
+        unsigned char mac[6];
+};
+
+extern int chip_name;
+
+void switch_ioctl_init(void);
+void switch_ioctl_fini(void);
+int reg_read_ioctl(unsigned int offset, unsigned int *value);
+int reg_write_ioctl(unsigned int offset, unsigned int value);
+int phy_dump_ioctl(unsigned int phy_addr);
+int mii_mgr_cl22_read_ioctl(unsigned int port_num, unsigned int reg,
+			    unsigned int *value);
+int mii_mgr_cl22_write_ioctl(unsigned int port_num, unsigned int reg,
+			     unsigned int value);
+int mii_mgr_cl45_read_ioctl(unsigned int port_num, unsigned int dev,
+			    unsigned int reg, unsigned int *value);
+int mii_mgr_cl45_write_ioctl(unsigned int port_num, unsigned int dev,
+			     unsigned int reg, unsigned int value);
+#endif
diff --git a/feed/switch/src/switch_netlink.c b/feed/switch/src/switch_netlink.c
new file mode 100644
index 0000000..90a4a19
--- /dev/null
+++ b/feed/switch/src/switch_netlink.c
@@ -0,0 +1,445 @@
+/*
+ * switch_netlink.c: switch(netlink) set API
+ *
+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netlink/netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+
+#include "switch_netlink.h"
+
+static struct nl_sock *user_sock;
+static struct nl_cache *cache;
+static struct genl_family *family;
+static struct nlattr *attrs[MT753X_ATTR_TYPE_MAX + 1];
+
+static int wait_handler(struct nl_msg *msg, void *arg)
+{
+	int *finished = arg;
+
+	*finished = 1;
+	return NL_STOP;
+}
+
+static int list_swdevs(struct nl_msg *msg, void *arg)
+{
+	struct mt753x_attr *val = arg;
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+	if (nla_parse(attrs, MT753X_ATTR_TYPE_MAX, genlmsg_attrdata(gnlh, 0),
+		      genlmsg_attrlen(gnlh, 0), NULL) < 0)
+		goto done;
+
+	if (gnlh->cmd == MT753X_CMD_REPLY) {
+		if (attrs[MT753X_ATTR_TYPE_MESG]) {
+			val->dev_info =
+				nla_get_string(attrs[MT753X_ATTR_TYPE_MESG]);
+			printf("register switch dev:\n%s", val->dev_info);
+		}
+		else {
+			fprintf(stderr, "ERROR:No switch dev now\n");
+			goto done;
+		}
+	} else
+		goto done;
+	return 0;
+done:
+	return NL_SKIP;
+}
+
+static int construct_attrs(struct nl_msg *msg, void *arg)
+{
+	struct mt753x_attr *val = arg;
+	int type = val->type;
+
+	if (val->dev_id > -1)
+		NLA_PUT_U32(msg, MT753X_ATTR_TYPE_DEV_ID, val->dev_id);
+
+	if (val->op == 'r') {
+		if (val->phy_dev != -1)
+			NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV, val->phy_dev);
+		if (val->port_num >= 0)
+			NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY, val->port_num);
+		NLA_PUT_U32(msg, type, val->reg);
+	} else if (val->op == 'w') {
+		if (val->phy_dev != -1)
+			NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY_DEV, val->phy_dev);
+		if (val->port_num >= 0)
+			NLA_PUT_U32(msg, MT753X_ATTR_TYPE_PHY, val->port_num);
+		NLA_PUT_U32(msg, type, val->reg);
+		NLA_PUT_U32(msg, MT753X_ATTR_TYPE_VAL, val->value);
+	} else {
+		printf("construct_attrs_message\n");
+		NLA_PUT_STRING(msg, type, "hello");
+	}
+	return 0;
+
+nla_put_failure:
+	return -1;
+}
+
+static int spilt_attrs(struct nl_msg *msg, void *arg)
+{
+	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+	struct mt753x_attr *val = arg;
+	char *str;
+
+	if (nla_parse(attrs, MT753X_ATTR_TYPE_MAX, genlmsg_attrdata(gnlh, 0),
+		      genlmsg_attrlen(gnlh, 0), NULL) < 0)
+		goto done;
+
+	if ((gnlh->cmd == MT753X_CMD_WRITE) || (gnlh->cmd == MT753X_CMD_READ)) {
+		if (attrs[MT753X_ATTR_TYPE_MESG]) {
+			str = nla_get_string(attrs[MT753X_ATTR_TYPE_MESG]);
+			printf(" %s\n", str);
+			if (!strncmp(str, "No", 2))
+				goto done;
+		}
+		if (attrs[MT753X_ATTR_TYPE_REG]) {
+			val->reg =
+			    nla_get_u32(attrs[MT753X_ATTR_TYPE_REG]);
+		}
+		if (attrs[MT753X_ATTR_TYPE_VAL]) {
+			val->value =
+			    nla_get_u32(attrs[MT753X_ATTR_TYPE_VAL]);
+		}
+	}
+	else
+		goto done;
+
+	return 0;
+done:
+	return NL_SKIP;
+}
+
+static int mt753x_request_callback(int cmd, int (*spilt)(struct nl_msg *, void *),
+				   int (*construct)(struct nl_msg *, void *),
+				   void *arg)
+{
+	struct nl_msg *msg;
+	struct nl_cb *callback = NULL;
+	int finished;
+	int flags = 0;
+	int err;
+
+	/*Allocate an netllink message buffer*/
+	msg = nlmsg_alloc();
+	if (!msg) {
+		fprintf(stderr, "Failed to allocate netlink message\n");
+		exit(1);
+	}
+	if (!construct) {
+		if (cmd == MT753X_CMD_REQUEST)
+			flags |= NLM_F_REQUEST;
+		else
+			flags |= NLM_F_DUMP;
+	}
+	genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, genl_family_get_id(family),
+		    0, flags, cmd, 0);
+
+	/*Fill attaribute of netlink message by construct function*/
+	if (construct) {
+		err = construct(msg, arg);
+		if (err < 0) {
+			fprintf(stderr, "attributes error\n");
+			goto nal_put_failure;
+		}
+	}
+
+	/*Allocate an new callback handler*/
+	callback = nl_cb_alloc(NL_CB_CUSTOM);
+	if (!callback) {
+		fprintf(stderr, "Failed to allocate callback handler\n");
+		exit(1);
+	}
+
+	/*Send netlink message*/
+	err = nl_send_auto_complete(user_sock, msg);
+	if (err < 0) {
+		fprintf(stderr, "nl_send_auto_complete failied:%d\n", err);
+		goto out;
+	}
+	finished = 0;
+	if (spilt)
+		nl_cb_set(callback, NL_CB_VALID, NL_CB_CUSTOM, spilt, arg);
+
+	if (construct)
+		nl_cb_set(callback, NL_CB_ACK, NL_CB_CUSTOM, wait_handler,
+			  &finished);
+	else
+		nl_cb_set(callback, NL_CB_FINISH, NL_CB_CUSTOM, wait_handler,
+			  &finished);
+
+	/*receive message from kernel request*/
+	err = nl_recvmsgs(user_sock, callback);
+	if (err < 0)
+		goto out;
+
+	/*wait until an ACK is received for the latest not yet acknowledge*/
+	if (!finished)
+		err = nl_wait_for_ack(user_sock);
+out:
+	if (callback)
+		nl_cb_put(callback);
+
+nal_put_failure:
+	nlmsg_free(msg);
+	return err;
+}
+
+void mt753x_netlink_free(void)
+{
+	if (family)
+		nl_object_put((struct nl_object *)family);
+	if (cache)
+		nl_cache_free(cache);
+	if (user_sock)
+		nl_socket_free(user_sock);
+	user_sock = NULL;
+	cache = NULL;
+	family = NULL;
+}
+
+int mt753x_netlink_init(const char *name)
+{
+	int ret;
+
+	user_sock = NULL;
+	cache = NULL;
+	family = NULL;
+
+	/*Allocate an new netlink socket*/
+	user_sock = nl_socket_alloc();
+	if (!user_sock) {
+		fprintf(stderr, "Failed to create user socket\n");
+		goto err;
+	}
+	/*Connetct the genl controller*/
+	if (genl_connect(user_sock)) {
+		fprintf(stderr, "Failed to connetct to generic netlink\n");
+		goto err;
+	}
+	/*Allocate an new nl_cache*/
+	ret = genl_ctrl_alloc_cache(user_sock, &cache);
+	if (ret < 0) {
+		fprintf(stderr, "Failed to allocate netlink cache\n");
+		goto err;
+	}
+
+	if (name == NULL)
+		return -EINVAL;
+
+	/*Look up generic netlik family by "mt753x" in the provided cache*/
+	family = genl_ctrl_search_by_name(cache, name);
+	if (!family) {
+		//fprintf(stderr,"switch(mt753x) API not be prepared\n");
+		goto err;
+	}
+	return 0;
+err:
+	mt753x_netlink_free();
+	return -EINVAL;
+}
+
+void mt753x_list_swdev(struct mt753x_attr *arg, int cmd)
+{
+	int err;
+
+	err = mt753x_request_callback(cmd, list_swdevs, NULL, arg);
+	if (err < 0)
+		fprintf(stderr, "mt753x list dev error\n");
+}
+
+static int mt753x_request(struct mt753x_attr *arg, int cmd)
+{
+	int err;
+
+	err = mt753x_request_callback(cmd, spilt_attrs, construct_attrs, arg);
+	if (err < 0) {
+		fprintf(stderr, "mt753x deal request error\n");
+		return err;
+	}
+	return 0;
+}
+
+static int phy_operate_netlink(char op, struct mt753x_attr *arg,
+			       unsigned int port_num, unsigned int phy_dev,
+			       unsigned int offset, unsigned int *value)
+{
+	int ret = 0;
+	struct mt753x_attr *attr = arg;
+
+	attr->port_num = port_num;
+	attr->phy_dev = phy_dev;
+	attr->reg = offset;
+	attr->value = -1;
+	attr->type = MT753X_ATTR_TYPE_REG;
+
+	switch (op)
+	{
+		case 'r':
+			attr->op = 'r';
+			ret = mt753x_request(attr, MT753X_CMD_READ);
+			*value = attr->value;
+			break;
+		case 'w':
+			attr->op = 'w';
+			attr->value = *value;
+			ret = mt753x_request(attr, MT753X_CMD_WRITE);
+			break;
+		default:
+			break;
+	}
+
+	return ret;
+}
+
+int reg_read_netlink(struct mt753x_attr *arg, unsigned int offset,
+		     unsigned int *value)
+{
+	int ret;
+
+	ret = phy_operate_netlink('r', arg, -1, -1, offset, value);
+	return ret;
+}
+
+int reg_write_netlink(struct mt753x_attr *arg, unsigned int offset,
+		      unsigned int value)
+{
+	int ret;
+
+	ret = phy_operate_netlink('w', arg, -1, -1, offset, &value);
+	return ret;
+}
+
+int phy_cl22_read_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			  unsigned int phy_addr, unsigned int *value)
+{
+	int ret;
+
+	ret = phy_operate_netlink('r', arg, port_num, -1, phy_addr, value);
+	return ret;
+}
+
+int phy_cl22_write_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			   unsigned int phy_addr, unsigned int value)
+{
+	int ret;
+
+	ret = phy_operate_netlink('w', arg, port_num, -1, phy_addr, &value);
+	return ret;
+}
+
+int phy_cl45_read_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			  unsigned int phy_dev, unsigned int phy_addr,
+			  unsigned int *value)
+{
+	int ret;
+
+	ret = phy_operate_netlink('r', arg, port_num, phy_dev, phy_addr, value);
+	return ret;
+}
+
+int phy_cl45_write_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			   unsigned int phy_dev, unsigned int phy_addr,
+			   unsigned int value)
+{
+	int ret;
+
+	ret = phy_operate_netlink('w', arg, port_num, phy_dev, phy_addr, &value);
+	return ret;
+}
+
+void dump_extend_phy_reg(struct mt753x_attr *arg, int port_no, int from,
+			int to, int is_local, int page_no)
+{
+        unsigned int temp = 0;
+        int r31 = 0;
+        int i = 0;
+
+        if (is_local == 0) {
+            printf("\n\nGlobal Register Page %d\n",page_no);
+            printf("===============");
+            r31 |= 0 << 15; //global
+            r31 |= ((page_no&0x7) << 12); //page no
+            phy_cl22_write_netlink(arg, port_no, 31, r31); //select global page x
+            for (i = 16; i < 32; i++) {
+                if(i%8 == 0)
+                    printf("\n");
+		phy_cl22_read_netlink(arg, port_no, i, &temp);
+                printf("%02d: %04X ", i, temp);
+            }
+        } else {
+            printf("\n\nLocal Register Port %d Page %d\n",port_no, page_no);
+            printf("===============");
+            r31 |= 1 << 15; //local
+            r31 |= ((page_no&0x7) << 12); //page no
+            phy_cl22_write_netlink(arg, port_no, 31, r31); //select global page x
+            for (i = 16; i < 32; i++) {
+                if (i%8 == 0) {
+                    printf("\n");
+                }
+		phy_cl22_read_netlink(arg, port_no, i, &temp);
+                printf("%02d: %04X ",i, temp);
+            }
+        }
+        printf("\n");
+}
+
+int phy_dump_netlink(struct mt753x_attr *arg, int phy_addr)
+{
+	int i;
+	int ret;
+	unsigned int offset, value;
+
+	if (phy_addr == 32) {
+		/*dump all phy register*/
+		for (i = 0; i < 5; i++) {
+			printf("\n[Port %d]=============", i);
+			for (offset = 0; offset < 16; offset++) {
+				if (offset % 8 == 0)
+					printf("\n");
+				ret = phy_cl22_read_netlink(arg, i, offset, &value);
+				printf("%02d: %04X ", offset, value);
+			}
+		}
+	} else {
+		printf("\n[Port %d]=============", phy_addr);
+		for (offset = 0; offset < 16; offset++) {
+			if (offset % 8 == 0)
+				printf("\n");
+			ret = phy_cl22_read_netlink(arg, phy_addr, offset, &value);
+			printf("%02d: %04X ", offset, value);
+		}
+	}
+	printf("\n");
+	for (offset = 0; offset < 5; offset++) { //global register  page 0~4
+		if (phy_addr == 32) //dump all phy register
+			dump_extend_phy_reg(arg, 0, 16, 31, 0, offset);
+		else
+			dump_extend_phy_reg(arg, phy_addr, 16, 31, 0, offset);
+	}
+
+	if (phy_addr == 32) {	//dump all phy register
+		for (offset = 0; offset < 5; offset++) { //local register port 0-port4
+			dump_extend_phy_reg(arg, offset, 16, 31, 1, 0); //dump local page 0
+			dump_extend_phy_reg(arg, offset, 16, 31, 1, 1); //dump local page 1
+			dump_extend_phy_reg(arg, offset, 16, 31, 1, 2); //dump local page 2
+			dump_extend_phy_reg(arg, offset, 16, 31, 1, 3); //dump local page 3
+		}
+	} else {
+		dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 0); //dump local page 0
+		dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 1); //dump local page 1
+		dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 2); //dump local page 2
+		dump_extend_phy_reg(arg, phy_addr, 16, 31, 1, 3); //dump local page 3
+	}
+	return ret;
+}
diff --git a/feed/switch/src/switch_netlink.h b/feed/switch/src/switch_netlink.h
new file mode 100644
index 0000000..b3f946e
--- /dev/null
+++ b/feed/switch/src/switch_netlink.h
@@ -0,0 +1,70 @@
+/*
+ * switch_netlink.h: switch(netlink) set API
+ * 
+ * Author: Sirui Zhao <Sirui.Zhao@mediatek.com>
+ */
+#ifndef MT753X_NETLINK_H
+#define MT753X_NETLINK_H
+
+#define MT753X_GENL_NAME "mt753x"
+#define MT753X_DSA_GENL_NAME "mt753x_dsa"
+#define MT753X_GENL_VERSION 0X1
+
+/*add your cmd to here*/
+enum {
+	MT753X_CMD_UNSPEC = 0, /*Reserved*/
+	MT753X_CMD_REQUEST,    /*user->kernelrequest/get-response*/
+	MT753X_CMD_REPLY,      /*kernel->user event*/
+	MT753X_CMD_READ,
+	MT753X_CMD_WRITE,
+	__MT753X_CMD_MAX,
+};
+#define MT753X_CMD_MAX (__MT753X_CMD_MAX - 1)
+
+/*define attar types */
+enum
+{
+	MT753X_ATTR_TYPE_UNSPEC = 0,
+	MT753X_ATTR_TYPE_MESG, /*MT753X message*/
+	MT753X_ATTR_TYPE_PHY,
+	MT753X_ATTR_TYPE_PHY_DEV,
+	MT753X_ATTR_TYPE_REG,
+	MT753X_ATTR_TYPE_VAL,
+	MT753X_ATTR_TYPE_DEV_NAME,
+	MT753X_ATTR_TYPE_DEV_ID,
+	__MT753X_ATTR_TYPE_MAX,
+};
+#define MT753X_ATTR_TYPE_MAX (__MT753X_ATTR_TYPE_MAX - 1)
+
+struct mt753x_attr {
+	int port_num;
+	int phy_dev;
+	int reg;
+	int value;
+	int type;
+	char op;
+	char *dev_info;
+	int dev_name;
+	int dev_id;
+};
+
+int mt753x_netlink_init(const char *name);
+void mt753x_netlink_free(void);
+void mt753x_list_swdev(struct mt753x_attr *arg, int cmd);
+int reg_read_netlink(struct mt753x_attr *arg, unsigned int offset,
+		     unsigned int *value);
+int reg_write_netlink(struct mt753x_attr *arg, unsigned int offset,
+		      unsigned int value);
+int phy_cl22_read_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			  unsigned int phy_addr, unsigned int *value);
+int phy_cl22_write_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			   unsigned int phy_addr, unsigned int value);
+int phy_cl45_read_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			  unsigned int phy_dev, unsigned int phy_addr,
+			  unsigned int *value);
+int phy_cl45_write_netlink(struct mt753x_attr *arg, unsigned int port_num,
+			   unsigned int phy_dev, unsigned int phy_addr,
+			   unsigned int value);
+int phy_dump_netlink(struct mt753x_attr *arg, int phy_addr);
+
+#endif