From 9ca5fbcb63a8dcaee0527f96afb91dc4b4bd8fa9 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 22 Nov 2023 01:08:11 +0000
Subject: [PATCH] add ip1811 driver

---
 kernel/drivers/net/ethernet/ip1811/ip1811reg.h             |  231 
 kernel/drivers/net/ethernet/ip1811/ip1811ds.h              |  746 +
 kernel/drivers/net/ethernet/ip1811/ip218.h                 |   29 
 kernel/drivers/net/ethernet/ip1811/ip1811op.h              |  427 +
 kernel/drivers/net/ethernet/ip1811/list.h                  |  517 +
 kernel/drivers/net/ethernet/ip1811/port_config.h           |   16 
 kernel/drivers/net/ethernet/ip1811/zconf.h                 |  506 +
 kernel/drivers/net/ethernet/ip1811/include/types.h         |   17 
 kernel/drivers/net/ethernet/ip1811/libcommon.h             |   53 
 kernel/drivers/net/ethernet/ip1811/Makefile                |    4 
 kernel/drivers/net/ethernet/ip1811/include/port_config.h   |   16 
 kernel/drivers/net/ethernet/ip1811/system_config.h         |   36 
 kernel/drivers/net/ethernet/Makefile                       |    1 
 kernel/drivers/net/ethernet/ip1811/types.h                 |   17 
 kernel/drivers/net/ethernet/ip1811/driver_load             |   29 
 kernel/drivers/net/ethernet/ip1811/include/list.h          |  517 +
 kernel/drivers/net/ethernet/ip1811/ip1811.h                | 1323 +++
 kernel/drivers/net/ethernet/ip1811/include/zconf.h         |  506 +
 kernel/drivers/net/ethernet/ip1811/include/zlib.h          | 1744 ++++
 kernel/drivers/net/ethernet/ip1811/include/Makefile        |    7 
 kernel/drivers/net/ethernet/ip1811/include/system_config.h |   36 
 kernel/drivers/net/ethernet/ip1811/Makefile_               |   50 
 kernel/drivers/net/ethernet/ip1811/ip1811.c                |  482 +
 kernel/drivers/net/ethernet/ip1811/ip1811fdat.c            |  466 +
 kernel/drivers/net/ethernet/ip1811/include/libcommon.h     |   53 
 kernel/drivers/net/ethernet/ip1811/zlib.h                  | 1744 ++++
 kernel/drivers/net/ethernet/ip1811/ip1811fdat.h            |  550 +
 kernel/drivers/net/ethernet/ip1811/ip1811func.c            | 13309 ++++++++++++++++++++++++++++++++++
 28 files changed, 23,432 insertions(+), 0 deletions(-)

diff --git a/kernel/drivers/net/ethernet/Makefile b/kernel/drivers/net/ethernet/Makefile
index b45d5f6..0ae0282 100644
--- a/kernel/drivers/net/ethernet/Makefile
+++ b/kernel/drivers/net/ethernet/Makefile
@@ -95,3 +95,4 @@
 obj-$(CONFIG_NET_VENDOR_XILINX) += xilinx/
 obj-$(CONFIG_NET_VENDOR_XIRCOM) += xircom/
 obj-$(CONFIG_NET_VENDOR_SYNOPSYS) += synopsys/
+obj-y				+= ip1811/
diff --git a/kernel/drivers/net/ethernet/ip1811/Makefile b/kernel/drivers/net/ethernet/ip1811/Makefile
new file mode 100644
index 0000000..c5f76e2
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/Makefile
@@ -0,0 +1,4 @@
+DRIVER_NAME = ip1811drv
+obj-m := $(DRIVER_NAME).o
+$(DRIVER_NAME)-objs := ip1811.o ip1811fdat.o ip1811func.o
+
diff --git a/kernel/drivers/net/ethernet/ip1811/Makefile_ b/kernel/drivers/net/ethernet/ip1811/Makefile_
new file mode 100644
index 0000000..e7bd479
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/Makefile_
@@ -0,0 +1,50 @@
+# Comment/uncomment the following line to disable/enable debugging
+#DEBFLAGS = -g # "-O" is needed to expand inlines
+EXTRA_CFLAGS += $(DEBFLAGS)
+
+# assign extra include path
+INCLUDEPATH	?= -I$(PWD)/../include
+EXTRA_CFLAGS += $(INCLUDEPATH)
+
+# Use MDC/MDIO to access external switch register.
+EXTRA_CFLAGS	+= -DACCESS_REG_BY_MDIO
+
+DRIVER_NAME = ip1811drv
+
+WORK_FN_FILE_SIZE	=$(shell (ls -l $(1) | awk '{print $$5}'))
+PWD	:= $(shell pwd)
+EXE	= $(DRIVER_NAME).ko
+
+KERNELDIR		?= /home/zdb/rk3568/rk356_linux4.19/kernel
+#KERNELDIR		?= ../../build/linux
+
+#CROSS_COMPILE :=mips-linux-
+CROSS_COMPILE := aarch64-linux-gnu-
+
+
+obj-m := $(DRIVER_NAME).o
+$(DRIVER_NAME)-objs := ip1811.o ip1811fdat.o ip1811func.o
+
+.PHONY: all
+all:
+	@echo "EXTRA_CFLGAS=[$(EXTRA_CFLAGS)]"
+	@echo "  Making $@ ..."
+	$(MAKE) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(PWD) modules
+	@make show_size
+	cp *.h $(INC)
+
+
+.PHONY: show_size
+show_size:
+	@echo "Info: generate AP $@ with size = $(call WORK_FN_FILE_SIZE,$(EXE))"
+
+.PHONY: clean
+clean:
+	rm -rf *.o .*.d *~ core .depend .*.cmd *.ko* *.mod.c .tmp_versions modules.order Module.symvers
+
+depend .depend dep:
+	$(CC) $(CFLAGS) -M *.c > .depend
+
+ifeq (.depend,$(wildcard .depend))
+	include .depend
+endif
diff --git a/kernel/drivers/net/ethernet/ip1811/driver_load b/kernel/drivers/net/ethernet/ip1811/driver_load
new file mode 100644
index 0000000..b611408
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/driver_load
@@ -0,0 +1,29 @@
+#!/bin/sh
+module="ip1811"
+mname="ip1811drv"
+device="ip1811_cdev"
+mode="664"
+
+# Group: since distributions do it differently, look for wheel or use staff
+if grep '^staff:' /etc/group > /dev/null; then
+    group="staff"
+else
+    group="wheel"
+fi
+
+# invoke insmod with all arguments we got
+# and use a pathname, as newer modutils don't look in . by default
+#/sbin/insmod -f ./$module.ko $* || exit 1
+insmod $mname.ko
+
+major=`cat /proc/devices | awk "\\$2==\"$device\" {print \\$1}"`
+
+# Remove stale nodes and replace them, then give gid and perms
+# Usually the script is shorter, it's simple that has several devices in it.
+
+#rm -f /dev/${device}[rn]
+mknod /dev/${module} c $major 0
+#mknod /dev/${device}r c $major 0
+#mknod /dev/${device}n c $major 1
+#chgrp $group /dev/${device}[rn] 
+#chmod $mode  /dev/${device}[rn]
diff --git a/kernel/drivers/net/ethernet/ip1811/include/Makefile b/kernel/drivers/net/ethernet/ip1811/include/Makefile
new file mode 100644
index 0000000..b441bc8
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/Makefile
@@ -0,0 +1,7 @@
+
+INCLUDEPATH = $(shell cd ../../linux/include; pwd)
+
+.PHONY: all
+all:
+	@echo "Copying include/*.h ..."
+	cp *.h $(INCLUDEPATH)
diff --git a/kernel/drivers/net/ethernet/ip1811/include/libcommon.h b/kernel/drivers/net/ethernet/ip1811/include/libcommon.h
new file mode 100644
index 0000000..3aaa686
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/libcommon.h
@@ -0,0 +1,53 @@
+#ifndef __LIB_COMMON_H__
+#define __LIB_COMMON_H__
+#include <sys/types.h>//for u_int8_t
+
+#undef OK
+#define OK		0
+
+#undef ERROR
+#define	ERROR	-1
+
+#undef FALSE
+#define FALSE	0
+
+#undef TRUE
+#define TRUE	1
+
+#undef DISABLE
+#define DISABLE	0
+
+#undef ENABLE
+#define ENABLE	1
+
+#define FREE_SAFE(a)	if(a!=NULL){free(a);a=NULL;}
+
+#define	SV_WDT_WDT_TIME	(100)//Unit depends on WORKQUEUE_DELAY_TIME defined in supervisor.c
+
+/************************************************************
+ * Name:	getSysUptime
+ * Description: get system uptime from proc file
+ * Parameters:	None
+ * Return value:failed:		-1
+ *				success:	float type uptime
+ * **********************************************************/
+float getSysUptime(void);
+long getSysUptime_10ms(void);
+void daemonize(void);
+int lock_file(char *filename);
+int unlock_file(int fd, char *filename);
+
+void get_switch_mac(u_int8_t* macaddr);
+void get_switch_ip(u_int8_t *ip);
+void get_switch_netmask(u_int8_t *mask);
+void get_gateway_ip(u_int8_t *ip);
+void get_gateway_ipv6(u_int8_t *ipv6);
+void DER_OID_decoder(unsigned char *input_OID, unsigned int OIDLen, char *outputString);
+char popen_d(char *cmd, char *ret, unsigned int ret_len);
+void printfd(char *file, char *buf);
+char ipStr2Array(char *ip, char *buf);
+int do_fork_execvp(char *argv[]);
+int supervisor_wdt_add(char *command, const char *func_name, int wdt_life_time);
+int supervisor_wdt_del(char *command);
+int supervisor_wdt_reset(char *command);
+#endif//__LIB_COMMON_H__
diff --git a/kernel/drivers/net/ethernet/ip1811/include/list.h b/kernel/drivers/net/ethernet/ip1811/include/list.h
new file mode 100644
index 0000000..0bbafbf
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/list.h
@@ -0,0 +1,517 @@
+/**
+ * 
+ * I grub it from linux kernel source code and fix it for user space
+ * program. Of course, this is a GPL licensed header file.
+ *
+ * Here is a recipe to cook list.h for user space program
+ *
+ * 1. copy list.h from linux/include/list.h
+ * 2. remove 
+ *     - #ifdef __KERNE__ and its #endif
+ *     - all #include line
+ *     - prefetch() and rcu related functions
+ * 3. add macro offsetof() and container_of
+ *
+ * - kazutomo@mcs.anl.gov
+ */
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+#include <stddef.h>
+/**
+ * @name from other kernel headers
+ */
+/*@{*/
+
+/**
+ * Get offset of a member
+ */
+//#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * Casts a member of a structure out to the containing structure
+ * @param ptr        the pointer to the member.
+ * @param type       the type of the container struct this is embedded in.
+ * @param member     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+/*@}*/
+
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1  ((void *) 0x00100100)
+#define LIST_POISON2  ((void *) 0x00200200)
+
+/**
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+
+
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+	return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+				 struct list_head *head)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->next;
+
+	first->prev = head;
+	head->next = first;
+
+	last->next = at;
+	at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+
+#define list_for_each(pos, head) \
+  for (pos = (head)->next; pos != (head);	\
+       pos = pos->next)
+
+/**
+ * __list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev	-	iterate over a list backwards
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+	for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+        	pos = pos->prev)
+
+/**
+ * list_for_each_safe	-	iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry	-	iterate over list of given type
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
+	     &pos->member != (head);					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member)			\
+	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
+	     &pos->member != (head); 	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use as a start point in
+ *			list_for_each_entry_continue
+ * @pos:	the type * to use as a start point
+ * @head:	the head of the list
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_prepare_entry(pos, head, member) \
+	((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue -	iterate over list of given type
+ *			continuing after existing point
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_continue(pos, head, member) 		\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head);	\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue -	iterate over list of given type
+ *			continuing after existing point safe against removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
+		n = list_entry(pos->member.next, typeof(*pos), member);		\
+	     &pos->member != (head);						\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
+ *				      removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
+	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
+		n = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+
+
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+	return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+	return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+	struct hlist_node *next = n->next;
+	struct hlist_node **pprev = n->pprev;
+	*pprev = next;
+	if (next)
+		next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+	__hlist_del(n);
+	n->next = LIST_POISON1;
+	n->pprev = LIST_POISON2;
+}
+
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+	if (n->pprev)  {
+		__hlist_del(n);
+		INIT_HLIST_NODE(n);
+	}
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+	struct hlist_node *first = h->first;
+	n->next = first;
+	if (first)
+		first->pprev = &n->next;
+	h->first = n;
+	n->pprev = &h->first;
+}
+
+
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+					struct hlist_node *next)
+{
+	n->pprev = next->pprev;
+	n->next = next;
+	next->pprev = &n->next;
+	*(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+					struct hlist_node *next)
+{
+	next->next = n->next;
+	n->next = next;
+	next->pprev = &n->next;
+
+	if(next->next)
+		next->next->pprev  = &next->next;
+}
+
+
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+	     pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+	     pos = n)
+
+/**
+ * hlist_for_each_entry	- iterate over list of given type
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member)			 \
+	for (pos = (head)->first;					 \
+	     pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member)		 \
+	for (pos = (pos)->next;						 \
+	     pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member)			 \
+	for (; pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @n:		another &struct hlist_node to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) 		 \
+	for (pos = (head)->first;					 \
+	     pos && ({ n = pos->next; 1; }) && 				 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = n)
+
+
+#endif
diff --git a/kernel/drivers/net/ethernet/ip1811/include/port_config.h b/kernel/drivers/net/ethernet/ip1811/include/port_config.h
new file mode 100644
index 0000000..96e556e
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/port_config.h
@@ -0,0 +1,16 @@
+#ifndef __PORT_CONFIG_H__
+#define __PORT_CONFIG_H__
+#include "portnumber.h"
+
+#define MAX_PORT_NUM		get_MaxPort()
+#define GIGA_PORT_START		get_GPStart()
+#define GIGA_PORT_END		get_GPEnd()
+
+#define MAX_IPORT_CNT		SWITCH_MAX_IPORT_CNT
+#define	ALL_PORTS_LIST		(~(-1 << MAX_PORT_NUM))
+#define	GIGA_PORT_NUM		(GIGA_PORT_END - GIGA_PORT_START)
+#define CPU_PORT_NUM		MAX_IPORT_CNT
+#define MAX_TP_PORT_NUM		(GIGA_PORT_START -1)
+
+#endif
+
diff --git a/kernel/drivers/net/ethernet/ip1811/include/system_config.h b/kernel/drivers/net/ethernet/ip1811/include/system_config.h
new file mode 100644
index 0000000..b80d6f5
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/system_config.h
@@ -0,0 +1,36 @@
+
+#ifndef __SYSTEM_CONFIG_H__
+#define __SYSTEM_CONFIG_H__
+///////////////////////////////////////////////
+//// board config
+///////////////////////////////////////////////
+
+//#define SYSTEM_CONFIG__FPGA
+//#define SYSTEM_CONFIG__ASIC//this is ASIC_135
+//#define SYSTEM_CONFIG__ASIC125
+//#define SYSTEM_CONFIG__ASIC_135
+#define SYSTEM_CONFIG__ASIC_150
+
+
+#define SYSTEM_CONFIG__SERVER_MODE
+//#define SYSTEM_CONFIG__PCI_MODE
+
+
+///////////////////////////////////////////////
+//// DRAM parameter - ref: sdram_support_list
+///////////////////////////////////////////////
+
+#define SYSTEM_CONFIG_DRAM__ARCH_4CH
+//#define SYSTEM_CONFIG_DRAM__USED_2CHIPS
+//#define SYSTEM_CONFIG_FLASH__USED_2CHIPS
+
+//#define SYSTEM_CONFIG_DRAM__NT5SV16M16CS_6K
+//#define SYSTEM_CONFIG_DRAM__PMS308416BTR_6
+//#define SYSTEM_CONFIG_DRAM__IS42S16320D
+#define SYSTEM_CONFIG_DRAM__W9825G6KH_6I
+//#define SYSTEM_CONFIG_DRAM__A3V56S30
+
+//#define SYS_CONFIG_WITH_IP102_PHY
+
+#endif
+
diff --git a/kernel/drivers/net/ethernet/ip1811/include/types.h b/kernel/drivers/net/ethernet/ip1811/include/types.h
new file mode 100644
index 0000000..bfcfab4
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/types.h
@@ -0,0 +1,17 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+typedef unsigned char		u8;
+typedef unsigned short		u16;
+typedef unsigned int		u32;
+typedef unsigned long long	u64;
+typedef char				s8;
+typedef short				s16;
+typedef int					s32;
+typedef long long			s64;
+
+#define BIT(x)	(1UL<<(x))
+
+#define err (-1)
+
+#endif
diff --git a/kernel/drivers/net/ethernet/ip1811/include/zconf.h b/kernel/drivers/net/ethernet/ip1811/include/zconf.h
new file mode 100644
index 0000000..8912fe6
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/zconf.h
@@ -0,0 +1,506 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2012 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#  endif
+#  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+/* ./configure may #define Z_U4 here */
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  else
+#    if (ULONG_MAX == 0xffffffffUL)
+#      define Z_U4 unsigned long
+#    else
+#      if (USHRT_MAX == 0xffffffffUL)
+#        define Z_U4 unsigned short
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#if 1    /* was set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#if 1    /* was set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  include <stddef.h>           /* for wchar_t */
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/include/zlib.h b/kernel/drivers/net/ethernet/ip1811/include/zlib.h
new file mode 100644
index 0000000..3edf3ac
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/include/zlib.h
@@ -0,0 +1,1744 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.7, May 2nd, 2012
+
+  Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.7"
+#define ZLIB_VERNUM 0x1270
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 7
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip streams in memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    z_const Bytef *next_in;     /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total number of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total number of bytes output so far */
+
+    z_const char *msg;  /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use in the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).  Some
+    output may be provided even if flush is not set.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed code
+  block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error.  After
+  deflate has returned Z_STREAM_END, the only possible operations on the stream
+  are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step.  In this case, avail_out must be at least the
+  value returned by deflateBound (see below).  Then deflate is guaranteed to
+  return Z_STREAM_END.  If not enough output space is provided, deflate will
+  not return Z_STREAM_END, and it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
+  binary.  This field is only for information purposes and does not affect the
+  compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
+   exact value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit() does not process any header information -- that is deferred
+   until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing will
+    resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.) The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained, so applications that need that information should
+  instead use raw inflate, see inflateInit2() below, or inflateBack() and
+  perform their own processing of the gzip header and trailer.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  producted so far.  The CRC-32 is checked against the gzip trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent.  In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.  The
+   stream will keep the same compression level and any other attributes that
+   may have been set by deflateInit2.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression level is changed, the input available so far is
+   compressed with the old level (and may be flushed); the new level will take
+   effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to be
+   compressed and flushed.  In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+   strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above or -1 << 16 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the normal
+   behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.) Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed buffer.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
+*/
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Two buffers are allocated, either both of the specified size when
+   writing, or one of the specified size and the other twice that size when
+   reading.  A larger buffer size of, for example, 64K or 128K bytes will
+   noticeably increase the speed of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.
+
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or 0 in case of error.  The number of
+   uncompressed bytes written is limited to 8191, or one less than the buffer
+   size given to gzbuffer().  The caller should assure that this limit is not
+   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
+   nothing written.  In this case, there may also be a buffer overflow with
+   unpredictable consequences, which is possible only if zlib was compiled with
+   the insecure functions sprintf() or vsprintf() because the secure snprintf()
+   or vsnprintf() functions were not available.  This can be determined using
+   zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatented gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                      (int)sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+                      ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+#  define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    define gzopen gzopen64
+#    define gzseek gzseek64
+#    define gztell gztell64
+#    define gzoffset gzoffset64
+#    define adler32_combine adler32_combine64
+#    define crc32_combine crc32_combine64
+#  endif
+#  ifndef Z_LARGE64
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811.c b/kernel/drivers/net/ethernet/ip1811/ip1811.c
new file mode 100644
index 0000000..df75aa6
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811.c
@@ -0,0 +1,482 @@
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+
+#include "ip1811.h"
+#include "ip1811fdat.h"
+
+static struct cdev ip1811_cdev;
+struct class *ip1811_class;
+static DEFINE_MUTEX(ip1811_mutex);
+u8 CPU_IF_SPEED_NORMAL;
+
+#define	IP1811_MAJOR	248
+#define IP1811_NAME	"ip1811_cdev"
+
+//#define IP1811DEBUG
+
+MODULE_LICENSE ("GPL");
+
+static int ip1811_open(struct inode *inode, struct file *fs)
+{
+#ifdef IP1811DEBUG
+	printk("ip1811: open...\n");
+#endif
+	try_module_get(THIS_MODULE);
+
+	return 0;
+}
+
+static int ip1811_release(struct inode *inode, struct file *file)
+{
+	module_put(THIS_MODULE);
+#ifdef IP1811DEBUG
+	printk("ip1811: release!\n");
+#endif
+	return 0;
+}
+
+static ssize_t ip1811_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset)
+{
+	//  	return simple_read_from_buffer(buffer, length, offset, msg, 200);
+	return 0;
+}
+
+static ssize_t ip1811_write(struct file *filp, const char __user *buff, size_t len, loff_t *off)
+{
+	/*	if (len > 199)
+		return -EINVAL;
+		copy_from_user(msg, buff, len);
+		msg[len] = '\0';
+		return len;*/
+	return 0;
+}
+
+static int ip1811_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	unsigned long len, cmdid, fno, fsubg, fgrp, fusg;
+	void *cptr;
+	char *cdata, *cmptr;
+	int offset_t;
+
+#ifdef IP1811DEBUG
+	printk(KERN_ALERT "ip1811: +ioctl...\n");
+#endif
+	len = (int)(_IOC_SIZE(cmd));
+	cptr = (void *)arg;
+	offset_t = sizeof(void*) + sizeof(unsigned long);
+
+	do {
+		cdata = kmalloc(len, GFP_KERNEL);
+		cmptr=cdata;
+
+		if (!cdata)
+		{
+			printk(KERN_ERR "cdata==NULL");
+			ret = -ENOMEM;
+			goto out_ip1811_ioctl;
+		}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
+		if(access_ok(VERIFY_READ, cptr, len)){
+#else
+		if(access_ok(cptr, len)){
+#endif
+			if(copy_from_user(cdata, cptr, len)){
+				printk(KERN_ERR "copy_from_user fail. len:%ld",(unsigned long)len);
+				ret=-EFAULT;
+				goto out_ip1811_ioctl;
+			}
+		}
+		else{
+			printk(KERN_ERR "[switchDriver] copy_from_user access fail by %s:%d CMD:%x\n",__FUNCTION__,__LINE__,cmd);
+			ret = -EFAULT;
+			goto out_ip1811_ioctl;
+		}
+		if(cmptr!=cdata){
+			printk(KERN_ERR "cdata error org: %p, after: %p", cmptr, cdata);
+		}
+		cmdid = *((unsigned long *)(cdata+offset_t));
+		fno = (cmdid >> _CMDID_NRSHIFT) & _CMDID_NRMASK;
+		fsubg=(cmdid >> _CMDID_SUBGSHIFT) & _CMDID_SUBGMASK;
+		fgrp= (cmdid >> _CMDID_GRPSHIFT) & _CMDID_GRPMASK;
+		fusg= (cmdid >> _CMDID_USGSHIFT) & _CMDID_USGMASK;
+#ifdef IP1811DEBUG
+		printk(KERN_ALERT "cmdid=0x%08x\n", (unsigned int)cmdid);
+#endif
+
+		if (fusg == _CMDID_USG_COMMON)
+		{
+			switch (fgrp)
+			{
+				case _CMDID_GRP_BASIC:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_SMI:
+							ret = func_of_common_smi[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_CAP:
+							ret = func_of_common_cap[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_LUT:
+							ret = func_of_common_lut[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_SNIFFER:
+							ret = func_of_common_sniffer[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_STORM:
+							ret = func_of_common_storm[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_EOC:
+							ret = func_of_common_eoc[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_LD:
+							ret = func_of_common_ld[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_WOL:
+							ret = func_of_common_wol[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_STAG:
+							ret = func_of_common_stag[fno](cdata, len);	break;
+
+						case _CMDID_SUB_BANDWIDTH:
+							ret = func_of_common_bandwidth[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_MISC:
+							ret = func_of_common_misc[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_VLAN:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_VLAN:
+							ret = func_of_common_vlan[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_QOS:
+					switch (fsubg)
+					{
+						case _CMDID_SUB_BANDWIDTH:
+							ret = func_of_common_bandwidth[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_SEC:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_IMP:
+							ret = func_of_common_imp[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_COS:
+							ret = func_of_common_cos[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_ADV:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_STP:
+							ret = func_of_common_stp[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_LACP:
+							ret = func_of_common_lacp[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				default:
+					ret = -EINVAL;
+			}
+		}
+		else if (fusg == _CMDID_USG_IP1811)
+		{
+			switch (fgrp)
+			{
+				case _CMDID_GRP_BASIC:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_CAP:
+							ret = func_of_common_cap[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_LUT:
+							ret = func_of_ip1811_lut[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_SNIFFER:
+							ret = func_of_ip1811_sniffer[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_STORM:
+							ret = func_of_ip1811_storm[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_EOC:
+							ret = func_of_ip1811_eoc[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_LD:
+							ret = func_of_ip1811_ld[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_WOL:
+							ret = func_of_ip1811_wol[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_IGMP:
+							ret = func_of_ip1811_igmp[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_PTP:
+							ret = func_of_ip1811_ptp[fno](cdata, len); break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_VLAN:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_VLAN:
+							ret = func_of_ip1811_vlan[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+				case _CMDID_GRP_QOS:
+					switch (fsubg)
+					{
+						case _CMDID_SUB_QOS:
+							ret = func_of_ip1811_qos[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+				case _CMDID_GRP_ACL:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_ACL:
+							ret = func_of_ip1811_acl[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_SEC:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_IMP:
+							ret = func_of_ip1811_imp[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_ADV:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_STP:
+							ret = func_of_ip1811_stp[fno](cdata, len);	break;
+
+						case _CMDID_SUBG_LACP:
+							ret = func_of_ip1811_lacp[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+				case _CMDID_GRP_MON:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_MIB_COUNTER:
+							ret = func_of_ip1811_mib_counter[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				case _CMDID_GRP_HSR:
+					switch (fsubg)
+					{
+						case _CMDID_SUBG_HSR:
+							ret = func_of_ip1811_hsr[fno](cdata, len);	break;
+
+						default:
+							ret = -EINVAL;
+					}
+					break;
+
+				default:
+					ret = -EINVAL;
+			}
+		}
+		else
+			ret = -EINVAL;
+
+		if (ret < 0)	goto out_ip1811_ioctl;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0)
+		if(access_ok(WERIFY_WRITE, cptr, len)){
+#else
+		if(access_ok(cptr, len)){
+#endif
+			if (copy_to_user(cptr, cdata, len))	{
+				printk(KERN_ERR "copy_touser fail.");
+				ret = -EFAULT;
+				goto out_ip1811_ioctl;
+			}
+		}
+		else{
+			printk(KERN_ERR "[switchDriver] copy_from_user access fail by %s:%d CMD:%x\n",__FUNCTION__,__LINE__,cmd);
+			ret=-EFAULT;
+			goto out_ip1811_ioctl;
+		}
+		cptr= (void *)*((unsigned long *)cdata);
+		len = *((unsigned long *)(cdata+4));
+
+		kfree(cdata);
+		cdata = NULL;
+	} while (cptr);
+out_ip1811_ioctl:
+	if(cdata)
+	{
+		//memset(cdata, 0x0, len);
+		kfree(cdata);
+	}
+#ifdef IP1811DEBUG
+	printk(KERN_ALERT "ip1811: -ioctl...\n");
+#endif
+	return (ret < 0) ? ret : 0;
+}
+
+static void lock_key_ioctl(void)
+{
+	mutex_lock(&ip1811_mutex);
+}
+
+static void unlock_key_ioctl(void)
+{
+	mutex_unlock(&ip1811_mutex);
+}
+
+static long ip1811_unlocked_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+
+	lock_key_ioctl();
+	ret = ip1811_ioctl(filep, cmd, arg);
+	unlock_key_ioctl();
+
+	return ret;
+}
+
+static struct file_operations ip1811_fops = {
+	.owner			= THIS_MODULE,
+	.read			= ip1811_read,
+	.write			= ip1811_write,
+	.unlocked_ioctl	= ip1811_unlocked_ioctl,
+	.open			= ip1811_open,
+	.release		= ip1811_release
+};
+
+extern u16 Read_Reg(u8 regaddr);
+extern void Write_Reg(u8 regaddr, u16 value);
+extern void IP2Page(u8 page);
+extern u16 Read_Reg_0_With_1s(void);
+
+/* ==================================================================================== */
+
+static int __init ip1811_init(void)
+{
+	int result;
+
+	result = register_chrdev_region(MKDEV(IP1811_MAJOR, 0), 1, IP1811_NAME);
+	if (result < 0)
+	{
+		printk(KERN_WARNING "ip1811: can't get major %d\n", IP1811_MAJOR);
+		return result;
+	}
+
+	cdev_init(&ip1811_cdev, &ip1811_fops);
+	ip1811_cdev.owner = THIS_MODULE;
+	result = cdev_add(&ip1811_cdev, MKDEV(IP1811_MAJOR, 0), 1);
+	if (result)
+	{
+		printk(KERN_WARNING "ip1811: error %d adding driver\n", result);
+		return result;
+	}
+
+	CPU_IF_SPEED_NORMAL = 0; //set to normal speed initially
+
+	IP2Page(0);
+	if( (Read_Reg_0_With_1s() & 0xFFF0) == 0x8120 )
+	{
+		printk("ip1811: CPU I/F High speed.");
+	}
+	else
+	{
+		CPU_IF_SPEED_NORMAL = 1;
+		printk("ip1811: CPU I/F Normal speed.");
+	}
+	
+	// for acl_man init.
+	acl_init();
+
+	printk(" Driver loaded!\n");
+	return 0;
+	/*
+fail_return:
+	if(ip1811_cdev){
+		cdev_del(ip1811_cdev);
+		kfree(ip1811_cdev);
+		ip1811_cdev=NULL;
+	}
+	if(devno)
+		unregister_chrdev_region(devno, 1);
+	if(ip1811_class)
+		class_destroy(ip1811_class);
+	return -1;
+	*/
+}
+
+static void __exit ip1811_exit(void)
+{
+	/*
+	if(ip1811_cdev){
+		cdev_del(ip1811_cdev);
+		kfree(ip1811_cdev);
+		ip1811_cdev=NULL;
+	}
+	if(devno)
+		unregister_chrdev_region(devno, 1);
+	if(ip1811_class)
+		class_destroy(ip1811_class);
+	*/
+	cdev_del(&ip1811_cdev);
+	unregister_chrdev_region(MKDEV(IP1811_MAJOR, 0), 1);
+	printk("ip1811: Driver unloaded!\n");
+}
+
+module_init(ip1811_init);
+module_exit(ip1811_exit);
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811.h b/kernel/drivers/net/ethernet/ip1811/ip1811.h
new file mode 100644
index 0000000..0774d60
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811.h
@@ -0,0 +1,1323 @@
+#ifndef IP1811_H
+#define IP1811_H
+
+/*===================================================================*/
+/* max port number of this switch */
+#define	MAX_PHY_NUM			(12)
+/* port-list mask */
+#define	ALL_PHY_PORTS_LIST	(~(-1 << (MAX_PHY_NUM - 1)))
+/* max port number of TP port */
+#define MAX_PHY_TP_NUM	(8)
+
+/* max number of fid */
+#define	MAX_FID_NUM			(16)
+/* max LUT table block number */
+#define	MAX_BLOCK_NUM		(1)
+/* max LUT table entry number */
+#define MAX_LUT_ENTRY_NUM	(4096)
+/* LUT table aging time unit(millisecond) */
+#define	AGING_TIME_UNIT		(550)
+
+/* max IP-Mac-Port table entry number */
+#define MAX_IMP_ENTRY_NUM	(128)
+
+/* max PVID number */
+#define MAX_PVID_NUM		(4096)
+/* mac Protocol Based VLAN entry number */
+#define MAX_PRO_VLAN_ENTRY_NUM	(4)
+
+/* max link speed of TP port */
+#define MAX_TP_SPEED (100000000)
+/* max link speed of Giga port */
+#define MAX_GIGA_SPEED (1000000000)
+
+/*===================================================================*/
+#define TYPECHECK(t)		(sizeof(t))
+
+#define _CMDID_NRBITS		8
+#define _CMDID_SUBGBITS		4
+#define _CMDID_RSVD1BITS	4
+#define _CMDID_GRPBITS		8
+#define _CMDID_USGBITS		4
+
+#define _CMDID_NRMASK		((1 << _CMDID_NRBITS)-1)
+#define _CMDID_SUBGMASK		((1 << _CMDID_SUBGBITS)-1)
+#define _CMDID_GRPMASK		((1 << _CMDID_GRPBITS)-1)
+#define _CMDID_USGMASK		((1 << _CMDID_USGBITS)-1)
+
+#define _CMDID_NRSHIFT		0
+#define _CMDID_SUBGSHIFT	(_CMDID_NRSHIFT+_CMDID_NRBITS)
+#define _CMDID_GRPSHIFT		(_CMDID_SUBGSHIFT+_CMDID_SUBGBITS+_CMDID_RSVD1BITS)
+#define _CMDID_USGSHIFT		(_CMDID_GRPSHIFT+_CMDID_GRPBITS)
+
+#define MAKECMDID(usg, grp, subg, nr)	( (usg << _CMDID_USGSHIFT) | (grp << _CMDID_GRPSHIFT) | \
+					(subg << _CMDID_SUBGSHIFT) | (nr << _CMDID_NRSHIFT) )
+
+#define _CMDID_USG_COMMON	0x0
+#define _CMDID_USG_IP1811	0x1
+#define _CMDID_USG_DBS		0x2
+#define NUM_CMDID_USG		0x3
+
+/*===================================================================*/
+#define _CMDID_GRP_BASIC	0x01
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_SMI		0x1
+enum{
+	 IDX_COMMON_SET_PORT_AN,	//0
+	 IDX_COMMON_GET_PORT_AN,
+	 IDX_COMMON_SET_PORT_SPEED,
+	 IDX_COMMON_GET_PORT_SPEED,
+	 IDX_COMMON_SET_PORT_DUPLEX,
+	 IDX_COMMON_GET_PORT_DUPLEX,
+	 IDX_COMMON_SET_PORT_PAUSE,
+	 IDX_COMMON_GET_PORT_PAUSE,
+	 IDX_COMMON_SET_PORT_ASYM_PAUSE,
+	 IDX_COMMON_GET_PORT_ASYM_PAUSE,
+	 IDX_COMMON_SET_PORT_LINK_STATUS,	//10
+	 IDX_COMMON_GET_PORT_LINK_STATUS,
+	 IDX_COMMON_SET_PORT_BACKPRESSURE,
+	 IDX_COMMON_GET_PORT_BACKPRESSURE,
+	 IDX_COMMON_SET_PORT_POWER_DOWN,
+	 IDX_COMMON_GET_PORT_POWER_DOWN,
+	 IDX_COMMON_SET_PORT_FORCE_LINK,
+	 IDX_COMMON_GET_PORT_FORCE_LINK,
+	 IDX_COMMON_SET_PORT_UNI_DIRECTION,
+	 IDX_COMMON_GET_PORT_UNI_DIRECTION,
+	 IDX_COMMON_SET_MDIO_DIV,		//20
+	 IDX_COMMON_SET_FALSE_LINK_SOLUTION,
+	 NUM_COMMON_SMI		//22
+};
+
+#define ID_COMMON_SMI(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_SMI, idx)
+
+#define ID_COMMON_SET_PORT_AN \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_AN)
+#define ID_COMMON_GET_PORT_AN \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_AN)
+#define ID_COMMON_SET_PORT_SPEED \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_SPEED)
+#define ID_COMMON_GET_PORT_SPEED \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_SPEED)
+#define ID_COMMON_SET_PORT_DUPLEX \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_DUPLEX)
+#define ID_COMMON_GET_PORT_DUPLEX \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_DUPLEX)
+#define ID_COMMON_SET_PORT_PAUSE \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_PAUSE)
+#define ID_COMMON_GET_PORT_PAUSE \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_PAUSE)
+#define ID_COMMON_SET_PORT_ASYM_PAUSE \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_ASYM_PAUSE)
+#define ID_COMMON_GET_PORT_ASYM_PAUSE \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_ASYM_PAUSE)
+#define ID_COMMON_SET_PORT_LINK_STATUS \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_LINK_STATUS)
+#define ID_COMMON_GET_PORT_LINK_STATUS \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_LINK_STATUS)
+#define ID_COMMON_SET_PORT_BACKPRESSURE \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_BACKPRESSURE)
+#define ID_COMMON_GET_PORT_BACKPRESSURE \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_BACKPRESSURE)
+#define ID_COMMON_SET_PORT_POWER_DOWN \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_POWER_DOWN)
+#define ID_COMMON_GET_PORT_POWER_DOWN \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_POWER_DOWN)
+#define ID_COMMON_SET_PORT_FORCE_LINK \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_FORCE_LINK)
+#define ID_COMMON_GET_PORT_FORCE_LINK \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_FORCE_LINK)
+#define ID_COMMON_SET_PORT_UNI_DIRECTION \
+	ID_COMMON_SMI(IDX_COMMON_SET_PORT_UNI_DIRECTION)
+#define ID_COMMON_GET_PORT_UNI_DIRECTION \
+	ID_COMMON_SMI(IDX_COMMON_GET_PORT_UNI_DIRECTION)
+#define ID_COMMON_SET_MDIO_DIV \
+	ID_COMMON_SMI(IDX_COMMON_SET_MDIO_DIV)
+#define ID_COMMON_SET_FALSE_LINK_SOLUTION\
+	ID_COMMON_SMI(IDX_COMMON_SET_FALSE_LINK_SOLUTION)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_CAP		0x2
+enum{
+	IDX_COMMON_L2_SET_CAP_ACT,
+	IDX_COMMON_CAP_SET_IN_BAND,
+	IDX_COMMON_CAP_SET_SWITCH_MAC,
+	IDX_COMMON_CAP_SET_IPV6_TCPUDP_ENABLE,
+	NUM_COMMON_CAP
+};
+
+#define ID_COMMON_CAP(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_CAP, idx)
+
+#define	ID_COMMON_L2_SET_CAP_ACT \
+	ID_COMMON_CAP(IDX_COMMON_L2_SET_CAP_ACT)
+
+#define	ID_COMMON_CAP_SET_IN_BAND \
+	ID_COMMON_CAP(IDX_COMMON_CAP_SET_IN_BAND)
+
+#define	ID_COMMON_CAP_SET_SWITCH_MAC \
+	ID_COMMON_CAP(IDX_COMMON_CAP_SET_SWITCH_MAC)
+
+#define	ID_COMMON_CAP_SET_IPV6_TCPUDP_ENABLE \
+	ID_COMMON_CAP(IDX_COMMON_CAP_SET_IPV6_TCPUDP_ENABLE)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_LUT		0x3
+
+enum{
+	IDX_COMMON_SET_SMAC_LEARNING,		//0
+	IDX_COMMON_GET_SMAC_LEARNING,
+	IDX_COMMON_LUT_SET_PORT_FLUSH,
+	IDX_COMMON_SET_LUT_AGING_TIME,
+	IDX_COMMON_GET_LUT_AGING_TIME,
+	IDX_COMMON_SET_LUT_AGING_TIME_ENABLE,
+	IDX_COMMON_SET_LUT_LEARN_NSA,
+	IDX_COMMON_SET_LUT_HASHING_ALGORITHM,
+	IDX_COMMON_SET_LUT_BINDING_ENABLE,
+	IDX_COMMON_GET_LUT_BINDING_ENABLE,
+	NUM_COMMON_LUT
+};
+
+#define ID_COMMON_LUT(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_LUT, idx)
+
+#define	ID_COMMON_SET_SMAC_LEARNING \
+	ID_COMMON_LUT(IDX_COMMON_SET_SMAC_LEARNING)
+#define	ID_COMMON_GET_SMAC_LEARNING\
+	ID_COMMON_LUT(IDX_COMMON_GET_SMAC_LEARNING)
+#define	ID_COMMON_LUT_SET_PORT_FLUSH\
+	ID_COMMON_LUT(IDX_COMMON_LUT_SET_PORT_FLUSH)
+#define	ID_COMMON_SET_LUT_AGING_TIME\
+	ID_COMMON_LUT(IDX_COMMON_SET_LUT_AGING_TIME)
+#define	ID_COMMON_GET_LUT_AGING_TIME\
+	ID_COMMON_LUT(IDX_COMMON_GET_LUT_AGING_TIME)
+#define	ID_COMMON_SET_LUT_AGING_TIME_ENABLE\
+	ID_COMMON_LUT(IDX_COMMON_SET_LUT_AGING_TIME_ENABLE)
+#define	ID_COMMON_SET_LUT_LEARN_NSA \
+	ID_COMMON_LUT(IDX_COMMON_SET_LUT_LEARN_NSA)
+#define	ID_COMMON_SET_LUT_HASHING_ALGORITHM \
+	ID_COMMON_LUT(IDX_COMMON_SET_LUT_HASHING_ALGORITHM)
+#define	ID_COMMON_SET_LUT_BINDING_ENABLE \
+	ID_COMMON_LUT(IDX_COMMON_SET_LUT_BINDING_ENABLE)
+#define	ID_COMMON_GET_LUT_BINDING_ENABLE\
+	ID_COMMON_LUT(IDX_COMMON_GET_LUT_BINDING_ENABLE)
+
+enum{
+	IDX_1811_LUT_SET_UNKNOWN_SA_RULE,
+	IDX_1811_LUT_SET_ENTRY,
+	IDX_1811_LUT_GET_ENTRY,
+	IDX_1811_LUT_GET_VALID_ENTRY,
+	NUM_1811_LUT
+};
+
+#define ID_1811_LUT(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_LUT, idx)
+
+#define	ID_1811_LUT_SET_UNKNOWN_SA_RULE \
+	ID_1811_LUT(IDX_1811_LUT_SET_UNKNOWN_SA_RULE)
+#define	ID_1811_LUT_SET_ENTRY\
+	ID_1811_LUT(IDX_1811_LUT_SET_ENTRY)
+#define	ID_1811_LUT_GET_ENTRY\
+	ID_1811_LUT(IDX_1811_LUT_GET_ENTRY)
+#define	ID_1811_LUT_GET_VALID_ENTRY\
+	ID_1811_LUT(IDX_1811_LUT_GET_VALID_ENTRY)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_SNIFFER	0x4
+
+enum{
+	IDX_COMMON_SET_SNIFFER_SOURCE,
+	IDX_COMMON_GET_SNIFFER_SOURCE,
+	IDX_COMMON_SET_SNIFFER_DEST_GRP1,
+	IDX_COMMON_GET_SNIFFER_DEST_GRP1,
+	IDX_COMMON_SNIFFER1_SET_METHOD,
+	IDX_COMMON_SNIFFER1_GET_METHOD,
+	NUM_COMMON_SNIFFER
+};
+#define ID_COMMON_SNIFFER(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_SNIFFER, idx)
+
+#define ID_COMMON_SET_SNIFFER_SOURCE \
+	ID_COMMON_SNIFFER(IDX_COMMON_SET_SNIFFER_SOURCE)
+#define ID_COMMON_GET_SNIFFER_SOURCE \
+	ID_COMMON_SNIFFER(IDX_COMMON_GET_SNIFFER_SOURCE)
+#define ID_COMMON_SET_SNIFFER_DEST_GRP1 \
+	ID_COMMON_SNIFFER(IDX_COMMON_SET_SNIFFER_DEST_GRP1)
+#define ID_COMMON_GET_SNIFFER_DEST_GRP1 \
+	ID_COMMON_SNIFFER(IDX_COMMON_GET_SNIFFER_DEST_GRP1)
+#define ID_COMMON_SNIFFER1_SET_METHOD \
+	ID_COMMON_SNIFFER(IDX_COMMON_SNIFFER1_SET_METHOD)
+#define ID_COMMON_SNIFFER1_GET_METHOD \
+	ID_COMMON_SNIFFER(IDX_COMMON_SNIFFER1_GET_METHOD)
+
+enum{
+	IDX_1811_SNIFFER1_SET_PKT_MODIFY,
+	IDX_1811_SNIFFER1_GET_PKT_MODIFY,
+	IDX_1811_SNIFFER1_SET_TAG_MODIFY_FOR_CPU_STAG,
+	IDX_1811_SNIFFER1_GET_TAG_MODIFY_FOR_CPU_STAG,
+	IDX_1811_SNIFFER1_SET_TAG_MODIFY_FOR_ACL_REDIR_2CPU,
+	IDX_1811_SNIFFER1_GET_TAG_MODIFY_FOR_ACL_REDIR_2CPU,
+	IDX_1811_SNIFFER1_SET_TAG_MODIFY_FOR_PKT_2MIRROR_PORT,
+	IDX_1811_SNIFFER1_GET_TAG_MODIFY_FOR_PKT_2MIRROR_PORT,
+	IDX_1811_SNIFFER2_SET_LUT_TRIGGER_TARGET_FOR_GRP1,
+	IDX_1811_SNIFFER2_GET_LUT_TRIGGER_TARGET_FOR_GRP1,
+	NUM_1811_SNIFFER
+};
+#define ID_1811_SNIFFER(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_SNIFFER, idx)
+
+#define ID_1811_SNIFFER1_SET_PKT_MODIFY \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_SET_PKT_MODIFY)
+#define ID_1811_SNIFFER1_GET_PKT_MODIFY \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_GET_PKT_MODIFY)
+#define ID_1811_SNIFFER1_SET_TAG_MODIFY_FOR_CPU_STAG \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_SET_TAG_MODIFY_FOR_CPU_STAG)
+#define ID_1811_SNIFFER1_GET_TAG_MODIFY_FOR_CPU_STAG \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_GET_TAG_MODIFY_FOR_CPU_STAG)
+#define ID_1811_SNIFFER1_SET_TAG_MODIFY_FOR_ACL_REDIR_2CPU \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_SET_TAG_MODIFY_FOR_ACL_REDIR_2CPU)
+#define ID_1811_SNIFFER1_GET_TAG_MODIFY_FOR_ACL_REDIR_2CPU \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_GET_TAG_MODIFY_FOR_ACL_REDIR_2CPU)
+#define ID_1811_SNIFFER1_SET_TAG_MODIFY_FOR_PKT_2MIRROR_PORT \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_SET_TAG_MODIFY_FOR_PKT_2MIRROR_PORT)
+#define ID_1811_SNIFFER1_GET_TAG_MODIFY_FOR_PKT_2MIRROR_PORT \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER1_GET_TAG_MODIFY_FOR_PKT_2MIRROR_PORT)
+#define ID_1811_SNIFFER2_SET_LUT_TRIGGER_TARGET_FOR_GRP1 \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER2_SET_LUT_TRIGGER_TARGET_FOR_GRP1)
+#define ID_1811_SNIFFER2_GET_LUT_TRIGGER_TARGET_FOR_GRP1 \
+	ID_1811_SNIFFER(IDX_1811_SNIFFER2_GET_LUT_TRIGGER_TARGET_FOR_GRP1)
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_STORM	0x5
+
+enum{
+	IDX_COMMON_STORM_CTRL_SET_FUNC,
+	IDX_COMMON_STORM_CTRL_GET_FUNC,
+	IDX_COMMON_STORM_CTRL_SET_THRESHOLD,
+	IDX_COMMON_STORM_CTRL_GET_THRESHOLD,
+	IDX_COMMON_STORM_SET_COUNTER_CLR_PERIOD,
+	IDX_COMMON_STORM_GET_COUNTER_CLR_PERIOD,
+	IDX_COMMON_STORM_SET_BLOCK_FRAME_2CPU,
+	IDX_COMMON_STORM_GET_BLOCK_FRAME_2CPU,
+	IDX_COMMON_STORM_SET_DROP_INTERRUPT,
+	IDX_COMMON_STORM_GET_DROP_INTERRUPT,
+	NUM_COMMON_STORM
+};
+#define ID_COMMON_STORM(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_STORM, idx)
+
+#define ID_COMMON_STORM_CTRL_SET_FUNC \
+	ID_COMMON_STORM(IDX_COMMON_STORM_CTRL_SET_FUNC)
+#define ID_COMMON_STORM_CTRL_GET_FUNC \
+	ID_COMMON_STORM(IDX_COMMON_STORM_CTRL_GET_FUNC)
+#define ID_COMMON_STORM_CTRL_SET_THRESHOLD \
+	ID_COMMON_STORM(IDX_COMMON_STORM_CTRL_SET_THRESHOLD)
+#define ID_COMMON_STORM_CTRL_GET_THRESHOLD \
+	ID_COMMON_STORM(IDX_COMMON_STORM_CTRL_GET_THRESHOLD)
+#define ID_COMMON_STORM_SET_COUNTER_CLR_PERIOD \
+	ID_COMMON_STORM(IDX_COMMON_STORM_SET_COUNTER_CLR_PERIOD)
+#define ID_COMMON_STORM_GET_COUNTER_CLR_PERIOD \
+	ID_COMMON_STORM(IDX_COMMON_STORM_GET_COUNTER_CLR_PERIOD)
+#define ID_COMMON_STORM_SET_BLOCK_FRAME_2CPU \
+	ID_COMMON_STORM(IDX_COMMON_STORM_SET_BLOCK_FRAME_2CPU)
+#define ID_COMMON_STORM_GET_BLOCK_FRAME_2CPU \
+	ID_COMMON_STORM(IDX_COMMON_STORM_GET_BLOCK_FRAME_2CPU)
+#define ID_COMMON_STORM_SET_DROP_INTERRUPT \
+	ID_COMMON_STORM(IDX_COMMON_STORM_SET_DROP_INTERRUPT)
+#define ID_COMMON_STORM_GET_DROP_INTERRUPT \
+	ID_COMMON_STORM(IDX_COMMON_STORM_GET_DROP_INTERRUPT)
+
+enum{
+	IDX_1811_MCST_STORM_SET_NBLOCK_IP_PKT,
+	IDX_1811_MCST_STORM_GET_NBLOCK_IP_PKT,
+	IDX_1811_MCST_STORM_SET_IGNORE_01005EXXXXXX,
+	IDX_1811_MCST_STORM_GET_IGNORE_01005EXXXXXX,
+	NUM_1811_STORM
+};
+#define ID_1811_STORM(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_STORM, idx)
+#define ID_1811_MCST_STORM_SET_NBLOCK_IP_PKT \
+	ID_1811_STORM(IDX_1811_MCST_STORM_SET_NBLOCK_IP_PKT)
+#define ID_1811_MCST_STORM_GET_NBLOCK_IP_PKT \
+	ID_1811_STORM(IDX_1811_MCST_STORM_GET_NBLOCK_IP_PKT)
+#define ID_1811_MCST_STORM_SET_IGNORE_01005EXXXXXX \
+	ID_1811_STORM(IDX_1811_MCST_STORM_SET_IGNORE_01005EXXXXXX)
+#define ID_1811_MCST_STORM_GET_IGNORE_01005EXXXXXX \
+	ID_1811_STORM(IDX_1811_MCST_STORM_GET_IGNORE_01005EXXXXXX)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_EOC		0x6
+#define ID_COMMON_EOC_SET_FUNC \
+			MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_EOC, 0)
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_LD		0x7
+enum{
+	IDX_COMMON_LOOP_DETECT_SET_FUNC,
+	IDX_COMMON_LOOP_DETECT_GET_FUNC,
+	IDX_COMMON_LOOP_DETECT_SET_TIME_UNIT,
+	IDX_COMMON_LOOP_DETECT_GET_TIME_UNIT,
+	IDX_COMMON_LOOP_DETECT_SET_PKT_SEND_TIMER,
+	IDX_COMMON_LOOP_DETECT_GET_PKT_SEND_TIMER,
+	IDX_COMMON_LOOP_DETECT_SET_BLOCK_RELEASE_TIMER,
+	IDX_COMMON_LOOP_DETECT_GET_BLOCK_RELEASE_TIMER,
+	IDX_COMMON_LOOP_DETECT_GET_STATUS,
+	NUM_COMMON_LOOP_DETECT
+};
+#define ID_COMMON_LOOP_DETECT(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_LD, idx)
+#define ID_COMMON_LOOP_DETECT_SET_FUNC \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_SET_FUNC)
+#define ID_COMMON_LOOP_DETECT_GET_FUNC \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_GET_FUNC)
+#define ID_COMMON_LOOP_DETECT_SET_TIME_UNIT \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_SET_TIME_UNIT)
+#define ID_COMMON_LOOP_DETECT_GET_TIME_UNIT \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_GET_TIME_UNIT)
+#define ID_COMMON_LOOP_DETECT_SET_PKT_SEND_TIMER \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_SET_PKT_SEND_TIMER)
+#define ID_COMMON_LOOP_DETECT_GET_PKT_SEND_TIMER \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_GET_PKT_SEND_TIMER)
+#define ID_COMMON_LOOP_DETECT_SET_BLOCK_RELEASE_TIMER \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_SET_BLOCK_RELEASE_TIMER)
+#define ID_COMMON_LOOP_DETECT_GET_BLOCK_RELEASE_TIMER \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_GET_BLOCK_RELEASE_TIMER)
+#define ID_COMMON_LOOP_DETECT_GET_STATUS \
+	ID_COMMON_LOOP_DETECT(IDX_COMMON_LOOP_DETECT_GET_STATUS)
+
+enum{
+	IDX_1811_LOOP_DETECT_SET_DMAC,
+	IDX_1811_LOOP_DETECT_SET_SUB_TYPE,
+	NUM_1811_LOOP_DETECT
+};
+#define ID_1811_LOOP_DETECT(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_LD, idx)
+#define ID_1811_LOOP_DETECT_SET_DMAC \
+	ID_1811_LOOP_DETECT(IDX_1811_LOOP_DETECT_SET_DMAC)
+#define ID_1811_LOOP_DETECT_SET_SUB_TYPE \
+	ID_1811_LOOP_DETECT(IDX_1811_LOOP_DETECT_SET_SUB_TYPE)
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_WOL		0x8
+#define ID_COMMON_WOL_SET_FUNC \
+			MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_WOL, 0)
+#define ID_COMMON_WOL_GET_FUNC \
+#define ID_1811_WOL_SET_WAKE_IF_TX_GET_ANY_PKT \
+			MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_WOL, 0)
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_STAG	0x9
+enum{
+	IDX_COMMON_SET_CPU_PORT_LINK,
+	IDX_COMMON_STAG_SET_FUNC, 
+	IDX_COMMON_STAG_GET_TYPE_LENGTH, 
+	IDX_COMMON_CONFIG_CPU_PORT, 
+	NUM_COMMON_STAG
+};
+#define ID_COMMON_STAG(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_STAG, idx)
+#define ID_COMMON_SET_CPU_PORT_LINK \
+	ID_COMMON_STAG(IDX_COMMON_SET_CPU_PORT_LINK)
+#define ID_COMMON_STAG_SET_FUNC \
+	ID_COMMON_STAG(IDX_COMMON_STAG_SET_FUNC)
+#define ID_COMMON_STAG_GET_TYPE_LENGTH \
+	ID_COMMON_STAG(IDX_COMMON_STAG_GET_TYPE_LENGTH )
+#define ID_COMMON_CONFIG_CPU_PORT\
+	ID_COMMON_STAG(IDX_COMMON_CONFIG_CPU_PORT)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_IGMP	0xA
+enum{
+	IDX_1811_IGMP_SET_SNOOPING_FUNCTION,
+	IDX_1811_IGMP_GET_SNOOPING_FUNCTION,
+	IDX_1811_IGMP_SET_MCT_BY_CPU,
+	IDX_1811_IGMP_GET_MCT_BY_CPU,
+	IDX_1811_IGMP_SET_ROUTER_LIST_MAKE_BY_CPU,
+	IDX_1811_IGMP_GET_ROUTER_LIST_MAKE_BY_CPU,
+	IDX_1811_IGMP_SET_PACKET_FORWARD_RULE,
+	IDX_1811_IGMP_GET_PACKET_FORWARD_RULE,
+	IDX_1811_IGMP_SET_ROUTER_LIST,
+	IDX_1811_IGMP_GET_ROUTER_LIST,
+	IDX_1811_IGMP_SET_HASHING_METHOD,
+	IDX_1811_IGMP_GET_HASHING_METHOD,
+	IDX_1811_MLD_SET_FORWARD_RULE,
+	IDX_1811_MLD_GET_FORWARD_RULE,
+	IDX_1811_MT_SET_RULE,
+	IDX_1811_MT_GET_RULE,
+	IDX_1811_SLT_SET_RULE,
+	IDX_1811_SLT_GET_RULE,
+	NUM_1811_IGMP
+};
+
+#define ID_1811_IGMP(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_IGMP, idx)
+
+#define ID_1811_IGMP_SET_SNOOPING_FUNCTION \
+	ID_1811_IGMP(IDX_1811_IGMP_SET_SNOOPING_FUNCTION)
+#define ID_1811_IGMP_GET_SNOOPING_FUNCTION \
+	ID_1811_IGMP(IDX_1811_IGMP_GET_SNOOPING_FUNCTION)
+#define ID_1811_IGMP_SET_MCT_BY_CPU \
+	ID_1811_IGMP(IDX_1811_IGMP_SET_MCT_BY_CPU)
+#define ID_1811_IGMP_GET_MCT_BY_CPU \
+	ID_1811_IGMP(IDX_1811_IGMP_GET_MCT_BY_CPU)
+#define ID_1811_IGMP_SET_ROUTER_LIST_MAKE_BY_CPU \
+	ID_1811_IGMP(IDX_1811_IGMP_SET_ROUTER_LIST_MAKE_BY_CPU)
+#define ID_1811_IGMP_GET_ROUTER_LIST_MAKE_BY_CPU \
+	ID_1811_IGMP(IDX_1811_IGMP_GET_ROUTER_LIST_MAKE_BY_CPU)
+#define ID_1811_IGMP_SET_PACKET_FORWARD_RULE \
+	ID_1811_IGMP(IDX_1811_IGMP_SET_PACKET_FORWARD_RULE)
+#define ID_1811_IGMP_GET_PACKET_FORWARD_RULE \
+	ID_1811_IGMP(IDX_1811_IGMP_GET_PACKET_FORWARD_RULE)
+#define ID_1811_IGMP_SET_ROUTER_LIST \
+	ID_1811_IGMP(IDX_1811_IGMP_SET_ROUTER_LIST)
+#define ID_1811_IGMP_GET_ROUTER_LIST \
+	ID_1811_IGMP(IDX_1811_IGMP_GET_ROUTER_LIST)
+#define ID_1811_IGMP_SET_HASHING_METHOD \
+	ID_1811_IGMP(IDX_1811_IGMP_SET_HASHING_METHOD)
+#define ID_1811_IGMP_GET_HASHING_METHOD \
+	ID_1811_IGMP(IDX_1811_IGMP_GET_HASHING_METHOD)
+#define ID_1811_MLD_SET_FORWARD_RULE \
+	ID_1811_IGMP(IDX_1811_MLD_SET_FORWARD_RULE)
+#define ID_1811_MLD_GET_FORWARD_RULE \
+	ID_1811_IGMP(IDX_1811_MLD_GET_FORWARD_RULE)
+#define ID_1811_MT_SET_RULE \
+	ID_1811_IGMP(IDX_1811_MT_SET_RULE)
+#define ID_1811_MT_GET_RULE \
+	ID_1811_IGMP(IDX_1811_MT_GET_RULE)
+#define ID_1811_SLT_SET_RULE \
+	ID_1811_IGMP(IDX_1811_SLT_SET_RULE)
+#define ID_1811_SLT_GET_RULE \
+	ID_1811_IGMP(IDX_1811_SLT_GET_RULE)
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_PTP	0xB
+
+enum{
+	IDX_1811_PTP_SET_ENABLE,
+	IDX_1811_PTP_GET_ENABLE,
+	IDX_1811_PTP_SET_DA_011B19000000,
+	IDX_1811_PTP_GET_DA_011B19000000,
+	IDX_1811_PTP_SET_DA_0180C200000E,
+	IDX_1811_PTP_GET_DA_0180C200000E,
+	IDX_1811_PTP_SET_UDP_DP,
+	IDX_1811_PTP_GET_UDP_DP,
+	IDX_1811_PTP_SET_UDP_SP,
+	IDX_1811_PTP_GET_UDP_SP,
+	IDX_1811_PTP_SET_TO_CPU,
+	IDX_1811_PTP_GET_TO_CPU,
+	IDX_1811_PTP_SET_SPECIAL_TAG,
+	IDX_1811_PTP_GET_SPECIAL_TAG,
+	IDX_1811_PTP_SET_CLOCK_RESET,
+	IDX_1811_PTP_GET_TIMESTAMP,
+	IDX_1811_PTP_SET_CLOCK_ENABLE,
+	IDX_1811_PTP_GET_CLOCK_ENABLE,
+	IDX_1811_PTP_SET_OVERWRITE_ENABLE,
+	IDX_1811_PTP_GET_OVERWRITE_ENABLE,
+	IDX_1811_PTP_SET_PROGRAMMABLE,
+	IDX_1811_PTP_GET_PROGRAMMABLE,
+	IDX_1811_PTP_SET_PROGRAMMABLE_OUTPUT,
+	IDX_1811_PTP_SET_TIMESTAMP_ENABLE,
+	IDX_1811_PTP_GET_TIMESTAMP_ENABLE,
+	IDX_1811_PTP_SET_TIMESTAMP_CLEAR,
+	IDX_1811_PTP_SET_TIMEDATA,
+	IDX_1811_PTP_GET_TIMEDATA,
+	IDX_1811_PTP_ADD_TIMEDATA,
+	IDX_1811_PTP_SUB_TIMEDATA,
+	IDX_1811_PTP_SET_FREQUENCY_ADD,
+	IDX_1811_PTP_GET_FREQUENCY_ADD,
+	IDX_1811_PTP_SET_CLOCK_PERIOD,
+	IDX_1811_PTP_GET_CLOCK_PERIOD,
+	IDX_1811_PTP_SET_PROGRAMMABLE_CONFIG,
+	IDX_1811_PTP_SET_DURATION_FREQUENCY_COMPENSATION,
+	IDX_1811_PTP_SET_ALWAYS_FREQUENCY_COMPENSATION,
+	IDX_1811_PTP_GET_INGRESS_LATENCY_10,
+	IDX_1811_PTP_GET_INGRESS_LATENCY_100,
+	IDX_1811_PTP_GET_INGRESS_LATENCY_FIBER,
+	IDX_1811_PTP_GET_EGRESS_LATENCY_10,
+	IDX_1811_PTP_GET_EGRESS_LATENCY_100,
+	IDX_1811_PTP_GET_EGRESS_LATENCY_FIBER,
+	NUM_1811_PTP
+};
+
+#define ID_1811_PTP(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_PTP, idx)
+
+#define	ID_1811_PTP_SET_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_SET_ENABLE)
+#define	ID_1811_PTP_GET_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_GET_ENABLE)
+#define	ID_1811_PTP_SET_DA_011B19000000 \
+	ID_1811_PTP(IDX_1811_PTP_SET_DA_011B19000000)
+#define	ID_1811_PTP_GET_DA_011B19000000 \
+	ID_1811_PTP(IDX_1811_PTP_GET_DA_011B19000000)
+#define	ID_1811_PTP_SET_DA_0180C200000E \
+	ID_1811_PTP(IDX_1811_PTP_SET_DA_0180C200000E)
+#define	ID_1811_PTP_GET_DA_0180C200000E \
+	ID_1811_PTP(IDX_1811_PTP_GET_DA_0180C200000E)
+#define	ID_1811_PTP_SET_UDP_DP \
+	ID_1811_PTP(IDX_1811_PTP_SET_UDP_DP)
+#define	ID_1811_PTP_GET_UDP_DP \
+	ID_1811_PTP(IDX_1811_PTP_GET_UDP_DP)
+#define	ID_1811_PTP_SET_UDP_SP \
+	ID_1811_PTP(IDX_1811_PTP_SET_UDP_SP)
+#define	ID_1811_PTP_GET_UDP_SP \
+	ID_1811_PTP(IDX_1811_PTP_GET_UDP_SP)
+#define	ID_1811_PTP_SET_TO_CPU \
+	ID_1811_PTP(IDX_1811_PTP_SET_TO_CPU)
+#define	ID_1811_PTP_GET_TO_CPU \
+	ID_1811_PTP(IDX_1811_PTP_GET_TO_CPU)
+#define ID_1811_PTP_SET_SPECIAL_TAG \
+	ID_1811_PTP(IDX_1811_PTP_SET_SPECIAL_TAG)
+#define ID_1811_PTP_GET_SPECIAL_TAG \
+	ID_1811_PTP(IDX_1811_PTP_GET_SPECIAL_TAG)
+#define ID_1811_PTP_SET_CLOCK_RESET \
+	ID_1811_PTP(IDX_1811_PTP_SET_CLOCK_RESET)
+#define ID_1811_PTP_GET_TIMESTAMP \
+	ID_1811_PTP(IDX_1811_PTP_GET_TIMESTAMP)
+#define ID_1811_PTP_SET_CLOCK_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_SET_CLOCK_ENABLE)
+#define ID_1811_PTP_GET_CLOCK_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_GET_CLOCK_ENABLE)
+#define ID_1811_PTP_SET_OVERWRITE_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_SET_OVERWRITE_ENABLE)
+#define ID_1811_PTP_GET_OVERWRITE_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_GET_OVERWRITE_ENABLE)
+#define ID_1811_PTP_SET_PROGRAMMABLE \
+	ID_1811_PTP(IDX_1811_PTP_SET_PROGRAMMABLE)
+#define ID_1811_PTP_GET_PROGRAMMABLE \
+	ID_1811_PTP(IDX_1811_PTP_GET_PROGRAMMABLE)
+#define ID_1811_PTP_SET_PROGRAMMABLE_OUTPUT \
+	ID_1811_PTP(IDX_1811_PTP_SET_PROGRAMMABLE_OUTPUT)
+#define ID_1811_PTP_SET_TIMESTAMP_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_SET_TIMESTAMP_ENABLE)
+#define ID_1811_PTP_GET_TIMESTAMP_ENABLE \
+	ID_1811_PTP(IDX_1811_PTP_GET_TIMESTAMP_ENABLE)
+#define ID_1811_PTP_SET_TIMESTAMP_CLEAR \
+	ID_1811_PTP(IDX_1811_PTP_SET_TIMESTAMP_CLEAR)
+#define ID_1811_PTP_SET_TIMEDATA \
+	ID_1811_PTP(IDX_1811_PTP_SET_TIMEDATA)
+#define ID_1811_PTP_GET_TIMEDATA \
+	ID_1811_PTP(IDX_1811_PTP_GET_TIMEDATA)
+#define ID_1811_PTP_ADD_TIMEDATA \
+	ID_1811_PTP(IDX_1811_PTP_ADD_TIMEDATA)
+#define ID_1811_PTP_SUB_TIMEDATA \
+	ID_1811_PTP(IDX_1811_PTP_SUB_TIMEDATA)
+#define ID_1811_PTP_SET_FREQUENCY_ADD \
+	ID_1811_PTP(IDX_1811_PTP_SET_FREQUENCY_ADD)
+#define ID_1811_PTP_GET_FREQUENCY_ADD \
+	ID_1811_PTP(IDX_1811_PTP_GET_FREQUENCY_ADD)
+#define ID_1811_PTP_SET_CLOCK_PERIOD \
+	ID_1811_PTP(IDX_1811_PTP_SET_CLOCK_PERIOD)
+#define ID_1811_PTP_GET_CLOCK_PERIOD \
+	ID_1811_PTP(IDX_1811_PTP_GET_CLOCK_PERIOD)
+#define ID_1811_PTP_SET_PROGRAMMABLE_CONFIG \
+	ID_1811_PTP(IDX_1811_PTP_SET_PROGRAMMABLE_CONFIG)
+#define ID_1811_PTP_SET_DURATION_FREQUENCY_COMPENSATION \
+	ID_1811_PTP(IDX_1811_PTP_SET_DURATION_FREQUENCY_COMPENSATION)
+#define ID_1811_PTP_SET_ALWAYS_FREQUENCY_COMPENSATION \
+	ID_1811_PTP(IDX_1811_PTP_SET_ALWAYS_FREQUENCY_COMPENSATION)
+#define ID_1811_PTP_GET_INGRESS_LATENCY_10 \
+	ID_1811_PTP(IDX_1811_PTP_GET_INGRESS_LATENCY_10)
+#define ID_1811_PTP_GET_INGRESS_LATENCY_100 \
+	ID_1811_PTP(IDX_1811_PTP_GET_INGRESS_LATENCY_100)
+#define ID_1811_PTP_GET_INGRESS_LATENCY_FIBER \
+	ID_1811_PTP(IDX_1811_PTP_GET_INGRESS_LATENCY_FIBER)
+#define ID_1811_PTP_GET_EGRESS_LATENCY_10 \
+	ID_1811_PTP(IDX_1811_PTP_GET_EGRESS_LATENCY_10)
+#define ID_1811_PTP_GET_EGRESS_LATENCY_100 \
+	ID_1811_PTP(IDX_1811_PTP_GET_EGRESS_LATENCY_100)
+#define ID_1811_PTP_GET_EGRESS_LATENCY_FIBER \
+	ID_1811_PTP(IDX_1811_PTP_GET_EGRESS_LATENCY_FIBER)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUB_BANDWIDTH	0xC
+#define	RATE_SCALE_UNIT	64000
+enum{
+	IDX_COMMON_BANDWIDTH_SET_INGRESS_RATE,
+	IDX_COMMON_BANDWIDTH_GET_INGRESS_RATE,
+	IDX_COMMON_BANDWIDTH_SET_EGRESS_RATE,
+	IDX_COMMON_BANDWIDTH_GET_EGRESS_RATE,
+	IDX_COMMON_BANDWIDTH_SET_EGRESS_PERIOD,
+	IDX_COMMON_BANDWIDTH_GET_EGRESS_PERIOD,
+	NUM_COMMON_BANDWIDTH
+};
+#define ID_COMMON_BANDWIDTH(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUB_BANDWIDTH, idx)
+
+#define ID_COMMON_BANDWIDTH_SET_INGRESS_RATE \
+	ID_COMMON_BANDWIDTH(IDX_COMMON_BANDWIDTH_SET_INGRESS_RATE)
+#define ID_COMMON_BANDWIDTH_GET_INGRESS_RATE \
+	ID_COMMON_BANDWIDTH(IDX_COMMON_BANDWIDTH_GET_INGRESS_RATE)
+#define ID_COMMON_BANDWIDTH_SET_EGRESS_RATE \
+	ID_COMMON_BANDWIDTH(IDX_COMMON_BANDWIDTH_SET_EGRESS_RATE)
+#define ID_COMMON_BANDWIDTH_GET_EGRESS_RATE \
+	ID_COMMON_BANDWIDTH(IDX_COMMON_BANDWIDTH_GET_EGRESS_RATE)
+#define ID_COMMON_BANDWIDTH_SET_EGRESS_PERIOD \
+	ID_COMMON_BANDWIDTH(IDX_COMMON_BANDWIDTH_SET_EGRESS_PERIOD)
+#define ID_COMMON_BANDWIDTH_GET_EGRESS_PERIOD \
+	ID_COMMON_BANDWIDTH(IDX_COMMON_BANDWIDTH_GET_EGRESS_PERIOD)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_MISC	0xF
+enum{
+	IDX_COMMON_8021X_PORT_LOCK_SET_FUNC, 
+	IDX_COMMON_8021X_PORT_LOCK_GET_FUNC, 
+	IDX_COMMON_MISC_SET_REG, 
+	IDX_COMMON_MISC_GET_REG, 
+	IDX_COMMON_MISC_SET_CPU_REG, 
+	IDX_COMMON_MISC_GET_CPU_REG, 
+	IDX_COMMON_MISC_SET_SWITCH_RESTART, 
+	IDX_COMMON_MISC_SET_SWITCH_RESET, 
+	IDX_COMMON_MISC_SET_CPU_IF_SPEED, 
+	IDX_COMMON_MISC_SET_EEPROM_BYTE, 
+	IDX_COMMON_MISC_GET_EEPROM_BYTE, 
+	NUM_COMMON_MISC
+};
+#define ID_COMMON_MISC(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_BASIC, _CMDID_SUBG_MISC, idx)
+
+#define ID_COMMON_8021X_PORT_LOCK_SET_FUNC \
+	ID_COMMON_MISC(IDX_COMMON_8021X_PORT_LOCK_SET_FUNC)
+#define ID_COMMON_8021X_PORT_LOCK_GET_FUNC \
+	ID_COMMON_MISC(IDX_COMMON_8021X_PORT_LOCK_GET_FUNC)
+#define ID_COMMON_MISC_SET_REG \
+	ID_COMMON_MISC(IDX_COMMON_MISC_SET_REG)
+#define ID_COMMON_MISC_GET_REG \
+	ID_COMMON_MISC(IDX_COMMON_MISC_GET_REG)
+#define ID_COMMON_MISC_SET_CPU_REG \
+	ID_COMMON_MISC(IDX_COMMON_MISC_SET_CPU_REG)
+#define ID_COMMON_MISC_GET_CPU_REG \
+	ID_COMMON_MISC(IDX_COMMON_MISC_GET_CPU_REG)
+#define ID_COMMON_MISC_SET_SWITCH_RESTART \
+	ID_COMMON_MISC(IDX_COMMON_MISC_SET_SWITCH_RESTART)
+#define ID_COMMON_MISC_SET_SWITCH_RESET\
+	ID_COMMON_MISC(IDX_COMMON_MISC_SET_SWITCH_RESET)
+#define ID_COMMON_MISC_SET_CPU_IF_SPEED\
+	ID_COMMON_MISC(IDX_COMMON_MISC_SET_CPU_IF_SPEED)
+#define ID_COMMON_MISC_SET_EEPROM_BYTE\
+	ID_COMMON_MISC(IDX_COMMON_MISC_SET_EEPROM_BYTE)
+#define ID_COMMON_MISC_GET_EEPROM_BYTE\
+	ID_COMMON_MISC(IDX_COMMON_MISC_GET_EEPROM_BYTE)
+	
+#if 0
+#define ID_1811_MAC_LOOP_BACK_SET_FUNC \
+			MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_BASIC, _CMDID_SUBG_MISC, 0)
+#endif
+/*===================================================================*/
+#define _CMDID_GRP_VLAN		0x02
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_VLAN	0x1
+
+enum{
+	IDX_COMMON_VLAN_SET_EGRESS_FRAME,	//0
+	IDX_COMMON_VLAN_GET_EGRESS_FRAME,
+	IDX_COMMON_VLAN_SET_TAGGING,
+	IDX_COMMON_VLAN_SET_TYPE,
+	IDX_COMMON_VLAN_SET_GROUP,
+	IDX_COMMON_VLAN_SET_QINQ_TYPE,		//5
+	IDX_COMMON_VLAN_SET_QINQ_P_ADDTAG,
+	IDX_COMMON_VLAN_GET_QINQ_P_ADDTAG,
+	IDX_COMMON_VLAN_SET_QINQ_P_RMVTAG,
+	IDX_COMMON_VLAN_GET_QINQ_P_RMVTAG,
+	IDX_COMMON_VLAN_SET_QINQ_P_RXDET,	//10
+	IDX_COMMON_VLAN_GET_QINQ_P_RXDET,
+	IDX_COMMON_VLAN_SET_QINQ_P_KEEP,
+	IDX_COMMON_VLAN_GET_QINQ_P_KEEP,
+	IDX_COMMON_VLAN_SET_QINQ_P_INDEX,
+	IDX_COMMON_VLAN_GET_QINQ_P_INDEX,	//15
+	IDX_COMMON_VLAN_SET_QINQ_INDEX,
+	IDX_COMMON_VLAN_SET_QINQ_STAG_SELECT_METHOD,
+	IDX_COMMON_VLAN_SET_PORT_ADDTAG,
+	IDX_COMMON_VLAN_GET_PORT_ADDTAG,
+	IDX_COMMON_VLAN_SET_PORT_RMVTAG,	//20
+	IDX_COMMON_VLAN_GET_PORT_RMVTAG,
+	IDX_COMMON_VLAN_SET_PORT_FORCE,
+	IDX_COMMON_VLAN_GET_PORT_FORCE,
+	IDX_COMMON_VLAN_SET_PORT_UPLINK,
+	IDX_COMMON_VLAN_GET_PORT_UPLINK,	//25
+	IDX_COMMON_VLAN_SET_PORT_EXCLUSIVE,
+	IDX_COMMON_VLAN_GET_PORT_EXCLUSIVE,
+	IDX_COMMON_VLAN_SET_PORT_EGRESS,
+	IDX_COMMON_VLAN_GET_PORT_EGRESS,
+	IDX_COMMON_VLAN_SET_PORT_INGRESS_FRAME,		//30
+	IDX_COMMON_VLAN_SET_PORT_INGRESS_CHECK,
+	IDX_COMMON_VLAN_GET_PORT_INGRESS_CHECK,
+	IDX_COMMON_VLAN_SET_PORT_VID,
+	IDX_COMMON_VLAN_SET_PROTOCOL_MODE,
+	IDX_COMMON_VLAN_SET_PROTOCOL_VID,	//35
+	IDX_COMMON_VLAN_SET_PROTOCOL_TYPE,
+	IDX_COMMON_VLAN_CLEAR_PROTOCOL,
+	IDX_COMMON_VLAN_SET_MAC_VLAN,
+	IDX_COMMON_VLAN_SET_MAC_VLAN_VLANTABLE_CONFIG,
+	IDX_COMMON_VLAN_GET_MAC_VLAN_VLANTABLE_CONFIG,		//40
+	IDX_COMMON_VLAN_SET_MAC_VLAN_UNKNOWN,
+	NUM_COMMON_VLAN
+};
+
+#define ID_COMMON_VLAN(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_VLAN, _CMDID_SUBG_VLAN, idx)
+
+#define	ID_COMMON_VLAN_SET_EGRESS_FRAME \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_EGRESS_FRAME)
+#define ID_COMMON_VLAN_GET_EGRESS_FRAME \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_EGRESS_FRAME)
+#define ID_COMMON_VLAN_SET_TAGGING \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_TAGGING)
+#define ID_COMMON_VLAN_SET_TYPE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_TYPE)
+#define ID_COMMON_VLAN_SET_GROUP \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_GROUP)
+
+#define ID_COMMON_VLAN_SET_QINQ_TYPE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_TYPE)
+#define ID_COMMON_VLAN_SET_QINQ_P_ADDTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_P_ADDTAG)
+#define ID_COMMON_VLAN_GET_QINQ_P_ADDTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_QINQ_P_ADDTAG)
+#define ID_COMMON_VLAN_SET_QINQ_P_RMVTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_P_RMVTAG)
+#define ID_COMMON_VLAN_GET_QINQ_P_RMVTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_QINQ_P_RMVTAG)
+#define ID_COMMON_VLAN_SET_QINQ_P_RXDET \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_P_RXDET)
+#define ID_COMMON_VLAN_GET_QINQ_P_RXDET \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_QINQ_P_RXDET)
+#define ID_COMMON_VLAN_SET_QINQ_P_KEEP \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_P_KEEP)
+#define ID_COMMON_VLAN_GET_QINQ_P_KEEP \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_QINQ_P_KEEP)
+#define ID_COMMON_VLAN_SET_QINQ_P_INDEX \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_P_INDEX)
+#define ID_COMMON_VLAN_GET_QINQ_P_INDEX \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_QINQ_P_INDEX)
+#define ID_COMMON_VLAN_SET_QINQ_INDEX \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_INDEX)
+#define ID_COMMON_VLAN_SET_QINQ_STAG_SELECT_METHOD \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_QINQ_STAG_SELECT_METHOD)
+	
+#define ID_COMMON_VLAN_SET_PORT_ADDTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_ADDTAG)
+#define ID_COMMON_VLAN_GET_PORT_ADDTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_ADDTAG)
+#define ID_COMMON_VLAN_SET_PORT_RMVTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_RMVTAG)
+#define ID_COMMON_VLAN_GET_PORT_RMVTAG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_RMVTAG)
+#define ID_COMMON_VLAN_SET_PORT_FORCE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_FORCE)
+#define ID_COMMON_VLAN_GET_PORT_FORCE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_FORCE)
+#define ID_COMMON_VLAN_SET_PORT_UPLINK \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_UPLINK)
+#define ID_COMMON_VLAN_GET_PORT_UPLINK \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_UPLINK)
+#define ID_COMMON_VLAN_SET_PORT_EXCLUSIVE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_EXCLUSIVE)
+#define ID_COMMON_VLAN_GET_PORT_EXCLUSIVE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_EXCLUSIVE)
+#define ID_COMMON_VLAN_SET_PORT_EGRESS \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_EGRESS)
+#define ID_COMMON_VLAN_GET_PORT_EGRESS \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_EGRESS)
+#define ID_COMMON_VLAN_SET_PORT_INGRESS_FRAME \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_INGRESS_FRAME)
+#define ID_COMMON_VLAN_SET_PORT_INGRESS_CHECK \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_INGRESS_CHECK)
+#define ID_COMMON_VLAN_GET_PORT_INGRESS_CHECK \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_PORT_INGRESS_CHECK)
+#define ID_COMMON_VLAN_SET_PORT_VID \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PORT_VID)
+
+#define ID_COMMON_VLAN_SET_PROTOCOL_MODE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PROTOCOL_MODE)
+#define ID_COMMON_VLAN_SET_PROTOCOL_VID \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PROTOCOL_VID)
+#define ID_COMMON_VLAN_SET_PROTOCOL_TYPE \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_PROTOCOL_TYPE)
+#define ID_COMMON_VLAN_CLEAR_PROTOCOL \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_CLEAR_PROTOCOL)
+#define	ID_COMMON_VLAN_SET_MAC_VLAN \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_MAC_VLAN)
+#define	ID_COMMON_VLAN_SET_MAC_VLAN_VLANTABLE_CONFIG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_MAC_VLAN_VLANTABLE_CONFIG)
+#define	ID_COMMON_VLAN_GET_MAC_VLAN_VLANTABLE_CONFIG \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_GET_MAC_VLAN_VLANTABLE_CONFIG)
+#define	ID_COMMON_VLAN_SET_MAC_VLAN_UNKNOWN \
+	ID_COMMON_VLAN(IDX_COMMON_VLAN_SET_MAC_VLAN_UNKNOWN)
+
+enum{
+	IDX_IP1811_VLAN_SET_ENTRY_MEMBER,	//0
+	IDX_IP1811_VLAN_SET_ENTRY_ADDTAG,
+	IDX_IP1811_VLAN_SET_ENTRY_RMVTAG,
+	IDX_IP1811_VLAN_SET_ENTRY_PRIORITY,
+	IDX_IP1811_VLAN_SET_ENTRY_FID,
+	IDX_IP1811_VLAN_GET_ENTRY_FID,		//5
+	IDX_IP1811_VLAN_DELETE_ENTRY,
+	NUM_IP1811_VLAN
+};
+
+#define ID_IP1811_VLAN(idx) \
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_VLAN, _CMDID_SUBG_VLAN, idx)
+
+#define ID_IP1811_VLAN_SET_ENTRY_MEMBER \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_SET_ENTRY_MEMBER)
+#define ID_IP1811_VLAN_SET_ENTRY_ADDTAG \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_SET_ENTRY_ADDTAG)
+#define ID_IP1811_VLAN_SET_ENTRY_RMVTAG \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_SET_ENTRY_RMVTAG)
+#define ID_IP1811_VLAN_SET_ENTRY_PRIORITY \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_SET_ENTRY_PRIORITY)
+#define ID_IP1811_VLAN_SET_ENTRY_FID \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_SET_ENTRY_FID)
+#define ID_IP1811_VLAN_GET_ENTRY_FID \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_GET_ENTRY_FID)
+#define	ID_IP1811_VLAN_DELETE_ENTRY \
+	ID_IP1811_VLAN(IDX_IP1811_VLAN_DELETE_ENTRY)
+
+/*===================================================================*/
+#define _CMDID_GRP_QOS		0x03
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUB_QOS		0x1
+enum{
+	IDX_IP1811_SET_QOS_AGING_FUNCTION,
+	IDX_IP1811_GET_QOS_AGING_FUNCTION,
+	IDX_IP1811_SET_QOS_AGING_TIME,
+	IDX_IP1811_GET_QOS_AGING_TIME,
+	IDX_IP1811_SET_QOS_FASTAGING,
+	IDX_IP1811_GET_QOS_FASTAGING,
+
+	IDX_IP1811_SET_COS_IGMP,
+	IDX_IP1811_GET_COS_IGMP,
+	IDX_IP1811_SET_COS_MACADDRESS,
+	IDX_IP1811_GET_COS_MACADDRESS,
+	IDX_IP1811_SET_COS_VID,
+	IDX_IP1811_GET_COS_VID,
+	IDX_IP1811_SET_COS_TCPUDPPORT,
+	IDX_IP1811_GET_COS_TCPUDPPORT,
+	IDX_IP1811_SET_COS_DSCP,
+	IDX_IP1811_GET_COS_DSCP,
+	IDX_IP1811_SET_COS_8021P,
+	IDX_IP1811_GET_COS_8021P,
+	IDX_IP1811_SET_COS_PHYSICALPORT,
+	IDX_IP1811_GET_COS_PHYSICALPORT,
+	IDX_IP1811_SET_COS_PORT_QUEUE,
+	IDX_IP1811_GET_COS_PORT_QUEUE,
+	IDX_IP1811_SET_COS_8021PEDTION,
+	IDX_IP1811_GET_COS_8021PEDTION,
+	IDX_IP1811_SET_COS_DSCPBASE_DSCP,
+	IDX_IP1811_GET_COS_DSCPBASE_DSCP,
+	IDX_IP1811_SET_COS_DSCPBASE_NOMATCHACTION,
+	IDX_IP1811_GET_COS_DSCPBASE_NOMATCHACTION,
+	
+	IDX_IP1811_SET_QOSMODE_GROUP_MEMEBER,
+	IDX_IP1811_GET_QOSMODE_GROUP_MEMEBER,
+	IDX_IP1811_SET_QOSGROUPB_EN,
+	IDX_IP1811_GET_QOSGROUPB_EN,
+	IDX_IP1811_SET_QOS_MODE,
+	IDX_IP1811_GET_QOS_MODE,
+	IDX_IP1811_SET_QOS_METHOD,
+	IDX_IP1811_GET_QOS_METHOD,
+	IDX_IP1811_SET_QOS_WEIGHT,
+	IDX_IP1811_GET_QOS_WEIGHT,
+	IDX_IP1811_SET_QOS_MAXBANDWIDTH,
+	IDX_IP1811_GET_QOS_MAXBANDWIDTH,
+	IDX_IP1811_SET_QOS_UNIT,
+	IDX_IP1811_GET_QOS_UNIT,
+	IDX_IP1811_SET_QOS_RATIOVALUE0_DEF,
+	IDX_IP1811_GET_QOS_RATIOVALUE0_DEF,
+	IDX_IP1811_SET_QOS_SBM_DBM,
+	IDX_IP1811_GET_QOS_SBM_DBM,
+	IDX_IP1811_SET_QOS_DBM_EN,
+	IDX_IP1811_GET_QOS_DBM_EN,
+	
+	IDX_IP1811_SET_QOS_REMAP,
+	IDX_IP1811_GET_QOS_REMAP,
+	NUM_IP1811_QOS
+};
+#define ID_IP1811_QOS(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_QOS, _CMDID_SUB_QOS, idx)
+
+#define ID_IP1811_SET_QOS_AGING_FUNCTION \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_AGING_FUNCTION)
+#define ID_IP1811_GET_QOS_AGING_FUNCTION \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_AGING_FUNCTION)
+#define ID_IP1811_SET_QOS_AGING_TIME \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_AGING_TIME)
+#define ID_IP1811_GET_QOS_AGING_TIME \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_AGING_TIME)
+#define ID_IP1811_SET_QOS_FASTAGING \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_FASTAGING)
+#define ID_IP1811_GET_QOS_FASTAGING \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_FASTAGING)
+
+#define ID_IP1811_SET_COS_IGMP \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_IGMP)
+#define ID_IP1811_GET_COS_IGMP \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_IGMP)
+#define ID_IP1811_SET_COS_MACADDRESS \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_MACADDRESS)
+#define ID_IP1811_GET_COS_MACADDRESS \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_MACADDRESS)
+#define ID_IP1811_SET_COS_VID \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_VID)
+#define ID_IP1811_GET_COS_VID \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_VID)
+#define ID_IP1811_SET_COS_TCPUDPPORT \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_TCPUDPPORT)
+#define ID_IP1811_GET_COS_TCPUDPPORT \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_TCPUDPPORT)
+#define ID_IP1811_SET_COS_DSCP \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_DSCP)
+#define ID_IP1811_GET_COS_DSCP \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_DSCP)
+#define ID_IP1811_SET_COS_8021P \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_8021P)
+#define ID_IP1811_GET_COS_8021P \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_8021P)
+#define ID_IP1811_SET_COS_PHYSICALPORT \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_PHYSICALPORT)
+#define ID_IP1811_GET_COS_PHYSICALPORT \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_PHYSICALPORT)
+#define ID_IP1811_SET_COS_PORT_QUEUE \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_PORT_QUEUE)
+#define ID_IP1811_GET_COS_PORT_QUEUE \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_PORT_QUEUE)
+#define ID_IP1811_SET_COS_8021PEDTION \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_8021PEDTION)
+#define ID_IP1811_GET_COS_8021PEDTION \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_8021PEDTION)
+#define ID_IP1811_SET_COS_DSCPBASE_DSCP \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_DSCPBASE_DSCP)
+#define ID_IP1811_GET_COS_DSCPBASE_DSCP \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_DSCPBASE_DSCP)
+#define ID_IP1811_SET_COS_DSCPBASE_NOMATCHACTION \
+	ID_IP1811_QOS(IDX_IP1811_SET_COS_DSCPBASE_NOMATCHACTION)
+#define ID_IP1811_GET_COS_DSCPBASE_NOMATCHACTION \
+	ID_IP1811_QOS(IDX_IP1811_GET_COS_DSCPBASE_NOMATCHACTION)
+
+#define ID_IP1811_SET_QOSMODE_GROUP_MEMEBER \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOSMODE_GROUP_MEMEBER)
+#define ID_IP1811_GET_QOSMODE_GROUP_MEMEBER \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOSMODE_GROUP_MEMEBER)
+#define ID_IP1811_SET_QOSGROUPB_EN \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOSGROUPB_EN)
+#define ID_IP1811_GET_QOSGROUPB_EN \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOSGROUPB_EN)
+#define ID_IP1811_SET_QOS_MODE \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_MODE)
+#define ID_IP1811_GET_QOS_MODE \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_MODE)
+#define ID_IP1811_SET_QOS_METHOD \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_METHOD)
+#define ID_IP1811_GET_QOS_METHOD \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_METHOD)
+#define ID_IP1811_SET_QOS_WEIGHT \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_WEIGHT)
+#define ID_IP1811_GET_QOS_WEIGHT \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_WEIGHT)
+#define ID_IP1811_SET_QOS_MAXBANDWIDTH \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_MAXBANDWIDTH)
+#define ID_IP1811_GET_QOS_MAXBANDWIDTH \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_MAXBANDWIDTH)
+#define ID_IP1811_SET_QOS_UNIT \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_UNIT)
+#define ID_IP1811_GET_QOS_UNIT \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_UNIT)
+#define ID_IP1811_SET_QOS_RATIOVALUE0_DEF \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_RATIOVALUE0_DEF)
+#define ID_IP1811_GET_QOS_RATIOVALUE0_DEF \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_RATIOVALUE0_DEF)
+#define ID_IP1811_SET_QOS_SBM_DBM \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_SBM_DBM)
+#define ID_IP1811_GET_QOS_SBM_DBM \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_SBM_DBM)
+#define ID_IP1811_SET_QOS_DBM_EN \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_DBM_EN)
+#define ID_IP1811_GET_QOS_DBM_EN \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_DBM_EN)
+
+#define ID_IP1811_SET_QOS_REMAP \
+	ID_IP1811_QOS(IDX_IP1811_SET_QOS_REMAP)
+#define ID_IP1811_GET_QOS_REMAP \
+	ID_IP1811_QOS(IDX_IP1811_GET_QOS_REMAP)
+/*===================================================================*/
+#define _CMDID_GRP_ACL		0x04
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_ACL		0x01
+enum{
+	IDX_IP1811_ACL_SET_RULE,
+	IDX_IP1811_ACL_GET_RULE,
+	IDX_IP1811_ACL_CLEAN_TABLE,
+	IDX_IP1811_ACL_SET_FUNCTION_EN,
+	IDX_IP1811_ACL_GET_FUNCTION_EN,
+	IDX_IP1811_ACL_SET_ETHER_AFTER_TAG,
+	IDX_IP1811_ACL_GET_ETHER_AFTER_TAG,
+	IDX_IP1811_ACL_GET_USED_RULES,
+	IDX_IP1811_ACL_GET_USED_ENTRIES,
+	IDX_IP1811_ACL_GET_USED_ENTRY_MASK,
+	IDX_IP1811_ACL_SET_BW,
+	IDX_IP1811_ACL_GET_BW,
+	IDX_IP1811_ACL_SET_DSCP,
+	IDX_IP1811_ACL_GET_DSCP,
+	IDX_IP1811_ACL_SET_VID_REMARK,
+	IDX_IP1811_ACL_GET_VID_REMARK,
+	IDX_IP1811_ACL_SET_STORM_PERIOD,
+	IDX_IP1811_ACL_GET_STORM_PERIOD,
+	IDX_IP1811_ACL_SET_STORM,
+	IDX_IP1811_ACL_GET_STORM,
+	NUM_IP1811_ACL
+};
+#define ID_IP1811_ACL(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_ACL, _CMDID_SUBG_ACL, idx)
+#define ID_1811_ACL_SET_RULE \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_RULE)
+#define ID_1811_ACL_GET_RULE \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_RULE)
+#define ID_1811_ACL_CLEAN_TABLE \
+	ID_IP1811_ACL(IDX_IP1811_ACL_CLEAN_TABLE)
+#define ID_1811_ACL_SET_FUNCTION_EN \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_FUNCTION_EN)
+#define ID_1811_ACL_GET_FUNCTION_EN \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_FUNCTION_EN)
+#define ID_1811_ACL_SET_ETHER_AFTER_TAG \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_ETHER_AFTER_TAG)
+#define ID_1811_ACL_GET_ETHER_AFTER_TAG \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_ETHER_AFTER_TAG)
+#define ID_1811_ACL_GET_USED_RULES \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_USED_RULES)
+#define ID_1811_ACL_GET_USED_ENTRIES \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_USED_ENTRIES)
+#define ID_1811_ACL_GET_USED_ENTRY_MASK \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_USED_ENTRY_MASK)
+#define ID_1811_ACL_SET_BW \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_BW)
+#define ID_1811_ACL_GET_BW \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_BW)
+#define ID_1811_ACL_SET_DSCP \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_DSCP)
+#define ID_1811_ACL_GET_DSCP \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_DSCP)
+#define ID_1811_ACL_SET_VID_REMARK \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_VID_REMARK)
+#define ID_1811_ACL_GET_VID_REMARK \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_VID_REMARK)
+#define ID_1811_ACL_SET_STORM_PERIOD \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_STORM_PERIOD)
+#define ID_1811_ACL_GET_STORM_PERIOD \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_STORM_PERIOD)
+#define ID_1811_ACL_SET_STORM \
+	ID_IP1811_ACL(IDX_IP1811_ACL_SET_STORM)
+#define ID_1811_ACL_GET_STORM \
+	ID_IP1811_ACL(IDX_IP1811_ACL_GET_STORM)
+
+/*===================================================================*/
+#define _CMDID_GRP_SEC		0x05
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_IMP		0x01
+#define ID_COMMON_SET_IMP_MODE \
+			MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_SEC, _CMDID_SUBG_IMP, 0)
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_COS		0x2
+enum{
+	IDX_COMMON_TCPUDP_SET_USER_DEFINE,
+	IDX_COMMON_TCPUDP_GET_USER_DEFINE,
+	IDX_COMMON_TCPUDP_SET_QUEUE,
+	IDX_COMMON_TCPUDP_GET_QUEUE,
+	IDX_COMMON_TCPUDP_SET_ENABLE,
+	IDX_COMMON_TCPUDP_GET_ENABLE,
+	IDX_COMMON_TCPUDP_SET_TCP_ENABLE,
+	IDX_COMMON_TCPUDP_GET_TCP_ENABLE,
+	IDX_COMMON_TCPUDP_SET_UDP_ENABLE,
+	IDX_COMMON_TCPUDP_GET_UDP_ENABLE,
+	IDX_COMMON_TCPFLAG_SET_DROP_NULL,
+	IDX_COMMON_TCPFLAG_GET_DROP_NULL,
+	IDX_COMMON_TCPFLAG_SET_DROP_ALLSET,
+	IDX_COMMON_TCPFLAG_GET_DROP_ALLSET,
+	IDX_COMMON_TCPFLAG_SET_FLAG,
+	IDX_COMMON_TCPFLAG_GET_FLAG,
+	IDX_COMMON_TCPFLAG_SET_ACTION,
+	IDX_COMMON_TCPFLAG_GET_ACTION,
+	IDX_COMMON_TCPFLAG_SET_PORT,
+	IDX_COMMON_TCPFLAG_GET_PORT,	
+	NUM_COMMON_TCPUDP
+};
+#define ID_COMMON_COS(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_SEC, _CMDID_SUBG_COS, idx)
+
+#define	ID_COMMON_TCPUDP_SET_USER_DEFINE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_SET_USER_DEFINE)
+#define	ID_COMMON_TCPUDP_GET_USER_DEFINE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_GET_USER_DEFINE)
+#define	ID_COMMON_TCPUDP_SET_QUEUE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_SET_QUEUE)
+#define	ID_COMMON_TCPUDP_GET_QUEUE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_GET_QUEUE)
+#define	ID_COMMON_TCPUDP_SET_ENABLE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_SET_ENABLE)
+#define	ID_COMMON_TCPUDP_GET_ENABLE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_GET_ENABLE)
+#define	ID_COMMON_TCPUDP_SET_TCP_ENABLE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_SET_TCP_ENABLE)
+#define	ID_COMMON_TCPUDP_GET_TCP_ENABLE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_GET_TCP_ENABLE)
+#define	ID_COMMON_TCPUDP_SET_UDP_ENABLE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_SET_UDP_ENABLE)
+#define	ID_COMMON_TCPUDP_GET_UDP_ENABLE \
+	ID_COMMON_COS(IDX_COMMON_TCPUDP_GET_UDP_ENABLE)
+#define	ID_COMMON_TCPFLAG_SET_DROP_NULL \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_SET_DROP_NULL)
+#define	ID_COMMON_TCPFLAG_GET_DROP_NULL \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_GET_DROP_NULL)
+#define	ID_COMMON_TCPFLAG_SET_DROP_ALLSET \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_SET_DROP_ALLSET)
+#define	ID_COMMON_TCPFLAG_GET_DROP_ALLSET \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_GET_DROP_ALLSET)
+#define	ID_COMMON_TCPFLAG_SET_FLAG \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_SET_FLAG)
+#define	ID_COMMON_TCPFLAG_GET_FLAG \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_GET_FLAG)
+#define	ID_COMMON_TCPFLAG_SET_ACTION \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_SET_ACTION)
+#define	ID_COMMON_TCPFLAG_GET_ACTION \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_GET_ACTION)
+#define	ID_COMMON_TCPFLAG_SET_PORT \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_SET_PORT)
+#define	ID_COMMON_TCPFLAG_GET_PORT \
+	ID_COMMON_COS(IDX_COMMON_TCPFLAG_GET_PORT)
+
+/*===================================================================*/
+#define _CMDID_GRP_ADV		0x06
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_STP		0x1
+enum{
+	IDX_COMMON_MSTP_SET_FUNC,
+	IDX_COMMON_MSTP_GET_FUNC,
+	NUM_COMMON_STP
+};
+#define ID_COMMON_STP(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_ADV, _CMDID_SUBG_STP, idx)
+
+#define ID_COMMON_MSTP_SET_FUNC \
+	ID_COMMON_STP(IDX_COMMON_MSTP_SET_FUNC)
+#define ID_COMMON_MSTP_GET_FUNC \
+	ID_COMMON_STP(IDX_COMMON_MSTP_GET_FUNC)
+
+enum{
+	IDX_1811_BPDU_SET_CAP_MODE,
+	IDX_1811_BPDU_GET_CAP_MODE,
+	IDX_1811_BPDU_SET_PORT_ACT,
+	IDX_1811_BPDU_GET_PORT_ACT,
+	IDX_1811_STP_SET_PORT_STATE,
+	IDX_1811_STP_GET_PORT_STATE,
+	NUM_1811_STP
+};
+#define ID_1811_STP(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_ADV, _CMDID_SUBG_STP, idx)
+
+#define ID_1811_BPDU_SET_CAP_MODE \
+	ID_1811_STP(IDX_1811_BPDU_SET_CAP_MODE)
+#define ID_1811_BPDU_GET_CAP_MODE \
+	ID_1811_STP(IDX_1811_BPDU_GET_CAP_MODE)
+#define ID_1811_BPDU_SET_PORT_ACT \
+	ID_1811_STP(IDX_1811_BPDU_SET_PORT_ACT)
+#define ID_1811_BPDU_GET_PORT_ACT \
+	ID_1811_STP(IDX_1811_BPDU_GET_PORT_ACT)
+#define ID_1811_STP_SET_PORT_STATE \
+	ID_1811_STP(IDX_1811_STP_SET_PORT_STATE)
+#define ID_1811_STP_GET_PORT_STATE \
+	ID_1811_STP(IDX_1811_STP_GET_PORT_STATE)
+
+
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_LACP	0x2
+enum{
+	IDX_COMMON_TRUNK_SET_HASH_METHOD,
+	IDX_COMMON_TRUNK_GET_HASH_METHOD,
+	IDX_COMMON_TRUNK_SET_MEMBER,
+	IDX_COMMON_TRUNK_GET_MEMBER,
+	IDX_COMMON_CPU_SET_NOT_CARE_TRUNK_AND_VLAN,
+	IDX_COMMON_CPU_GET_NOT_CARE_TRUNK_AND_VLAN,
+	NUM_COMMON_LACP
+};
+#define ID_COMMON_LACP(idx)	\
+	MAKECMDID(_CMDID_USG_COMMON, _CMDID_GRP_ADV, _CMDID_SUBG_LACP, idx)
+
+#define ID_COMMON_TRUNK_SET_HASH_METHOD \
+	ID_COMMON_LACP(IDX_COMMON_TRUNK_SET_HASH_METHOD)
+#define ID_COMMON_TRUNK_GET_HASH_METHOD \
+	ID_COMMON_LACP(IDX_COMMON_TRUNK_GET_HASH_METHOD)
+#define ID_COMMON_TRUNK_SET_MEMBER \
+	ID_COMMON_LACP(IDX_COMMON_TRUNK_SET_MEMBER)
+#define ID_COMMON_TRUNK_GET_MEMBER \
+	ID_COMMON_LACP(IDX_COMMON_TRUNK_GET_MEMBER)
+#define ID_COMMON_CPU_SET_NOT_CARE_TRUNK_AND_VLAN \
+	ID_COMMON_LACP(IDX_COMMON_CPU_SET_NOT_CARE_TRUNK_AND_VLAN)
+#define ID_COMMON_CPU_GET_NOT_CARE_TRUNK_AND_VLAN \
+	ID_COMMON_LACP(IDX_COMMON_CPU_GET_NOT_CARE_TRUNK_AND_VLAN)
+	
+enum{
+	IPX_1811_TRUNK_SET_HASH_METHOD_SEQ,
+	IPX_1811_TRUNK_GET_HASH_METHOD_SEQ,
+	IPX_1811_TRUNK_SET_GROUP_COMBINE,
+	IPX_1811_TRUNK_GET_GROUP_COMBINE,
+	NUM_1811_LACP
+};
+#define ID_1811_LACP(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_ADV, _CMDID_SUBG_LACP, idx)
+
+#define IP_1811_TRUNK_SET_HASH_METHOD_SEQ \
+	ID_1811_LACP(IPX_1811_TRUNK_SET_HASH_METHOD_SEQ)
+#define IP_1811_TRUNK_GET_HASH_METHOD_SEQ \
+	ID_1811_LACP(IPX_1811_TRUNK_GET_HASH_METHOD_SEQ)
+#define IP_1811_TRUNK_SET_GROUP_COMBINE \
+	ID_1811_LACP(IPX_1811_TRUNK_SET_GROUP_COMBINE)
+#define IP_1811_TRUNK_GET_GROUP_COMBINE \
+	ID_1811_LACP(IPX_1811_TRUNK_GET_GROUP_COMBINE)
+
+/*===================================================================*/
+#define _CMDID_GRP_MON		0x07
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_MIB_COUNTER   0x1
+enum{
+	IDX_1811_SET_MIB_COUNTER_ENABLE,
+	IDX_1811_GET_MIB_COUNTER_ENABLE,
+	IDX_1811_GET_MIB_COUNTER_ALL,
+	IDX_1811_GET_MIB_COUNTER_BY_PORT,
+	IDX_1811_GET_MIB_COUNTER_BY_ITEM,
+	NUM_1811_MIB_COUNTER
+};
+#define ID_COMMON_MIB_COUNTER(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_MON, _CMDID_SUBG_MIB_COUNTER, idx)
+
+#define	ID_1811_SET_MIB_COUNTER_ENABLE \
+	ID_COMMON_MIB_COUNTER(IDX_1811_SET_MIB_COUNTER_ENABLE)
+#define	ID_1811_GET_MIB_COUNTER_ENABLE \
+	ID_COMMON_MIB_COUNTER(IDX_1811_GET_MIB_COUNTER_ENABLE)
+#define	ID_1811_GET_MIB_COUNTER_ALL \
+	ID_COMMON_MIB_COUNTER(IDX_1811_GET_MIB_COUNTER_ALL)
+#define	ID_1811_GET_MIB_COUNTER_BY_PORT \
+	ID_COMMON_MIB_COUNTER(IDX_1811_GET_MIB_COUNTER_BY_PORT)
+#define	ID_1811_GET_MIB_COUNTER_BY_ITEM \
+	ID_COMMON_MIB_COUNTER(IDX_1811_GET_MIB_COUNTER_BY_ITEM)
+
+/*===================================================================*/
+#define _CMDID_GRP_HSR		0x08
+/*-------------------------------------------------------------------*/
+#define _CMDID_SUBG_HSR   0x1
+enum{
+	IDX_1811_SET_HSR_ENABLE,
+	IDX_1811_GET_HSR_ENABLE,
+	IDX_1811_SET_HSR_MODE,
+	IDX_1811_GET_HSR_MODE,
+	NUM_IP1811_HSR
+};
+#define ID_COMMON_HSR(idx)	\
+	MAKECMDID(_CMDID_USG_IP1811, _CMDID_GRP_HSR, _CMDID_SUBG_HSR, idx)
+
+#define	ID_1811_SET_HSR_ENABLE \
+	ID_COMMON_HSR(IDX_1811_SET_HSR_ENABLE)
+#define	ID_1811_GET_HSR_ENABLE \
+	ID_COMMON_HSR(IDX_1811_GET_HSR_ENABLE)
+#define	ID_1811_SET_HSR_MODE \
+	ID_COMMON_HSR(IDX_1811_SET_HSR_MODE)
+#define	ID_1811_GET_HSR_MODE \
+	ID_COMMON_HSR(IDX_1811_GET_HSR_MODE)
+
+#endif		/* IP1811_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811ds.h b/kernel/drivers/net/ethernet/ip1811/ip1811ds.h
new file mode 100644
index 0000000..50e52b8
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811ds.h
@@ -0,0 +1,746 @@
+#ifndef IP1811DS_H
+#define IP1811DS_H
+
+#include "ip1811.h"
+#include "include/list.h"
+
+/*typedef unsigned char 	u8;
+typedef unsigned short  u16;
+typedef unsigned long	u32;*/
+
+struct GeneralSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int gdata;
+};
+
+struct PortMemberSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long member;
+};
+
+struct ByPortSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int port;
+	int pdata;
+};
+
+struct ByPortSetting32
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int port;
+	unsigned long pdata;
+};
+
+struct AllPortsSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int apdata[MAX_PHY_NUM];
+};
+
+struct PortmapSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long portmap;
+	int pmdata;
+};
+
+struct PortMaskSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long portmap;
+	int mask;
+};
+
+/*--------------- Special Data Structures for PTP ---------------*/
+struct PTPReadSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned char addr;			//0-15
+	char in_out;				//1:egress, 0:ingress
+	int port;					//1-12
+	unsigned long long second;
+	unsigned long nanosecond;
+};
+
+struct PTPPortTSSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long portmap;
+	char in_out;			//1:egress, 0:ingress
+	char pmdata;			//set:OP_FUNC_ENABLE/DISABLE
+							//get:always enable
+};
+
+struct PTPTimeSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long long second;
+	unsigned long nanosecond;
+};
+
+struct PTPFrequencySetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	char type;					//1:add 0:sub
+	unsigned long frequency;
+	unsigned long clockcycle;
+	unsigned long period_time;	//nanosecond
+};
+
+struct PTPFrequencyPPMSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	char type;					//1:add 0:sub
+	unsigned long ppm_h;
+	unsigned long ppm_l;
+};
+/*--------------- Special Data Structures for SMI ---------------*/
+struct LinkStatusSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+    int port;
+    unsigned int link;
+	unsigned int speed;
+    unsigned int duplex;
+    unsigned int pause;
+    unsigned int asym;
+    unsigned int an;
+    unsigned int fiber;
+};
+
+/*--------------- Special Data Structures for L2 Protocol ---------------*/
+struct CapActSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int protocol;
+	int act;
+};
+
+/*--------------- Special Data Structures for Storm ---------------*/
+struct StormGeneralSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+    unsigned char storm;
+	long sdata;
+};
+
+/*--------------- Special Data Structures for Loop Detect ---------------*/
+struct LDDASetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned char da[6];
+};
+
+/*--------------- Special Data Structures for Special Tag ---------------*/
+struct STagTypeLenSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int length;
+	unsigned int type;
+};
+
+/*--------------- Special Data Structures for MISC ---------------*/
+struct RegSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned char page;
+	unsigned char reg;
+	unsigned short val;
+};
+/*--------------- Special Data Structures for MISC PHY ---------------*/
+struct PhySetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned char phy;
+	unsigned char page;
+	unsigned char reg;
+	unsigned short val;
+	unsigned char all;
+};
+
+/*--------------- Special Data Structures for STP ---------------*/
+struct StpByFPSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int fid;
+	int port;
+	int pstate;
+};
+
+struct StpAllPortsSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int fid;
+	int pstate[MAX_PHY_NUM-1];
+};
+
+/*--------------- Special Data Structures for LACP ---------------*/
+struct TrunkMemberSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+    unsigned long portmask;
+	unsigned long tstate;
+};
+
+struct TrunkCombineSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long tgrps;
+	int cen;
+};
+
+/*--------------- Special Data Structures for LUT ---------------*/
+struct IP1811LUTEntry
+{
+	unsigned char cfg;
+	unsigned char mac[6];
+	unsigned char fid;
+	unsigned char srcport;
+	unsigned char aging;
+	unsigned char priority;
+	struct{
+		unsigned short drop: 1;
+		unsigned short snif: 1;
+		unsigned short sflow: 1;
+		unsigned short reserve: 13;
+	}flag;
+};
+
+struct IP1811LUTSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long retval;
+	unsigned char action;
+	unsigned long tarports;
+	unsigned short index;
+	unsigned char block;
+	struct IP1811LUTEntry entry;
+	unsigned short data[6];
+};
+
+struct IP1811LUTReg
+{
+	unsigned short data[6];
+	unsigned char block;
+	struct list_head list;
+};
+
+/*--------------- Special Data Structures for IGMP ---------------*/
+
+struct mt_rule{
+	unsigned char group[4];
+	unsigned char fid;
+	unsigned long port_mem;
+	unsigned char pri;
+	unsigned char slt_index;
+	unsigned char flag;
+};
+
+struct MtRuleSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int index;
+	struct mt_rule mt_data;
+};
+
+struct slt_rule{
+	unsigned char type;	//4:ipv4, 6:ipv6, define in ip1811op.h
+	union slt_para{
+		struct slt_ipv4{
+			unsigned char ip[6][4];
+			unsigned int used_port[6];
+		}ipv4;
+
+		struct slt_ipv6{
+			unsigned short ip[2][8];
+			unsigned int used_port[2];
+		}ipv6;
+	}data;
+	unsigned int port_filter_mode;
+};
+
+struct SltRuleSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int index;
+	struct slt_rule slt_data;
+};
+
+struct IgmpPacketRule{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int packet_type;
+	unsigned int rule;
+};
+
+struct IgmpRouterListSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int portmask;
+	unsigned int tstate;
+};
+
+/*--------------- Special Data Structures for IMP ---------------*/
+struct IP1811IMPEntry
+{
+	unsigned char ip[16];
+	unsigned char mac[6];
+	unsigned char srcport;
+	unsigned char priority;
+	struct{
+		unsigned int valid: 1;
+		unsigned int ip_type: 1;
+		unsigned int check_ip: 1;
+		unsigned int check_mac: 1;
+		unsigned int check_port: 1;
+		unsigned int filter: 1;
+		unsigned int sniff2: 1;
+		unsigned int reserved: 9;
+	}flag;
+};
+
+struct IP1811IMPSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned long retval;
+	unsigned char action;
+	unsigned char index;
+	struct IP1811IMPEntry entry;
+};
+
+/*--------------- Special Data Structures for VLAN ---------------*/
+struct VlanSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int vtype;
+	unsigned int vdata;
+};
+
+struct MACVlanSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int index;
+	unsigned int mvdata;
+};
+
+/*--------------- Special Data Structures for MAC ---------------*/
+struct MACSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	char mac[6];
+};
+
+/*--------------- Special Data Structures for TCP Flag ---------------*/
+struct TcpFlagSetting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int index;
+	int fdata;
+};
+
+/*--------------- Special Data Structures for IPv6 ---------------*/
+struct IPv6Setting{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int header;
+	int act;
+};
+
+/*--------------- Special Data Structures for MIB Counter ---------------*/
+#define NUM_MIB_COUNTER_RX  24
+#define NUM_MIB_COUNTER_TX  20
+
+struct MIBCounterData{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int port;
+	int dir;
+	int idx;
+	unsigned long counter;
+};
+
+struct MIBCounterEntry{
+	unsigned long RX_counter[NUM_MIB_COUNTER_RX];
+	unsigned long TX_counter[NUM_MIB_COUNTER_TX];
+};
+
+struct MIBCounterEntry_all{
+	struct MIBCounterEntry entry[MAX_PHY_NUM];
+};
+
+/*--------------- Special Data Structures for QOS ---------------*/
+struct qos_dscp_setting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned char dscpentry;
+	unsigned char dscpvalue;
+	unsigned char dscpqueue;
+};
+
+struct qos_modesettings
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int groupnum;
+	int queuenum;
+	int modesettings;
+};
+
+struct qos_remap
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int port;
+	unsigned char queue;
+	unsigned char remap;
+};
+/*--------------- Special Data Structures for ACL ---------------*/
+struct acl_man {
+	struct list_head	rule_list;
+
+	int num_used_rules;
+	int num_used_entries;
+
+	// IP1811 has 64 entries
+	unsigned short	used_entry_mask[4];
+};
+
+#define		ACL_RULE_FUNC_USED_ACL		BIT(0)
+#define		ACL_RULE_FUNC_USED_MCP		BIT(1)
+#define		ACL_RULE_FUNC_USED_SNOOP	BIT(2)
+#define		ACL_RULE_FUNC_USED_DOS		BIT(3)
+
+struct acl_man_rule {
+	struct list_head	rule_entry;
+	int start_block;
+	int start_index;
+	int num_entries;
+	int rule_index;
+	unsigned int func_used;		// bit 0 : acl
+					// bit 1 : mcp
+					// bit 2 : dhcp snooping
+};
+
+enum {
+	ACL_SELECT_MODE_0001 = 1,
+	ACL_SELECT_MODE_0010,
+	ACL_SELECT_MODE_0100 = 4,
+	ACL_SELECT_MODE_0101,
+	ACL_SELECT_MODE_0110,
+	ACL_SELECT_MODE_0111,
+	ACL_SELECT_MODE_1x00,
+	ACL_SELECT_MODE_1x01,
+	ACL_SELECT_MODE_1x10,
+	ACL_SELECT_MODE_1x11,
+};
+#define		ACL_SELECT_MODE_BIT_0010			BIT(ACL_SELECT_MODE_0010)
+#define		ACL_SELECT_MODE_BIT_0100			BIT(ACL_SELECT_MODE_0100)
+#define		ACL_SELECT_MODE_BIT_0101			BIT(ACL_SELECT_MODE_0101)
+#define		ACL_SELECT_MODE_BIT_0110			BIT(ACL_SELECT_MODE_0110)
+#define		ACL_SELECT_MODE_BIT_0111			BIT(ACL_SELECT_MODE_0111)
+#define		ACL_SELECT_MODE_BIT_1x00			BIT(ACL_SELECT_MODE_1x00)
+#define		ACL_SELECT_MODE_BIT_1x01			BIT(ACL_SELECT_MODE_1x01)
+#define		ACL_SELECT_MODE_BIT_1x10			BIT(ACL_SELECT_MODE_1x10)
+#define		ACL_SELECT_MODE_BIT_1x11			BIT(ACL_SELECT_MODE_1x11)
+enum {
+	ACL_LINK_TYPE_00 = 0,
+	ACL_LINK_TYPE_01,
+	ACL_LINK_TYPE_10,
+	ACL_LINK_TYPE_11,
+};
+
+#define		ACL_RULE_VALID_SMAC		BIT(0)
+#define		ACL_RULE_VALID_DMAC		BIT(1)
+#define		ACL_RULE_VALID_SIP		BIT(2)
+#define		ACL_RULE_VALID_SIP_MASK		BIT(3)
+#define		ACL_RULE_VALID_DIP		BIT(4)
+#define		ACL_RULE_VALID_DIP_MASK		BIT(5)
+#define		ACL_RULE_VALID_SIP6		BIT(6)
+#define		ACL_RULE_VALID_SIP6_MASK	BIT(7)
+#define		ACL_RULE_VALID_DIP6		BIT(8)
+#define		ACL_RULE_VALID_DIP6_MASK	BIT(9)
+#define		ACL_RULE_VALID_ETH_TYPE		BIT(10)
+#define		ACL_RULE_VALID_VLAN		BIT(11)
+#define		ACL_RULE_VALID_COS		BIT(12)
+#define		ACL_RULE_VALID_SP_R		BIT(13)
+#define		ACL_RULE_VALID_DP_R		BIT(14)
+#define		ACL_RULE_VALID_DSCP		BIT(15)
+#define		ACL_RULE_VALID_IP_PROT		BIT(16)
+#define		ACL_RULE_VALID_INGRESS_PORT	BIT(17)
+#define		ACL_RULE_VALID_USERDEF_OFFSET	BIT(18)
+
+#define		ACL_RULE_RVS_SMAC		BIT(0)
+#define		ACL_RULE_RVS_DMAC		BIT(1)
+#define		ACL_RULE_RVS_SIP		BIT(2)
+#define		ACL_RULE_RVS_SIP_MASK		BIT(3)
+#define		ACL_RULE_RVS_DIP		BIT(4)
+#define		ACL_RULE_RVS_DIP_MASK		BIT(5)
+#define		ACL_RULE_RVS_SIP6		BIT(6)
+#define		ACL_RULE_RVS_SIP6_MASK		BIT(7)
+#define		ACL_RULE_RVS_DIP6		BIT(8)
+#define		ACL_RULE_RVS_DIP6_MASK		BIT(9)
+#define		ACL_RULE_RVS_ETH_TYPE		BIT(10)
+#define		ACL_RULE_RVS_VLAN		BIT(11)
+#define		ACL_RULE_RVS_COS		BIT(12)
+#define		ACL_RULE_RVS_SP_R		BIT(13)
+#define		ACL_RULE_RVS_DP_R		BIT(14)
+#define		ACL_RULE_RVS_DSCP		BIT(15)
+#define		ACL_RULE_RVS_IP_PROT		BIT(16)
+#define		ACL_RULE_RVS_INGRESS_PORT	BIT(17)
+#define		ACL_RULE_RVS_USERDEF_OFFSET	BIT(18)
+
+#define		ACL_ACT_VALID_REDIR		BIT(0)
+#define		ACL_ACT_VALID_PRI		BIT(1)
+#define		ACL_ACT_VALID_DSCP		BIT(2)
+#define		ACL_ACT_VALID_CPU		BIT(3)
+#define		ACL_ACT_VALID_SNIFFER		BIT(4)
+#define		ACL_ACT_VALID_PTP		BIT(5)
+#define		ACL_ACT_VALID_SFLOW		BIT(6)
+#define		ACL_ACT_VALID_CTAG		BIT(7)
+#define		ACL_ACT_VALID_STAG		BIT(8)
+#define		ACL_ACT_VALID_BW		BIT(9)
+#define		ACL_ACT_VALID_STORM		BIT(10)
+#define		ACL_ACT_VALID_MIB_COUNTER	BIT(11)
+
+#define		ACL_ACT_TYPE_3			3
+
+struct acl_rule
+{
+	// rule
+	unsigned long	rule_valid;			// bit 0 : smac
+							// bit 1 : dmac
+							// bit 2 : sip
+							// bit 3 : sip_mask
+							// bit 4 : dip
+							// bit 5 : dip_mask
+							// bit 6 : sip6
+							// bit 7 : sip6_mask
+							// bit 8 : dip6
+							// bit 9 : dip6_mask
+							// bit 10: eth_type
+							// bit 11: vlan
+							// bit 12: cos
+							// bit 13: sp_range
+							// bit 14: dp_range
+							// bit 15: dscp
+							// bit 16: ip_prot
+							// bit 17: ingress_port
+	// reverse
+	unsigned long	rule_rvs;			// bit 0 : smac
+							// bit 1 : dmac
+							// bit 2 : sip
+							// bit 3 : sip_mask
+							// bit 4 : dip
+							// bit 5 : dip_mask
+							// bit 6 : sip6
+							// bit 7 : sip6_mask
+							// bit 8 : dip6
+							// bit 9 : dip6_mask
+							// bit 10: eth_type
+							// bit 11: vlan
+							// bit 12: cos
+							// bit 13: sp_range
+							// bit 14: dp_range
+							// bit 15: dscp
+							// bit 16: ip_prot
+							// bit 17: ingress_port
+
+	unsigned char	smac[6];
+	unsigned char	dmac[6];
+
+	union{
+		unsigned long	sip4;
+		unsigned short	sip6[8];
+	}sip;
+#define sip4_addr	sip.sip4
+#define sip6_addr16	sip.sip6
+	unsigned char	sip_mask;			
+		// IPv4	0 - FF:FF:FF:FF	IPv6 	0 - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF(0x00)
+		// 	1 - FF:FF:FF:00		1 - FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:0000:0000(0x3C)
+		// 	2 - FF:FF:00:00		2 - FFFF:FFFF:FFFF:FFFF:0000:0000:0000:0000(0x3D)
+		// 	4 - FF:00:00:00		3 - FFFF:FFFF:0000:0000:0000:0000:0000:0000(0x3F)
+		// 	8 - F0:00:00:00		4 - FFFF:0000:0000:0000:0000:0000:0000:0000(0xFF)
+	union{
+		unsigned long	dip4;
+		unsigned short	dip6[8];
+	}dip;
+#define dip4_addr	dip.dip4
+#define dip6_addr16	dip.dip6
+	unsigned char	dip_mask;
+
+	unsigned short	eth_type;
+	unsigned short	vlan;
+	unsigned short	cos;
+	unsigned short	sp_hi;
+	unsigned short	sp_lo;
+	unsigned short	dp_hi;
+	unsigned short	dp_lo;
+	unsigned char	r_dscp;
+	unsigned char	ip_prot;
+	unsigned char	ingress_port;
+
+	// action
+	int		act_type;		// value = 0 ~ 2, type 3 need a acl entry
+							// 0 for drop
+							// 1 for Act_0 = b'0
+							// 2 for Act_1 = b'1
+							// 3 for Act_0001
+
+	unsigned long	act_valid;		// bit 0 : redir
+						// bit 1 : pri
+						// bit 2 : dscp
+						// bit 3 : cpu
+						// bit 4 : mirror
+						// bit 5 : ptp
+						// bit 6 : sflow
+						// bit 7 : ctag
+						// bit 8 : stag
+						// bit 9 : bw
+						// bit 10: storm 
+						// bit 11: mib_counter 
+	unsigned int	redir:5;
+	unsigned int	pri:3;
+	unsigned int	a_dscp:3;
+	unsigned int	cpu:1;
+	unsigned int	mirror:1;
+	unsigned int	ptp:1;
+	unsigned int	sflow:1;
+	unsigned short	ctag;
+	unsigned short	stag;
+	unsigned short	bw;
+	unsigned short	storm;
+	unsigned short	mib_counter;
+
+	/* User define 64 bytes offset */
+					//one bit for 2 bytes offset
+	unsigned short location1;	//[4:0] user0
+					//[9:5] user1
+	unsigned short location2;	//[4:0] user2
+					//[9:5] user3
+
+	unsigned short usr0;
+	unsigned short usr0_start;
+	unsigned short usr1;
+	unsigned short usr1_start;
+	unsigned short usr2;
+	unsigned short usr3;
+
+	unsigned short mask0;
+	unsigned short mask1;
+	unsigned short mask2;
+	unsigned short mask3;
+};
+
+struct AclRuleSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned int find_index_blockn; // find index start from block n and return used block actually.
+	unsigned int find_index_rvs; // in block, find index in reverse or not
+	unsigned int rule_index;
+	unsigned int func_used;
+	int rule_index_res;
+	struct acl_rule rule;
+	unsigned long reserved;			// show the used entry numbers for ip1811
+};
+
+struct AclGeneralSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int index;
+	int data;
+};
+
+struct AclEntryMaskGetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned short mask[4];
+};
+
+struct AclTableCleanSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	int rule_idx;
+	int func_used;
+};
+
+/*--------------- Special Data Structures for EEPROM ---------------*/
+struct EepromSetting
+{
+	void *nextcmd;
+	unsigned long size_nextcmd;
+	unsigned long cmdid;
+	unsigned short addr;
+	unsigned char value;
+};
+
+#endif		/* IP1811DS_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811fdat.c b/kernel/drivers/net/ethernet/ip1811/ip1811fdat.c
new file mode 100644
index 0000000..e467128
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811fdat.c
@@ -0,0 +1,466 @@
+#include "ip1811fdat.h"
+
+int (*func_of_common_smi[NUM_COMMON_SMI])(void *cdata, int len) =
+{
+	&setPortAN,
+	&getPortAN,
+	&setPortSpeed,
+	&getPortSpeed,
+	&setPortDuplex,
+	&getPortDuplex,
+	&setPortPause,
+	&getPortPause,
+	&setPortAsymPause,
+	&getPortAsymPause,
+	&setPortLinkStatus,
+	&getPortLinkStatus,
+	&setPortBackpressure,
+	&getPortBackpressure,
+	&setPortPowerDown,
+	&getPortPowerDown,
+	&setPortForceLink,
+	&getPortForceLink,
+	&setPortUniDirection,
+	&getPortUniDirection,
+};
+
+int (*func_of_common_cap[NUM_COMMON_CAP])(void *cdata, int len) =
+{
+	&setL2CapAct,
+	&setCapInBand,
+	&setCapSwitchMac,
+	&setCapIpv6TcpUdpEnable,
+};
+
+int (*func_of_common_lut[NUM_COMMON_LUT])(void *cdata, int len) =
+{
+	&setSMACLearning,
+	&getSMACLearning,
+	&setLutPortFlush,
+	&setLutAgingTime,
+	&getLutAgingTime,
+	&setLutAgingTimeEnable,
+	&setLutLearningNullSA,
+	&setLutHashingAlgorithm,
+	&setLutBindingEnable,
+	&getLutBindingEnable,
+};
+
+int (*func_of_common_sniffer[NUM_COMMON_SNIFFER])(void *cdata, int len) =
+{
+	&setSnifferSrc,
+	&getSnifferSrc,
+	&setSnifferDestGrp1,
+	&getSnifferDestGrp1,
+	&setS1Method,
+	&getS1Method,
+};
+
+int (*func_of_common_storm[NUM_COMMON_STORM])(void *cdata, int len) =
+{
+	&setStormFunc,
+	&getStormFunc,
+	&setStormThreshold,
+	&getStormThreshold,
+	&setStormCntrClrPeriod,
+	&getStormCntrClrPeriod,
+	&setStormBlockFrm2Cpu,
+	&getStormBlockFrm2Cpu,
+	&setStormDropInterrupt,
+	&getStormDropInterrupt,
+};
+
+int (*func_of_common_eoc[5])(void *cdata, int len) =
+{
+};
+
+int (*func_of_common_ld[NUM_COMMON_LOOP_DETECT])(void *cdata, int len) =
+{
+	&setLdFunc,
+	&getLdFunc,
+	&setLdTimeUnit,
+	&getLdTimeUnit,
+	&setLdPktSendTimer,
+	&getLdPktSendTimer,
+	&setLdBlockReleaseTimer,
+	&getLdBlockReleaseTimer,
+	&getLdStatus,
+};
+
+int (*func_of_common_wol[12])(void *cdata, int len) =
+{
+};
+
+int (*func_of_common_stag[NUM_COMMON_STAG])(void *cdata, int len) =
+{
+	&setCpuPortLink,
+	&setSTagFunc,
+	&getSTagTypeLen,
+	&configCpuPort,
+	&getCpuPort,
+};
+
+int (*func_of_common_misc[NUM_COMMON_MISC])(void *cdata, int len) =
+{
+	&set8021xFunc,
+	&get8021xFunc,
+	&setReg,
+	&getReg,
+	&setCPUReg,
+	&getCPUReg,
+	&setSwitchRestart,
+	&setSwitchReset,
+	&setCpuIfSpeed,
+	&setEepromByte,
+	&getEepromByte,
+};
+
+int (*func_of_common_vlan[NUM_COMMON_VLAN])(void *cdata, int len) =
+{
+	&setVlanEgressFrame,		//0
+	&getVlanEgressFrame,
+	&setVlanTagging,
+	&setVlanType,
+
+	&setVlanGroup,
+
+	&setVlanQinQPType,			//5
+	&setVlanQinQPAddtag,
+	&getVlanQinQPAddtag,
+	&setVlanQinQPRmvtag,
+	&getVlanQinQPRmvtag,
+	&setVlanQinQPRxdet,			//10
+	&getVlanQinQPRxdet,
+	&setVlanQinQPKeep,
+	&getVlanQinQPKeep,
+	&setVlanQinQPIndex,
+	&getVlanQinQPIndex,			//15
+	&setVlanQinQIndex,
+	&setVlanQinQStagSelectMethod,
+
+	&setVlanPortAddtag,
+	&getVlanPortAddtag,
+	&setVlanPortRmvtag,			//20
+	&getVlanPortRmvtag,
+	&setVlanPortForce,
+	&getVlanPortForce,
+	&setVlanPortUplink,
+	&getVlanPortUplink,			//25
+	&setVlanPortExclusive,
+	&getVlanPortExclusive,
+	&setVlanPortEgress,
+	&getVlanPortEgress,
+	&setVlanPortIngressFrame,	//30
+	&setVlanPortIngressCheck,
+	&getVlanPortIngressCheck,
+	&setVlanPortVid,
+
+	&setVlanProtocolMode,
+	&setVlanProtocolVid,		//35
+	&setVlanProtocolType,
+
+	&setVlanProtocolClear,
+	&setVlanMACBased,
+	&setVlanMACBasedtableconfig,
+	&getVlanMACBasedtableconfig,		//40
+	&setVlanMACBasedunknown,
+};
+
+int (*func_of_common_stp[NUM_COMMON_STP])(void *cdata, int len) =
+{
+	&setMstpFunc,
+	&getMstpFunc,
+};
+
+int (*func_of_common_lacp[NUM_COMMON_LACP])(void *cdata, int len) =
+{
+	&setTrunkHashMthd,
+	&getTrunkHashMthd,
+	&setTrunkMbr,
+	&getTrunkMbr,
+	&setCpuNCareTrunkAndVlan,
+	&getCpuNCareTrunkAndVlan,
+};
+
+int (*func_of_common_imp[8])(void *cdata, int len) =
+{
+};
+
+int (*func_of_common_cos[NUM_COMMON_TCPUDP])(void *cdata, int len) =
+{
+	&setCosTcpUdpUserDefine,
+	&getCosTcpUdpUserDefine,
+	&setCosTcpUdpQueue,
+	&getCosTcpUdpQueue,
+	&setCosTcpUdpEnable,
+	&getCosTcpUdpEnable,
+	&setCosTcpEnable,
+	&getCosTcpEnable,
+	&setCosUdpEnable,
+	&getCosUdpEnable,
+	&setCosTcpFlagDropNull,
+	&getCosTcpFlagDropNull,
+	&setCosTcpFlagDropAllset,
+	&getCosTcpFlagDropAllset,
+	&setCosTcpFlag,
+	&getCosTcpFlag,
+	&setCosTcpFlagAct,
+	&getCosTcpFlagAct,
+	&setCosTcpFlagPort,
+	&getCosTcpFlagPort,
+};
+
+int (*func_of_common_bandwidth[NUM_COMMON_BANDWIDTH])(void *cdata, int len) =
+{
+	&setBandwidthIngressRate,
+	&getBandwidthIngressRate,
+	&setBandwidthEgressRate,
+	&getBandwidthEgressRate,
+	&setBandwidthEgressPeriod,
+	&getBandwidthEgressPeriod,
+};
+/* ---------------- functions of ip1811 ---------------------------*/
+int (*func_of_ip1811_lut[NUM_1811_LUT])(void *cdata, int len) =
+{
+	&setLutUnknownSARule,
+	&setLutEntry,
+	&getLutEntry,
+	&getLutValidEntry,
+};
+
+int (*func_of_ip1811_sniffer[NUM_1811_SNIFFER])(void *cdata, int len) =
+{
+	&setS1PktModify,
+	&getS1PktModify,
+	&setS1TM4CpuSTag,
+	&getS1TM4CpuSTag,
+	&setS1TM4Acl2Cpu,
+	&getS1TM4Acl2Cpu,
+	&setS1TM4Pkt2MPort,
+	&getS1TM4Pkt2MPort,
+	&setS2LTT4Grp1,
+	&getS2LTT4Grp1,
+};
+
+int (*func_of_ip1811_storm[NUM_1811_STORM])(void *cdata, int len) =
+{
+	&setMStormNBlockIpPkt,
+	&getMStormNBlockIpPkt,
+	&setMStormIgnr01005EXXXXXX,
+	&getMStormIgnr01005EXXXXXX,
+};
+
+int (*func_of_ip1811_eoc[3])(void *cdata, int len) =
+{
+};
+
+int (*func_of_ip1811_ld[NUM_1811_LOOP_DETECT])(void *cdata, int len) =
+{
+	&setLdDMAC,
+	&setLdSubType,
+};
+
+int (*func_of_ip1811_wol[6])(void *cdata, int len) =
+{
+};
+
+int (*func_of_ip1811_misc[15])(void *cdata, int len) =
+{
+};
+
+int (*func_of_ip1811_stp[NUM_1811_STP])(void *cdata, int len) =
+{
+	&setBpduCapMode,
+	&getBpduCapMode,
+	&setBpduPortAct,
+	&getBpduPortAct,
+	&setStpPortState,
+	&getStpPortState,
+};
+
+int (*func_of_ip1811_lacp[NUM_1811_LACP])(void *cdata, int len) =
+{
+	&setTrunkHashMthdSeq,
+	&getTrunkHashMthdSeq,
+	&setTrunkGrpCombine,
+	&getTrunkGrpCombine,
+};
+
+int (*func_of_ip1811_igmp[NUM_1811_IGMP])(void *cdata, int len) =
+{
+	&setIGMPSnooping,
+	&getIGMPSnooping,
+	&setIGMPMctByCPU,
+	&getIGMPMctByCPU,
+	&setIGMPRltByCPU,
+	&getIGMPRltByCPU,
+	&setIGMPPktForward,
+	&getIGMPPktForward,
+	&setIGMPRlt,
+	&getIGMPRlt,
+	&setIGMPHashMethod,
+	&getIGMPHashMethod,
+	&setIGMPMldRule,
+	&getIGMPMldRule,
+	&setIGMPMctTable,
+	&getIGMPMctTable,
+	&setIGMPSltTable,
+	&getIGMPSltTable,
+};
+
+int (*func_of_ip1811_ptp[NUM_1811_PTP])(void *cdata, int len)=
+{
+	&setPTPEnable,
+	&getPTPEnable,
+	&setPTPDA011B19000000,
+	&getPTPDA011B19000000,
+	&setPTPDA0180C200000E,
+	&getPTPDA0180C200000E,
+	&setPTPUdpDP,
+	&getPTPUdpDP,
+	&setPTPUdpSP,
+	&getPTPUdpSP,
+	&setPTPToCPU,
+	&getPTPToCPU,
+	&setPTPSpecialTag,
+	&getPTPSpecialTag,
+	&setPTPClockReset,
+	&getPTPTimeStamp,
+	&setPTPClockEnable,
+	&getPTPClockEnable,
+	&setPTPOverwriteEnable,
+	&getPTPOverwriteEnable,
+	&setPTPProgrammable,
+	&getPTPProgrammable,
+	&setPTPProgrammableOut,
+	&setPTPTimestampEnable,
+	&getPTPTimestampEnable,
+	&setPTPTimestampClear,
+	&setPTPTimeData,
+	&getPTPTimeData,
+	&addPTPTimeData,
+	&subPTPTimeData,
+	&setPTPFrequencyAdd,
+	&getPTPFrequencyAdd,
+	&setPTPClockPeriod,
+	&getPTPClockPeriod,
+	&setPTPProgrammableConfig,
+	&setPTPDurationFrequencyCompensation,
+	&setPTPAlwaysFrequencyCompensation,
+	&getPTPIngressLatency10,
+	&getPTPIngressLatency100,
+	&getPTPIngressLatencyFiber,
+	&getPTPEgressLatency10,
+	&getPTPEgressLatency100,
+	&getPTPEgressLatencyFiber,
+};
+
+int (*func_of_ip1811_imp[2])(void *cdata, int len) =
+{
+};
+
+int (*func_of_ip1811_vlan[NUM_IP1811_VLAN])(void *cdata, int len) =
+{
+	&setVlanEntryMember,
+	&setVlanEntryAddtag,
+	&setVlanEntryRmvtag,
+	&setVlanEntryPriority,
+	&setVlanEntryFid,
+	&getVlanEntryFid,
+	&setVlanEntryClear,
+};
+
+int (*func_of_ip1811_mib_counter[NUM_1811_MIB_COUNTER])(void *cdata, int len) =
+{
+	&setMibCounterEnable,
+	&getMibCounterEnable,
+	&getMibCounterAll,
+	&getMibCounterByPort,
+	&getMibCounterByItem,
+};
+
+int (*func_of_ip1811_qos[NUM_IP1811_QOS])(void *cdata, int len) =
+{
+	&setQOSAgingFunction,
+	&getQOSAgingFunction,
+	&setQOSAgingTime,
+	&getQOSAgingTime,
+	&setQOSFastAging,
+	&getQOSFastAging,
+	&setCOSIGMP,
+	&getCOSIGMP,
+	&setCOSMACAddress,
+	&getCOSMACAddress,
+	&setCOSVID,
+	&getCOSVID,
+	&setCOSTCPUDPPort,
+	&getCOSTCPUDPPort,
+	&setCOSDSCP,
+	&getCOSDSCP,
+	&setCOS8021P,
+	&getCOS8021P,
+	&setCOSPhsicalPort,
+	&getCOSPhsicalPort,
+	&setCOSPortQueue,
+	&getCOSPortQueue,
+	&setCOS8021PEdtion,
+	&getCOS8021PEdtion,
+	&setCOSDSCPBaseDSCP,
+	&getCOSDSCPBaseDSCP,
+	&setCOSDSCPBaseNoMatchAction,
+	&getCOSDSCPBaseNoMatchAction,
+	&setQOSmodeGroupMember,
+	&getQOSmodeGroupMember,
+	&setQOSGroupBEn,
+	&getQOSGroupBEn,
+	&setQOSMode,
+	&getQOSMode,
+	&setQOSMethod,
+	&getQOSMethod,
+	&setQOSWeight,
+	&getQOSWeight,
+	&setQOSMaxBandwidth,
+	&getQOSMaxBandwidth,
+	&setQOSUnit,
+	&getQOSUnit,
+	&setQOSRatioValue0Def,
+	&getQOSRatioValue0Def,
+	&setQOSSBMDBM,
+	&getQOSSBMDBM,
+	&setQOSDBMEn,
+	&getQOSDBMEn,
+	&setQOSRemap,
+	&getQOSRemap,
+};
+
+int (*func_of_ip1811_acl[NUM_IP1811_ACL])(void *cdata, int len) =
+{
+	&setAclRule,
+	&getAclRule,
+	&aclCleanTable,
+	&setAclFunctionEn,
+	&getAclFunctionEn,
+	&setAclEtherAfterTag,
+	&getAclEtherAfterTag,
+	&getAclUsedRules,
+	&getAclUsedEntries,
+	&getAclUsedEntryMask,
+	&setAclBW,
+	&getAclBW,
+	&setAclDscp,
+	&getAclDscp,
+	&setAclVidRemark,
+	&getAclVidRemark,
+	&setAclStormPeriod,
+	&getAclStormPeriod,
+	&setAclStorm,
+	&getAclStorm,
+};
+
+int (*func_of_ip1811_hsr[NUM_IP1811_HSR])(void *cdata, int len) =
+{
+	&setHSREnable,
+	&getHSREnable,
+	&setHSRMode,
+	&getHSRMode,
+};
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811fdat.h b/kernel/drivers/net/ethernet/ip1811/ip1811fdat.h
new file mode 100644
index 0000000..8b5d4cd
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811fdat.h
@@ -0,0 +1,550 @@
+#ifndef IP1811FDAT_H
+#define IP1811FDAT_H
+#include "ip1811.h"
+
+extern int (*func_of_common_smi[NUM_COMMON_SMI])(void *cdata, int len);
+extern int (*func_of_common_cap[NUM_COMMON_CAP])(void *cdata, int len);
+extern int (*func_of_common_lut[NUM_COMMON_LUT])(void *cdata, int len);
+extern int (*func_of_common_sniffer[NUM_COMMON_SNIFFER])(void *cdata, int len);
+extern int (*func_of_common_storm[NUM_COMMON_STORM])(void *cdata, int len);
+extern int (*func_of_common_eoc[5])(void *cdata, int len);
+extern int (*func_of_common_ld[NUM_COMMON_LOOP_DETECT])(void *cdata, int len);
+extern int (*func_of_common_wol[12])(void *cdata, int len);
+extern int (*func_of_common_stag[NUM_COMMON_STAG])(void *cdata, int len);
+extern int (*func_of_common_misc[NUM_COMMON_MISC])(void *cdata, int len);
+extern int (*func_of_common_vlan[NUM_COMMON_VLAN])(void *cdata, int len);
+extern int (*func_of_common_stp[NUM_COMMON_STP])(void *cdata, int len);
+extern int (*func_of_common_lacp[NUM_COMMON_LACP])(void *cdata, int len);
+extern int (*func_of_common_imp[8])(void *cdata, int len);
+extern int (*func_of_common_cos[NUM_COMMON_TCPUDP])(void *cdata, int len);
+extern int (*func_of_common_bandwidth[NUM_COMMON_BANDWIDTH])(void *cdata, int len);
+extern int (*func_of_ip1811_sniffer[NUM_1811_SNIFFER])(void *cdata, int len);
+extern int (*func_of_ip1811_storm[NUM_1811_STORM])(void *cdata, int len);
+extern int (*func_of_ip1811_eoc[3])(void *cdata, int len);
+extern int (*func_of_ip1811_ld[NUM_1811_LOOP_DETECT])(void *cdata, int len);
+extern int (*func_of_ip1811_wol[6])(void *cdata, int len);
+extern int (*func_of_ip1811_misc[15])(void *cdata, int len);
+extern int (*func_of_ip1811_stp[NUM_1811_STP])(void *cdata, int len);
+extern int (*func_of_ip1811_lacp[NUM_1811_LACP])(void *cdata, int len);
+extern int (*func_of_ip1811_lut[NUM_1811_LUT])(void *cdata, int len);
+extern int (*func_of_ip1811_igmp[NUM_1811_IGMP])(void *cdata, int len);
+extern int (*func_of_ip1811_ptp[NUM_1811_PTP])(void *cdata, int len);
+extern int (*func_of_ip1811_imp[2])(void *cdata, int len);
+extern int (*func_of_ip1811_vlan[NUM_IP1811_VLAN])(void *cdata, int len);
+extern int (*func_of_ip1811_mib_counter[NUM_1811_MIB_COUNTER])(void *cdata, int len);
+extern int (*func_of_ip1811_qos[NUM_IP1811_QOS])(void *cdata, int len);
+extern int (*func_of_ip1811_acl[NUM_IP1811_ACL])(void *cdata, int len);
+extern int (*func_of_ip1811_hsr[NUM_IP1811_HSR])(void *cdata, int len);
+
+int setPortAN(void *cdata, int len);
+int getPortAN(void *cdata, int len);
+int setPortSpeed(void *cdata, int len);
+int getPortSpeed(void *cdata, int len);
+int setPortDuplex(void *cdata, int len);
+int getPortDuplex(void *cdata, int len);
+int setPortPause(void *cdata, int len);
+int getPortPause(void *cdata, int len);
+int setPortAsymPause(void *cdata, int len);
+int getPortAsymPause(void *cdata, int len);
+int setPortLinkStatus(void *cdata, int len);
+int getPortLinkStatus(void *cdata, int len);
+int setPortBackpressure(void *cdata, int len);
+int getPortBackpressure(void *cdata, int len);
+int setPortPowerDown(void *cdata, int len);
+int getPortPowerDown(void *cdata, int len);
+int setPortForceLink(void *cdata, int len);
+int getPortForceLink(void *cdata, int len);
+int setPortUniDirection(void *cdata, int len);
+int getPortUniDirection(void *cdata, int len);
+int setMdioDivisor(void *cdata, int len);
+int setFalseLinkSolution(void *cdata, int len);
+
+int setL2CapAct(void *cdata, int len);
+int getL2CapAct(void *cdata, int len);
+int setCapInBand(void *cdata, int len);
+int getCapInBand(void *cdata, int len);
+int setCapInBandRestrict(void *cdata, int len);
+int getCapInBandRestrict(void *cdata, int len);
+int setCapInBandRestrictCfg(void *cdata, int len);
+int getCapInBandRestrictCfg(void *cdata, int len);
+int setCapSwitchMac(void *cdata, int len);
+int getCapSwitchMac(void *cdata, int len);
+int setCapL3Act(void *cdata, int len);
+int getCapL3Act(void *cdata, int len);
+int setCapL3User(void *cdata, int len);
+int getCapL3User(void *cdata, int len);
+int setCapEtherUser(void *cdata, int len);
+int getCapEtherUser(void *cdata, int len);
+int setCapIpv6TcpUdpEnable(void *cdata, int len);
+int getCapIpv6TcpUdpEnable(void *cdata, int len);
+int setCapIpv6TcpUdpFlagEnable(void *cdata, int len);
+int getCapIpv6TcpUdpFlagEnable(void *cdata, int len);
+int setCapIpv6StopFinding(void *cdata, int len);
+int getCapIpv6StopFinding(void *cdata, int len);
+int setCapIpv6ToAllPortsHigh(void *cdata, int len);
+int getCapIpv6ToAllPortsHigh(void *cdata, int len);
+int setCapIpv6ToCpuHigh(void *cdata, int len);
+int getCapIpv6ToCpuHigh(void *cdata, int len);
+int setCapIpv6Act(void *cdata, int len);
+int getCapIpv6Act(void *cdata, int len);
+int setCapIpv6User(void *cdata, int len);
+int getCapIpv6User(void *cdata, int len);
+int setCapIcmpv6User(void *cdata, int len);
+int getCapIcmpv6User(void *cdata, int len);
+
+int setSMACLearning(void *cdata, int len);
+int getSMACLearning(void *cdata, int len);
+int setSMACLrnCntCtrl(void *cdata, int len);
+int getSMACLrnCntCtrl(void *cdata, int len);
+int setSMACLrnThreshold(void *cdata, int len);
+int getSMACLrnThreshold(void *cdata, int len);
+int setLutPortFlush(void *cdata, int len);
+int setLutAgingTime(void *cdata, int len);
+int getLutAgingTime(void *cdata, int len);
+int setLutAgingTimeEnable(void *cdata, int len);
+int getLutAgingTimeEnable(void *cdata, int len);
+int setLutLearningNullSA(void *cdata, int len);
+int getLutLearningNullSA(void *cdata, int len);
+int setLutHashingAlgorithm(void *cdata, int len);
+int getLutHashingAlgorithm(void *cdata, int len);
+int setLutBindingEnable(void *cdata, int len);
+int getLutBindingEnable(void *cdata, int len);
+int setLutLearnPktDropByVlanIgsChk(void *cdata, int len);
+int getLutLearnPktDropByVlanIgsChk(void *cdata, int len);
+
+int setLutLearningMode(void *cdata, int len);
+int getLutLearningMode(void *cdata, int len);
+int setLutUnknownSARule(void *cdata, int len);
+int getLutUnknownSARule(void *cdata, int len);
+int setLutEntry(void *cdata, int len);
+int getLutEntry(void *cdata, int len);
+int getLutValidEntry(void *cdata, int len);
+
+int setSnifferSrc(void *cdata, int len);
+int getSnifferSrc(void *cdata, int len);
+int setSnifferDestGrp1(void *cdata, int len);
+int getSnifferDestGrp1(void *cdata, int len);
+int setSnifferDestGrp2(void *cdata, int len);
+int getSnifferDestGrp2(void *cdata, int len);
+int setS1Method(void *cdata, int len);
+int getS1Method(void *cdata, int len);
+
+int setStormFunc(void *cdata, int len);
+int getStormFunc(void *cdata, int len);
+int setStormThreshold(void *cdata, int len);
+int getStormThreshold(void *cdata, int len);
+int setStormCntrClrPeriod(void *cdata, int len);
+int getStormCntrClrPeriod(void *cdata, int len);
+int setStormBlockFrm2Cpu(void *cdata, int len);
+int getStormBlockFrm2Cpu(void *cdata, int len);
+int setStormDropInterrupt(void *cdata, int len);
+int getStormDropInterrupt(void *cdata, int len);
+
+int setEocFunc(void *cdata, int len);
+int getEocFunc(void *cdata, int len);
+int getEocStatus(void *cdata, int len);
+int setEocReleaseTime(void *cdata, int len);
+int getEocReleaseTime(void *cdata, int len);
+
+int setLdFunc(void *cdata, int len);
+int getLdFunc(void *cdata, int len);
+int setLdTimeUnit(void *cdata, int len);
+int getLdTimeUnit(void *cdata, int len);
+int setLdPktSendTimer(void *cdata, int len);
+int getLdPktSendTimer(void *cdata, int len);
+int setLdBlockReleaseTimer(void *cdata, int len);
+int getLdBlockReleaseTimer(void *cdata, int len);
+int getLdStatus(void *cdata, int len);
+
+int setWolFunc(void *cdata, int len);
+int getWolFunc(void *cdata, int len);
+int setWolMode(void *cdata, int len);
+int getWolMode(void *cdata, int len);
+int setWolInterrupt(void *cdata, int len);
+int getWolInterrupt(void *cdata, int len);
+int setWolIPUnit(void *cdata, int len);
+int getWolIPUnit(void *cdata, int len);
+int setWolIPThreshold(void *cdata, int len);
+int getWolIPThreshold(void *cdata, int len);
+int setWolStatusInSlaveMode(void *cdata, int len);
+int getWolStatus(void *cdata, int len);
+
+int setCpuPortLink(void *cdata, int len);
+int getCpuPortLink(void *cdata, int len);
+int setSTagFunc(void *cdata, int len);
+int getSTagFunc(void *cdata, int len);
+int setSTagTypeLen(void *cdata, int len);
+int getSTagTypeLen(void *cdata, int len);
+int configCpuPort(void *cdata, int len);
+int getCpuPort(void *cdata, int len);
+
+int setCosTcpUdpUserDefine(void *cdata, int len);
+int getCosTcpUdpUserDefine(void *cdata, int len);
+int setCosTcpUdpQueue(void *cdata, int len);
+int getCosTcpUdpQueue(void *cdata, int len);
+int setCosTcpUdpEnable(void *cdata, int len);
+int getCosTcpUdpEnable(void *cdata, int len);
+int setCosTcpEnable(void *cdata, int len);
+int getCosTcpEnable(void *cdata, int len);
+int setCosUdpEnable(void *cdata, int len);
+int getCosUdpEnable(void *cdata, int len);
+int setCosTcpFlagDropNull(void *cdata, int len);
+int getCosTcpFlagDropNull(void *cdata, int len);
+int setCosTcpFlagDropAllset(void *cdata, int len);
+int getCosTcpFlagDropAllset(void *cdata, int len);
+int setCosTcpFlag(void *cdata, int len);
+int getCosTcpFlag(void *cdata, int len);
+int setCosTcpFlagAct(void *cdata, int len);
+int getCosTcpFlagAct(void *cdata, int len);
+int setCosTcpFlagPort(void *cdata, int len);
+int getCosTcpFlagPort(void *cdata, int len);
+
+int setBandwidthIngressRate(void *cdata, int len);
+int getBandwidthIngressRate(void *cdata, int len);
+int setBandwidthEgressRate(void *cdata, int len);
+int getBandwidthEgressRate(void *cdata, int len);
+int setBandwidthEgressPeriod(void *cdata, int len);
+int getBandwidthEgressPeriod(void *cdata, int len);
+
+int setPTPEnable(void *cdata, int len);
+int getPTPEnable(void *cdata, int len);
+int setPTPDA011B19000000(void *cdata, int len);
+int getPTPDA011B19000000(void *cdata, int len);
+int setPTPDA0180C200000E(void *cdata, int len);
+int getPTPDA0180C200000E(void *cdata, int len);
+int setPTPUdpDP(void *cdata, int len);
+int getPTPUdpDP(void *cdata, int len);
+int setPTPUdpSP(void *cdata, int len);
+int getPTPUdpSP(void *cdata, int len);
+int setPTPToCPU(void *cdata, int len);
+int getPTPToCPU(void *cdata, int len);
+int setPTPSpecialTag(void *cdata, int len);
+int getPTPSpecialTag(void *cdata, int len);
+int setPTPClockReset(void *cdata, int len);
+int getPTPTimeStamp(void *cdata, int len);
+int setPTPClockEnable(void *cdata, int len);
+int getPTPClockEnable(void *cdata, int len);
+int setPTPOverwriteEnable(void *cdata, int len);
+int getPTPOverwriteEnable(void *cdata, int len);
+int setPTPProgrammable(void *cdata, int len);
+int getPTPProgrammable(void *cdata, int len);
+int setPTPProgrammableOut(void *cdata, int len);
+int setPTPTimestampEnable(void *cdata, int len);
+int getPTPTimestampEnable(void *cdata, int len);
+int setPTPTimestampClear(void *cdata, int len);
+int setPTPTimeData(void *cdata, int len);
+int getPTPTimeData(void *cdata, int len);
+int addPTPTimeData(void *cdata, int len);
+int subPTPTimeData(void *cdata, int len);
+int setPTPFrequencyAdd(void *cdata, int len);
+int getPTPFrequencyAdd(void *cdata, int len);
+int setPTPClockPeriod(void *cdata, int len);
+int getPTPClockPeriod(void *cdata, int len);
+int setPTPProgrammableConfig(void *cdata, int len);
+int setPTPDurationFrequencyCompensation(void *cdata, int len);
+int setPTPAlwaysFrequencyCompensation(void *cdata, int len);
+int getPTPIngressLatency10(void *cdata, int len);
+int getPTPIngressLatency100(void *cdata, int len);
+int getPTPIngressLatencyFiber(void *cdata, int len);
+int getPTPEgressLatency10(void *cdata, int len);
+int getPTPEgressLatency100(void *cdata, int len);
+int getPTPEgressLatencyFiber(void *cdata, int len);
+
+int setJumboPktFunc(void *cdata, int len);
+int getJumboPktFunc(void *cdata, int len);
+int set8021xFunc(void *cdata, int len);
+int get8021xFunc(void *cdata, int len);
+int setReg(void *cdata, int len);
+int getReg(void *cdata, int len);
+int setCPUReg(void *cdata, int len);
+int getCPUReg(void *cdata, int len);
+int setSwitchRestart(void *cdata, int len);
+int setSwitchReset(void *cdata, int len);
+int setCpuIfSpeed(void *cdata, int len);
+int setEepromByte(void *cdata, int len);
+int getEepromByte(void *cdata, int len);
+int get_mii_reg(void *cdata, int len);
+int set_mii_reg(void *cdata, int len);
+
+int setVlanEgressFrame(void *cdata, int len);
+int getVlanEgressFrame(void *cdata, int len);
+int setVlanTagging(void *cdata, int len);
+int getVlanTagging(void *cdata, int len);
+int setVlanType(void *cdata, int len);
+int getVlanType(void *cdata, int len);
+int setVlanGroup(void *cdata, int len);
+
+int setVlanQinQPType(void *cdata, int len);
+int getVlanQinQPType(void *cdata, int len);
+int setVlanQinQPAddtag(void *cdata, int len);
+int getVlanQinQPAddtag(void *cdata, int len);
+int setVlanQinQPRmvtag(void *cdata, int len);
+int getVlanQinQPRmvtag(void *cdata, int len);
+int setVlanQinQPRxdet(void *cdata, int len);
+int getVlanQinQPRxdet(void *cdata, int len);
+int setVlanQinQPKeep(void *cdata, int len);
+int getVlanQinQPKeep(void *cdata, int len);
+int setVlanQinQPIndex(void *cdata, int len);
+int getVlanQinQPIndex(void *cdata, int len);
+int setVlanQinQIndex(void *cdata, int len);
+int getVlanQinQIndex(void *cdata, int len);
+int setVlanQinQStagSelectMethod(void *cdata, int len);
+int getVlanQinQStagSelectMethod(void *cdata, int len);
+
+int setVlanPortAddtag(void *cdata, int len);
+int getVlanPortAddtag(void *cdata, int len);
+int setVlanPortRmvtag(void *cdata, int len);
+int getVlanPortRmvtag(void *cdata, int len);
+int setVlanPortForce(void *cdata, int len);
+int getVlanPortForce(void *cdata, int len);
+int setVlanPortUplink(void *cdata, int len);
+int getVlanPortUplink(void *cdata, int len);
+int setVlanPortExclusive(void *cdata, int len);
+int getVlanPortExclusive(void *cdata, int len);
+int setVlanPortEgress(void *cdata, int len);
+int getVlanPortEgress(void *cdata, int len);
+int setVlanPortIngressFrame(void *cdata, int len);
+int getVlanPortIngressFrame(void *cdata, int len);
+int setVlanPortIngressCheck(void *cdata, int len);
+int getVlanPortIngressCheck(void *cdata, int len);
+int setVlanPortMember(void *cdata, int len);
+int getVlanPortMember(void *cdata, int len);
+int setVlanPortVid(void *cdata, int len);
+int getVlanPortVid(void *cdata, int len);
+
+int setVlanProtocolMode(void *cdata, int len);
+int getVlanProtocolMode(void *cdata, int len);
+int setVlanProtocolVid(void *cdata, int len);
+int getVlanProtocolVid(void *cdata, int len);
+int setVlanProtocolType(void *cdata, int len);
+int getVlanProtocolType(void *cdata, int len);
+int setVlanProtocolClear(void *cdata, int len);
+int setVlanMACBased(void *cdata, int len);
+int setVlanMACBasedtableconfig(void *cdata, int len);
+int getVlanMACBasedtableconfig(void *cdata, int len);
+int setVlanMACBasedunknown(void *cdata, int len);
+
+int setVlanEntryMember(void *cdata, int len);
+int getVlanEntryMember(void *cdata, int len);
+int setVlanEntryAddtag(void *cdata, int len);
+int getVlanEntryAddtag(void *cdata, int len);
+int setVlanEntryRmvtag(void *cdata, int len);
+int getVlanEntryRmvtag(void *cdata, int len);
+int setVlanEntryPriority(void *cdata, int len);
+int getVlanEntryPriority(void *cdata, int len);
+int setVlanEntryFid(void *cdata, int len);
+int getVlanEntryFid(void *cdata, int len);
+int setVlanEntryClear(void *cdata, int len);
+
+int setMstpFunc(void *cdata, int len);
+int getMstpFunc(void *cdata, int len);
+
+int setTrunkHashMthd(void *cdata, int len);
+int getTrunkHashMthd(void *cdata, int len);
+int setTrunkMbr(void *cdata, int len);
+int getTrunkMbr(void *cdata, int len);
+int setCpuNCareTrunkAndVlan(void *cdata, int len);
+int getCpuNCareTrunkAndVlan(void *cdata, int len);
+
+int setImpMode(void *cdata, int len);
+int getImpMode(void *cdata, int len);
+int setImpPassNullIP(void *cdata, int len);
+int getImpPassNullIP(void *cdata, int len);
+int setImpHash(void *cdata, int len);
+int getImpHash(void *cdata, int len);
+int setImpPort(void *cdata, int len);
+int getImpPort(void *cdata, int len);
+
+int setImpEntry(void *cdata, int len);
+int getImpEntry(void *cdata, int len);
+
+int setIGMPSnooping(void *cdata, int len);
+int getIGMPSnooping(void *cdata, int len);
+int setIGMPMctByCPU(void *cdata, int len);
+int getIGMPMctByCPU(void *cdata, int len);
+int setIGMPRltByCPU(void *cdata, int len);
+int getIGMPRltByCPU(void *cdata, int len);
+int setIGMPPktForward(void *cdata, int len);
+int getIGMPPktForward(void *cdata, int len);
+int setIGMPRlt(void *cdata, int len);
+int getIGMPRlt(void *cdata, int len);
+int setIGMPHashMethod(void *cdata, int len);
+int getIGMPHashMethod(void *cdata, int len);
+int setIGMPMldRule(void *cdata, int len);
+int getIGMPMldRule(void *cdata, int len);
+int setIGMPMctTable(void *cdata, int len);
+int getIGMPMctTable(void *cdata, int len);
+int setIGMPSltTable(void *cdata, int len);
+int getIGMPSltTable(void *cdata, int len);
+
+
+int setS1PktModify(void *cdata, int len);
+int getS1PktModify(void *cdata, int len);
+int setS1TM4CpuSTag(void *cdata, int len);
+int getS1TM4CpuSTag(void *cdata, int len);
+int setS1TM4Acl2Cpu(void *cdata, int len);
+int getS1TM4Acl2Cpu(void *cdata, int len);
+int setS1TM4Pkt2MPort(void *cdata, int len);
+int getS1TM4Pkt2MPort(void *cdata, int len);
+int setS2LTT4Grp1(void *cdata, int len);
+int getS2LTT4Grp1(void *cdata, int len);
+int setS2LTT4Grp2(void *cdata, int len);
+int getS2LTT4Grp2(void *cdata, int len);
+
+int setMStormNBlockIpPkt(void *cdata, int len);
+int getMStormNBlockIpPkt(void *cdata, int len);
+int setMStormIgnr01005EXXXXXX(void *cdata, int len);
+int getMStormIgnr01005EXXXXXX(void *cdata, int len);
+
+int setEocBlockClr(void *cdata, int len);
+int setEocClrBlockWhenRcvGood(void *cdata, int len);
+int getEocClrBlockWhenRcvGood(void *cdata, int len);
+
+int setLdSMACB40(void *cdata, int len);
+int getLdSMACB40(void *cdata, int len);
+int setLdRerandom(void *cdata, int len);
+int getLdRerandom(void *cdata, int len);
+int setLdDMAC(void *cdata, int len);
+int getLdDMAC(void *cdata, int len);
+int setLdEtherType(void *cdata, int len);
+int getLdEtherType(void *cdata, int len);
+int setLdSubType(void *cdata, int len);
+int getLdSubType(void *cdata, int len);
+int setLdDeviceID(void *cdata, int len);
+int getLdDeviceID(void *cdata, int len);
+
+int setWolWakeIfTxGetAnyPkt(void *cdata, int len);
+int getWolWakeIfTxGetAnyPkt(void *cdata, int len);
+int setWolWakeIfRxGetAnyPkt(void *cdata, int len);
+int getWolWakeIfRxGetAnyPkt(void *cdata, int len);
+int setWolWakeIfMatchAcl2Cpu(void *cdata, int len);
+int getWolWakeIfMatchAcl2Cpu(void *cdata, int len);
+
+int setMACLoopBackFunc(void *cdata, int len);
+int getMACLoopBackFunc(void *cdata, int len);
+int setPausePktFunc(void *cdata, int len);
+int getPausePktFunc(void *cdata, int len);
+int setPausePktDest(void *cdata, int len);
+int getPausePktDest(void *cdata, int len);
+int setLocalTrafficFunc(void *cdata, int len);
+int getLocalTrafficFunc(void *cdata, int len);
+int setMACReset(void *cdata, int len);
+int getMACReset(void *cdata, int len);
+int setMACSelfTestFunc(void *cdata, int len);
+int getMACSelfTestFunc(void *cdata, int len);
+int setMACSelfTestPktNum(void *cdata, int len);
+int getMACSelfTestPktNum(void *cdata, int len);
+int getMACSelfTestResult(void *cdata, int len);
+
+int setBpduCapMode(void *cdata, int len);
+int getBpduCapMode(void *cdata, int len);
+int setBpduPortAct(void *cdata, int len);
+int getBpduPortAct(void *cdata, int len);
+int setStpPortState(void *cdata, int len);
+int getStpPortState(void *cdata, int len);
+int setStpAllPortsState(void *cdata, int len);
+int getStpAllPortsState(void *cdata, int len);
+
+int setTrunkHashMthdSeq(void *cdata, int len);
+int getTrunkHashMthdSeq(void *cdata, int len);
+int setTrunkGrpCombine(void *cdata, int len);
+int getTrunkGrpCombine(void *cdata, int len);
+
+int setMibCounterEnable(void *cdata, int len);
+int getMibCounterEnable(void *cdata, int len);
+int getMibCounterAll(void *cdata, int len);
+int getMibCounterByPort(void *cdata, int len);
+int getMibCounterByItem(void *cdata, int len);
+
+int setQOSAgingFunction(void *cdata, int len);
+int getQOSAgingFunction(void *cdata, int len);
+int setQOSAgingTime(void *cdata, int len);
+int getQOSAgingTime(void *cdata, int len);
+int setQOSFastAging(void *cdata, int len);
+int getQOSFastAging(void *cdata, int len); 
+  
+int setCOSIGMP(void *cdata, int len);
+int getCOSIGMP(void *cdata, int len);
+int setCOSMACAddress(void *cdata, int len);
+int getCOSMACAddress(void *cdata, int len);
+int setCOSVID(void *cdata, int len);
+int getCOSVID(void *cdata, int len);
+int setCOSTCPUDPPort(void *cdata, int len);
+int getCOSTCPUDPPort(void *cdata, int len);
+int setCOSDSCP(void *cdata, int len);
+int getCOSDSCP(void *cdata, int len);
+int setCOS8021P(void *cdata, int len);
+int getCOS8021P(void *cdata, int len);
+int setCOSPhsicalPort(void *cdata, int len);
+int getCOSPhsicalPort(void *cdata, int len);
+int setCOSPortQueue(void *cdata, int len);
+int getCOSPortQueue(void *cdata, int len);
+int setCOS8021PEdtion(void *cdata, int len);
+int getCOS8021PEdtion(void *cdata, int len);
+int setCOSDSCPBaseDSCP(void *cdata, int len);
+int getCOSDSCPBaseDSCP(void *cdata, int len);
+int setCOSDSCPBaseNoMatchAction(void *cdata, int len);
+int getCOSDSCPBaseNoMatchAction(void *cdata, int len);
+int setQOSmodeGroupMember(void *cdata, int len);
+int getQOSmodeGroupMember(void *cdata, int len);
+int setQOSGroupBEn(void *cdata, int len);
+int getQOSGroupBEn(void *cdata, int len);
+int setQOSMode(void *cdata, int len);
+int getQOSMode(void *cdata, int len);
+int setQOSMethod(void *cdata, int len);
+int getQOSMethod(void *cdata, int len);
+int setQOSWeight(void *cdata, int len);
+int getQOSWeight(void *cdata, int len);
+int setQOSMaxBandwidth(void *cdata, int len);
+int getQOSMaxBandwidth(void *cdata, int len);
+int setQOSUnit(void *cdata, int len);
+int getQOSUnit(void *cdata, int len);
+int setQOSRatioValue0Def(void *cdata, int len);
+int getQOSRatioValue0Def(void *cdata, int len);
+int setQOSSBMDBM(void *cdata, int len);
+int getQOSSBMDBM(void *cdata, int len);
+int setQOSDBMEn(void *cdata, int len);
+int getQOSDBMEn(void *cdata, int len);
+int setQOSEgressControl(void *cdata, int len);
+int getQOSEgressControl(void *cdata, int len);
+  
+int setQOSRemap(void *cdata, int len);
+int getQOSRemap(void *cdata, int len);
+
+void acl_init(void);
+int setAclRule(void *cdata, int len);
+int getAclRule(void *cdata, int len);
+int aclCleanTable(void *cdata, int len);
+int setAclFunctionEn(void *cdata, int len);
+int getAclFunctionEn(void *cdata, int len);
+int setAclEtherAfterTag(void *cdata, int len);
+int getAclEtherAfterTag(void *cdata, int len);
+int getAclUsedRules(void *cdata, int len);
+int getAclUsedEntries(void *cdata, int len);
+int getAclUsedEntryMask(void *cdata, int len);
+int setAclBW(void *cdata, int len);
+int getAclBW(void *cdata, int len);
+int setAclDscp(void *cdata, int len);
+int getAclDscp(void *cdata, int len);
+int setAclVidRemark(void *cdata, int len);
+int getAclVidRemark(void *cdata, int len);
+int setAclStormPeriod(void *cdata, int len);
+int getAclStormPeriod(void *cdata, int len);
+int setAclStorm(void *cdata, int len);
+int getAclStorm(void *cdata, int len);
+
+/*	ipv:	4:	IPv4
+ *			6:	IPv6
+ *	addr:	IP	address
+ *	method:	1:	Direct
+ *			0:	CRC
+ * */
+unsigned char tb_calc_index(unsigned char ipv, void *addr, unsigned char method);
+
+int setHSREnable(void *cdata, int len);
+int getHSREnable(void *cdata, int len);
+int setHSRMode(void *cdata, int len);
+int getHSRMode(void *cdata, int len);
+
+void noFunc(void);
+#endif		/* IP1811FDAT_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811func.c b/kernel/drivers/net/ethernet/ip1811/ip1811func.c
new file mode 100644
index 0000000..2edd2fe
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811func.c
@@ -0,0 +1,13309 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/uaccess.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <asm/io.h>
+
+#include "ip1811.h"
+#include "ip1811reg.h"
+#include "ip1811ds.h"
+#include "ip1811op.h"
+#include "ip1811fdat.h"
+#include "ip218.h"
+
+#define MII_OP_READ 0
+#define MII_OP_WRITE 1
+
+//#define TEST_REG
+//#define IP1811DEBUG
+//#define IP1811DRV_REG_DEBUG
+#ifdef	IP1811DRV_REG_DEBUG
+#define	ip1811drv_dbg(fmt, ...)	printk(KERN_DEBUG "<%s:%d>" fmt, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define	ip1811drv_dbg(...)
+#endif//IP1811DRV_REG_DEBUG
+
+#define IP1811DRV_REG_ERROR
+#ifdef	IP1811DRV_REG_ERROR
+#define	ip1811drv_err(fmt, ...)	printk(KERN_ERR "<%s:%d>" fmt, __func__, __LINE__, ##__VA_ARGS__)
+#else
+#define	ip1811drv_err(...)
+#endif//IP1811DRV_REG_ERROR
+
+#define FUNC_MSG_IN		ip1811drv_dbg("IN \n")
+#define FUNC_MSG_OUT	ip1811drv_dbg("OUT\n")
+
+extern u8 CPU_IF_SPEED_NORMAL;
+
+#ifdef TEST_REG
+u16 RegList[16][256];
+u8 pg;
+#endif//TEST_REG
+
+#define ip1811delay()		(udelay(100))
+
+/*=============   misc. driver functions   ===================*/
+
+//#define ACCESS_REG_BY_MDIO
+#ifdef ACCESS_REG_BY_MDIO
+//--------------  p1811 project GPIO MDIO Function ---------------------
+#define MDIO_DELAY	0
+#define MDIO_RD		0
+#define MDIO_WR		1
+#define GPIO_MDIO_OFFSET 10
+#define GPIO_MDC_OFFSET 11
+#include <asm/io.h>
+static DEFINE_MUTEX(ip1811_gpio_lock);
+#define IP1811_GPIO_BASE      0xBD700000
+#define IP1811_GPIO_OUTPUT_VALUE_2_OFFSET	0x003C
+#define IP1811_GPIO_OUTPUT_ENABLE_2_OFFSET	0x0040
+#define IP1811_GPIO_INPUT_VALUE_2_OFFSET	0x0038
+#define IP1811_GPIO_SET_VALUE_1 0x1
+#define IP1811_GPIO_SET_VALUE_0 0x0
+static int ip1811_gpio_get(unsigned offset)
+{
+	void __iomem				*base;
+	u32					val;
+
+	mutex_lock(&ip1811_gpio_lock);
+
+
+	base = IP1811_GPIO_BASE + IP1811_GPIO_INPUT_VALUE_2_OFFSET;
+	val = readl(base);
+	val = ((val & BIT(offset))>>offset);
+
+	mutex_unlock(&ip1811_gpio_lock);
+
+	return val;
+}
+static void ip1811_gpio_set(unsigned offset,int value)
+{
+	void __iomem				*base;
+	u32					val;
+
+	mutex_lock(&ip1811_gpio_lock);
+
+	base = IP1811_GPIO_BASE + IP1811_GPIO_OUTPUT_VALUE_2_OFFSET;
+	val = readl(base);
+	val = (value == IP1811_GPIO_SET_VALUE_1) ? (val | BIT(offset)) : (val & ~((BIT(offset))));
+	writel(val, base);
+
+	mutex_unlock(&ip1811_gpio_lock);
+
+	return;
+}
+static int ip1811_gpio_direction_out(unsigned offset,int value)
+{
+	void __iomem				*base;
+	u32					val;
+
+	mutex_lock(&ip1811_gpio_lock);
+
+	base = IP1811_GPIO_BASE + IP1811_GPIO_OUTPUT_ENABLE_2_OFFSET;
+	val = readl(base);
+	val |= BIT(offset);
+	writel(val, base);
+
+	mutex_unlock(&ip1811_gpio_lock);
+
+	return 0;
+}
+static int ip1811_gpio_direction_in( unsigned offset)
+{
+	void __iomem				*base;
+	u32					val;
+
+	mutex_lock(&ip1811_gpio_lock);
+
+	base = IP1811_GPIO_BASE + IP1811_GPIO_OUTPUT_ENABLE_2_OFFSET;
+	val = readl(base);
+	val &= ~(BIT(offset));
+	writel(val, base);
+
+	mutex_unlock(&ip1811_gpio_lock);
+
+	return val;
+}
+void mdio_1(void){
+
+	int i;
+	//set MDIO to 1
+	//set MDC to 0
+	ip1811_gpio_set(GPIO_MDIO_OFFSET,1);
+	ip1811_gpio_set(GPIO_MDC_OFFSET,0);
+
+	for(i=0;i<MDIO_DELAY;i++);
+
+	//set MDIO to 1
+	//set MDC to 1
+	ip1811_gpio_set(GPIO_MDIO_OFFSET,1);
+	ip1811_gpio_set(GPIO_MDC_OFFSET,1);
+
+	for(i=0;i<MDIO_DELAY;i++);
+}
+
+void mdio_0(void){
+
+	int i;
+	//set MDIO to 0
+	//set MDC to 0
+	ip1811_gpio_set(GPIO_MDIO_OFFSET,0);
+	ip1811_gpio_set(GPIO_MDC_OFFSET,0);
+
+	for(i=0;i<MDIO_DELAY;i++);
+
+	//set MDIO to 0
+	//set MDC to 1
+	ip1811_gpio_set(GPIO_MDIO_OFFSET,0);
+	ip1811_gpio_set(GPIO_MDC_OFFSET,1);
+
+	for(i=0;i<MDIO_DELAY;i++);
+}
+
+void mdio_z(void){
+
+	int i;
+	//set MDC to 0
+	ip1811_gpio_set(GPIO_MDC_OFFSET,0);
+
+	for(i=0;i<MDIO_DELAY;i++);
+	//set MDC to 1
+	ip1811_gpio_set(GPIO_MDC_OFFSET,1);
+
+	for(i=0;i<MDIO_DELAY;i++);
+}
+
+void mdio_start(void){
+	mdio_0();
+	mdio_1();
+}
+
+void mdio_rw(int rw){
+	if(rw==MDIO_RD){
+		mdio_1();
+		mdio_0();
+	}else{
+		mdio_0();
+		mdio_1();
+	}
+}
+void mdio_set_MDC_MDIO_direction(unsigned char mdc, unsigned char mdio)//0:input, 1:output for mdc/mdio values
+{
+	if(mdc) ;
+	if(mdio)
+		ip1811_gpio_direction_out(GPIO_MDIO_OFFSET,0);
+	else
+		ip1811_gpio_direction_in(GPIO_MDIO_OFFSET);
+}
+void ic_mdio_wr(unsigned short pa, unsigned short ra, unsigned short va){
+	int i=0;
+	unsigned short data=0;
+
+	//set MDC/MDIO pins to GPIO mode
+	ip1811_gpio_direction_out(GPIO_MDC_OFFSET,0);
+	ip1811_gpio_direction_out(GPIO_MDIO_OFFSET,0);
+
+	//set MDC direction to output
+	//set MDIO direction to output
+	mdio_set_MDC_MDIO_direction(1,1);
+
+	for(i=0;i<32;i++)
+		mdio_1();
+	mdio_start();
+	mdio_rw(MDIO_WR);
+	for(i=0;i<5;i++){
+		if((pa>>(5-1-i))%2)
+			mdio_1();
+		else
+			mdio_0();
+	}
+	for(i=0;i<5;i++){
+		if((ra>>(5-1-i))%2)
+			mdio_1();
+		else
+			mdio_0();
+	}
+	mdio_1();
+	mdio_0();
+	for(i=0;i<16;i++){
+		data=va<<i;
+		data=data>>15;
+		if(data==1)
+			mdio_1();
+		else
+			mdio_0();
+	}
+}
+unsigned short ic_mdio_rd(unsigned short pa, unsigned short ra){
+	int i=0,j=0;
+	unsigned short data=0;
+	int regBit;
+	unsigned char debug[16];
+
+	//set MDC/MDIO pins to GPIO mode
+	ip1811_gpio_direction_out(GPIO_MDC_OFFSET,0);
+	ip1811_gpio_direction_out(GPIO_MDIO_OFFSET,0);
+
+	//set MDC/MDIO PIN direction
+	//mdio_set_MDC_MDIO_dir();
+	//MDC direction set to output
+	//MDIO direction set to output
+	mdio_set_MDC_MDIO_direction(1,1);
+
+	for(i=0;i<32;i++)
+		mdio_1();
+	mdio_start();
+	mdio_rw(MDIO_RD);
+	for(i=0;i<5;i++){
+		if((pa>>(5-1-i))%2)
+			mdio_1();
+		else
+			mdio_0();
+	}
+	for(i=0;i<5;i++){
+		if((ra>>(5-1-i))%2)
+			mdio_1();
+		else
+			mdio_0();
+	}
+	mdio_z();
+	//MDIO DIR set to input
+	mdio_set_MDC_MDIO_direction(1,0);
+	mdio_0();
+
+
+	for(j=0;j<16;j++){
+		//MDC set to 0
+		ip1811_gpio_set(GPIO_MDC_OFFSET,0);
+
+		for(i=0;i<MDIO_DELAY;i++);
+		//get MDIO value
+		regBit=ip1811_gpio_get(GPIO_MDIO_OFFSET);
+		if(regBit==0)
+		{
+			data|=0;
+			debug[15-j]=0;
+		}
+		else
+		{
+			data|=1;
+			debug[15-j]=1;
+		}
+		if(j<15)
+			data=data<<1;
+		//MDC set to 1
+		ip1811_gpio_set(GPIO_MDC_OFFSET,1);
+
+		for(i=0;i<MDIO_DELAY;i++);
+	}
+	//MDC set to 0
+	ip1811_gpio_set(GPIO_MDC_OFFSET,0);
+
+	for(i=0;i<MDIO_DELAY;i++);
+	//MDC set to 1
+	ip1811_gpio_set(GPIO_MDC_OFFSET,1);
+
+	for(i=0;i<MDIO_DELAY;i++);
+
+	return data;
+}
+#else//#ifndef ACCESS_REG_BY_MDIO
+void ic_mdio_wr(unsigned short pa, unsigned short ra, unsigned short va){
+	void __iomem *base;
+	unsigned long val;
+	struct ip218_smictrl0 *smic0;
+
+	FUNC_MSG_IN;
+
+	val = 0;
+	smic0 = (struct ip218_smictrl0 *)&val;
+	smic0 -> phy = pa;
+	smic0 -> reg = ra;
+	smic0 -> wr_data = va;
+	smic0 -> rdwr = 1;//1: write cycle
+	smic0 -> en = 1;
+
+	base = (void __iomem *)(IP218_MAC_BASE + IP218_MAC_SMICTRL0);
+	ip1811drv_dbg("write [%p]=%08lX\n", base, val);
+	writel(val, base);
+
+	// wait for writing process done
+	do{
+		val = readl(base);
+	}while(smic0 -> en);
+
+	FUNC_MSG_OUT;
+}
+unsigned short ic_mdio_rd(unsigned short pa, unsigned short ra){
+	void __iomem	*base;
+	unsigned long val;
+	unsigned short ret;
+	struct ip218_smictrl0 *smic0;
+	struct ip218_smictrl1 *smic1;
+
+	FUNC_MSG_IN;
+
+	val = 0;
+	smic0 = (struct ip218_smictrl0 *)&val;
+	smic0 -> phy = pa;
+	smic0 -> reg = ra;
+	smic0 -> rdwr = 0;//0: read cycle
+	smic0 -> en = 1;
+
+	base = (void __iomem *)(IP218_MAC_BASE + IP218_MAC_SMICTRL0);
+	ip1811drv_dbg("write [%p]=%08lX\n", base, val);
+	writel(val, base);
+
+	// wait for writing process done
+	do{
+		val = readl(base);
+	}while(smic0 -> en);
+
+	// read data from register
+	base = (void __iomem *)(IP218_MAC_BASE + IP218_MAC_SMICTRL1);
+	val = readl(base);
+	smic1 = (struct ip218_smictrl1 *)&val;
+	ret = smic1 -> rd_data;
+	ip1811drv_dbg("read [%p]=%08lX\n", base, val);
+
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+#endif//ACCESS_REG_BY_MDIO
+
+void Write_Reg(u8 regaddr, u16 value)
+{
+	u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2;
+#ifdef TEST_REG
+	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, regaddr, RegList[pg][regaddr]);
+	RegList[pg][regaddr]=value;
+#else
+	ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,value);
+#endif//TEST_REG
+
+#ifdef TEST_REG
+	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, regaddr, RegList[pg][regaddr]);
+#endif//TEST_REG
+
+	ip1811drv_dbg("write [%02X]=%04x\n", regaddr, value);
+}
+u16 Read_Reg(u8 regaddr)
+{
+	u16 u16d;
+	u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2;
+#ifdef TEST_REG
+	u16d = RegList[pg][regaddr];
+#else
+	u16d=ic_mdio_rd(((tmp)>>5)&0x1f,(tmp)&0x1f);
+#endif//TEST_REG
+#ifdef TEST_REG
+	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, regaddr, RegList[pg][regaddr]);
+#endif//TEST_REG
+	ip1811drv_dbg("read [%02X]=%04x\n", regaddr, u16d);
+	return u16d;
+}
+
+void _Write_Reg(u8 regaddr, u16 value)
+{
+	u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2;
+	ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,value);
+
+	ip1811drv_dbg("write [%02X]=%04x\n", regaddr, value);
+}
+u16 _Read_Reg(u8 regaddr)
+{
+	u16 u16d;
+	u16 tmp = CPU_IF_SPEED_NORMAL ? regaddr : (u16)regaddr << 2;
+	u16d=ic_mdio_rd(((tmp)>>5)&0x1f,(tmp)&0x1f);
+	ip1811drv_dbg("read [%02X]=%04x\n", regaddr, u16d);
+	return u16d;
+}
+u16 Read_Reg_0_With_1s(void)
+{
+	u16 u16d;
+	u16 tmp = CPU_IF_SPEED_NORMAL ? 0x300 : 0x3;
+	u16d = ic_mdio_rd(((tmp)>>5)&0x1f,(tmp)&0x1f);
+	ip1811drv_dbg("read [%04X]=%04x\n", tmp, u16d);
+	return u16d;
+}
+void IP2Page(u8 page)		// Change page to pagenum
+{
+	u16 tmp = CPU_IF_SPEED_NORMAL ? REG_Page : (u16)REG_Page << 2;
+#ifdef TEST_REG
+	pg = page;
+#else
+	ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,page);
+#endif//TEST_REG
+	ip1811drv_dbg("set to  page[%02u]\n", page);
+}
+void _IP2Page(u8 page)		// Change page to pagenum
+{
+	u16 tmp = CPU_IF_SPEED_NORMAL ? REG_Page : (u16)REG_Page << 2;
+	ic_mdio_wr(((tmp)>>5)&0x1f,(tmp)&0x1f,page);
+	ip1811drv_dbg("set to  page[%02u]\n", page);
+}
+/*=============   sub. driver functions   ==================*/
+static void _WriteRegBits(u8 page, u16 reg, u8 offset, u8 len, u16 val)
+{
+	u16 mask = 0;
+	u16 u16dat;
+
+	FUNC_MSG_IN;
+
+	IP2Page(page);
+	mask = (0x1 << len) - 1;
+	u16dat = Read_Reg(reg);
+	u16dat &= ~(mask<<offset);
+	u16dat |= (val&mask)<<offset;
+	Write_Reg(reg, u16dat);
+
+	FUNC_MSG_OUT;
+}
+
+static u16 _ReadRegBits(u8 page, u16 reg, u8 offset, u8 len)
+{
+	u16 mask = 0;
+	u16 u16dat;
+	u16 val;
+
+	FUNC_MSG_IN;
+
+	IP2Page(page);
+	mask = (0x1 << len) - 1;
+	u16dat = Read_Reg(reg);
+	val = (u16dat>>offset)&mask;
+
+	FUNC_MSG_OUT;
+	return val;
+}
+#if 0
+u16 _read_mii_register(u8 phy, u8 page, u8 reg)
+{
+	u8 option = MII_OP_READ;
+	u16 u16dat = 0;
+	IP2Page(3);
+
+	// change phy page
+	Write_Reg(P3REG_PHYACCESS_DATA, page);
+	
+	u16dat = (phy & 0x1f); //PHY
+	u16dat |= (0x14 & 0x1f ) << 5; //MII Reg
+	u16dat |= (MII_OP_WRITE & 0x1 )<< 14;//Read or Write
+	u16dat |= 0x1 << 15;//Trigger & Write
+	
+	Write_Reg(P3REG_PHYACCESS_CMD, u16dat);
+	while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1));
+	udelay(5000);
+	
+	// phy read command
+	u16dat = 0;
+
+	u16dat = (phy & 0x1f);	//PHY
+	u16dat |= (reg & 0x1f ) << 5;//MII Reg
+	u16dat |= (option & 0x1 )<< 14;//Read or Write
+	u16dat |= 0x1 << 15;//Trigger & Write
+	
+	Write_Reg(P3REG_PHYACCESS_CMD, u16dat);
+	while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1));
+	udelay(5000);
+	
+	return Read_Reg(P3REG_PHYACCESS_DATA);
+
+}
+
+u16 _write_mii_register(u8 phy, u8 page, u8 reg, u16 val, u8 all)
+{
+	u8 option = MII_OP_WRITE;
+	u16 u16dat = 0;
+	u8 count = 0;
+	IP2Page(3);
+
+	// change phy page
+	do
+	{
+		Write_Reg(P3REG_PHYACCESS_DATA, page);
+	
+		u16dat = ((phy+(count*8)) & 0x1f); //PHY
+		u16dat |= (0x14 & 0x1f ) << 5; //MII Reg
+		u16dat |= (MII_OP_WRITE & 0x1 )<< 14;//Read or Write
+		u16dat |= 0x1 << 15;//Trigger & Write
+	
+		Write_Reg(P3REG_PHYACCESS_CMD, u16dat);
+		while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1));
+		udelay(5000);
+		count = count + 1;
+	}while(all&&(count<3));
+	
+	// phy write command
+	Write_Reg(P3REG_PHYACCESS_DATA, val);
+	u16dat = 0;
+	
+	u16dat = (phy & 0x1f); //PHY
+	u16dat |= (reg & 0x1f ) << 5; //MII Reg
+	u16dat |= (all & 0x1) << 10; // write to all 24 phy
+	u16dat |= (option & 0x1 )<< 14;//Read or Write
+	u16dat |= 0x1 << 15;//Trigger & Write
+	
+	Write_Reg(P3REG_PHYACCESS_CMD, u16dat);
+	while(_ReadRegBits(3, P3REG_PHYACCESS_CMD, 15, 1));
+	if(all)
+		udelay(30000);
+	else
+		udelay(5000);
+	
+	return 0;
+}
+
+int get_mii_reg(void *cdata, int len)
+{
+	u8 phy, page, reg;
+	u16 u16dat;
+
+	if (sizeof(struct PhySetting) != len)
+		return -EINVAL;
+
+	phy = ((struct PhySetting *)cdata) ->phy;
+	page = ((struct PhySetting *)cdata) ->page;
+	reg = ((struct PhySetting *)cdata) ->reg;
+
+	if (phy >= 0x20)
+		return -EINVAL;	
+
+	if (page >= 0x20)
+		return -EINVAL;
+	
+	if (reg >= 0x20)
+		return -EINVAL;
+	
+	u16dat = _read_mii_register(phy, page, reg);
+	((struct PhySetting *)cdata) ->val = (unsigned short)u16dat;
+	
+	return 0;
+}
+
+int set_mii_reg(void *cdata, int len)
+{
+	u8 phy, page, reg, all;
+	u16 val;
+	u16 u16dat;
+
+	if (sizeof(struct PhySetting) != len)
+		return -EINVAL;
+
+	phy = ((struct PhySetting *)cdata) ->phy;
+	page = ((struct PhySetting *)cdata) ->page;
+	reg = ((struct PhySetting *)cdata) ->reg;
+	val = ((struct PhySetting *)cdata) ->val;
+	all = ((struct PhySetting *)cdata) ->all;  // if the command is set 24 phy,bit=1
+
+	if (phy >= 0x20)
+		return -EINVAL;
+	
+	if (page >= 0x20)
+		return -EINVAL;
+	
+	if (reg >= 0x20)
+		return -EINVAL;
+	
+	if (all >= 2)
+		return -EINVAL;
+
+	u16dat = _write_mii_register(phy, page, reg, val, all);
+	
+	return 0;
+}
+
+#endif
+static int _setGeneralEnable(void *cdata, int len, u8 page, u16 reg, u8 offset)
+{
+	int gdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	gdata = ((struct GeneralSetting *)cdata) ->gdata;
+	if( gdata != OP_FUNC_ENABLE && gdata != OP_FUNC_DISABLE ){
+		ip1811drv_err("Error: gdata=%X\n", gdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", gdata);
+
+	_WriteRegBits(page, reg, offset, 1, gdata);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+static int _getGeneralEnable(void *cdata, int len, u8 page, u16 reg, u8 offset)
+{
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	((struct GeneralSetting *)cdata) ->gdata = _ReadRegBits(page, reg, offset, 1);
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+static int _setPortmapMask(void *cdata, int len, u8 page, u8 reg)
+{
+	unsigned long pm;
+	int pd;
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	pd = ((struct PortmapSetting *)cdata) ->pmdata;
+	if (pm & ~0x1FFFFFFF){
+		ip1811drv_err("Error: portmap=%08lX\n", pm);
+		return -EINVAL;
+	}
+	if (pd & ~0x1FFFFFFF){
+		ip1811drv_err("Error: pmdata=%X\n", pd);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("portmap=0x%08lX\n", pm);
+	ip1811drv_dbg("portdata=0x%08X\n", pd);
+
+	IP2Page(page);
+	u32dat = (u32)Read_Reg(reg+1)<<16 | (u32)Read_Reg(reg);
+
+	u32dat &= ~pm;
+	u32dat |= pm & pd;
+
+	Write_Reg(reg, (u16)(u32dat & 0xFFFF));
+	Write_Reg(reg+1, (u16)(u32dat >> 16));
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+static int _getPortmapMask(void *cdata, int len, u8 page, u8 reg)
+{
+	unsigned long pm;
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	if (pm & ~0x1FFFFFFF){
+		ip1811drv_err("Error: portmap=%08lX\n", pm);
+		return -EINVAL;
+	}
+
+	IP2Page(page);
+	u32dat = (u32)Read_Reg(reg+1)<<16 | (u32)Read_Reg(reg);
+	((struct PortmapSetting *)cdata) ->pmdata = u32dat & pm;
+
+	ip1811drv_dbg("cdata ->portmap=0x%08lX\n", ((struct PortmapSetting *)cdata) ->portmap);
+	ip1811drv_dbg("cdata ->pmdata=0x%08X\n", ((struct PortmapSetting *)cdata) ->pmdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+
+static int _setPortmap(void *cdata, int len, u8 page, u8 reg)
+{
+	unsigned long pm;
+	int pd;
+	u16 u16dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	pd = ((struct PortmapSetting *)cdata) ->pmdata;
+
+	if (pm & ~0xFFF) {
+		ip1811drv_err("Error: portmap=%08lX\n", pm);
+		return -EINVAL;
+	}
+	if ((pd != OP_FUNC_ENABLE) && (pd != OP_FUNC_DISABLE)) {
+		ip1811drv_err("Error: pd=%X\n", pd);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("portmap=0x%08lX\n", pm);
+	ip1811drv_dbg("portdata=0x%X\n", pd);
+
+	IP2Page(page);
+	u16dat = Read_Reg(reg);
+	
+#ifdef COMBINED_PORT
+	if ((pm >> 9) & 0x1)
+		pm |= (u16)(1 << 10);
+#endif
+
+	if (pd == OP_FUNC_ENABLE)
+		u16dat |= (u16)pm;
+	else//OP_FUNC_DISABLE
+		u16dat &= ~(u16)pm;
+
+	Write_Reg(reg, (u16dat & 0xFFF));
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+static int _getPortmap(void *cdata, int len, u8 page, u8 reg)
+{
+	unsigned long pm;
+	u16 u16dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+
+	if (pm & ~0xFFF){
+		ip1811drv_err("Error: portmap=%08lX\n", pm);
+		return -EINVAL;
+	}
+	IP2Page(page);
+	u16dat = Read_Reg(reg);
+	u16dat &= (u16)pm;
+	((struct PortmapSetting *)cdata) ->pmdata = u16dat;
+
+	ip1811drv_dbg("cdata ->pmdata=0x%08X\n", ((struct PortmapSetting *)cdata) ->pmdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+
+//------------------------------------------------
+//common_smi
+int switchdSetPortAN(int port, int an)
+{
+	u16 u16dat;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(an==OP_FUNC_DISABLE || an==OP_FUNC_ENABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("an=%d\n", an);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_AN);
+	if (an == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (an == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_AN, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortAN);
+int setPortAN(void *cdata, int len)
+{
+	int port, an;
+
+	ip1811drv_dbg("ip1811: +setPortAN...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	an = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortAN(port, an) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortAN...\n");
+	return 0;
+}
+
+int switchdGetPortAN(int port, int *ptrInt)
+{
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = _ReadRegBits(3, P3REG_PORTSTS0 + port/2,6+(port&0x1)*8 , 1);
+	ip1811drv_dbg("an=0x%x\n", *ptrInt);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortAN);
+int getPortAN(void *cdata, int len)
+{
+	int port, an;
+
+	ip1811drv_dbg("ip1811: +getPortAN...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortAN(port, &an) != 0)
+		return -EINVAL;
+
+	((struct ByPortSetting *)cdata) ->pdata = an;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortAN...\n");
+	return 0;
+}
+
+int switchdSetPortSpeed(int port, int speed)
+{
+	u16 u16dat;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(speed==OP_SMI_SPEED_10 || speed==OP_SMI_SPEED_100 ||
+				(speed==OP_SMI_SPEED_1000 && port>=8)) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("speed=%d\n", speed);
+
+	IP2Page(3);
+	if (speed == OP_SMI_SPEED_1000)
+	{
+		u16dat = Read_Reg(P3REG_SPG);
+		u16dat |= (u16)(1 << (port-8));
+#ifdef COMBINED_PORT
+		if (port==9)
+			u16dat |= (u16)(1 << (port+1-8));
+#endif
+		Write_Reg(P3REG_SPG, u16dat);
+	}
+	else
+	{
+		if (port >= 8)
+		{
+			u16dat = Read_Reg(P3REG_SPG);
+			u16dat &= (u16)~(1 << (port-8));
+#ifdef COMBINED_PORT
+		if (port==9)
+			u16dat &= (u16)~(1 << (port+1-8));
+#endif
+			Write_Reg(P3REG_SPG, u16dat);
+		}
+
+		u16dat = (u16)( Read_Reg(P3REG_SP) );
+		if (speed == OP_SMI_SPEED_100)
+			u16dat |= (u16)(1 << port);
+		else
+			u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+		if (port==9){
+			if (speed == OP_SMI_SPEED_100)
+				u16dat |= (u16)(1 << port+1);
+			else
+				u16dat &= (u16)~(1 << port+1);
+		}
+#endif
+		Write_Reg(P3REG_SP, u16dat & 0xFFFF);
+	}
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortSpeed);
+int setPortSpeed(void *cdata, int len)
+{
+	int port, speed;
+
+	ip1811drv_dbg("ip1811: +setPortSpeed...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	speed= ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortSpeed(port, speed) != 0)
+		return -EINVAL;
+	ip1811drv_dbg("ip1811: -setPortSpeed...\n");
+	return 0;
+}
+
+int switchdGetPortSpeed(int port, int *ptrInt)
+{
+	int speed;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	speed = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,1+(port&0x1)*8 , 2);
+	ip1811drv_dbg("speed=0x%x\n", speed);
+	if (speed & 0x2)
+		*ptrInt = OP_SMI_SPEED_1000;
+	else{
+		if (speed & 0x1)
+			*ptrInt = OP_SMI_SPEED_100;
+		else
+			*ptrInt = OP_SMI_SPEED_10;
+	}
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortSpeed);
+int getPortSpeed(void *cdata, int len)
+{
+	int port, speed;
+
+	ip1811drv_dbg("ip1811: +getPortSpeed...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortSpeed(port, &speed) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = speed;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortSpeed...\n");
+	return 0;
+}
+
+int switchdSetPortDuplex(int port, int dup)
+{
+	u16 u16dat;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(dup==OP_SMI_DUPLEX_HALF || dup==OP_SMI_DUPLEX_FULL) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("dup=%d\n", dup);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_DUPLEX);
+	if (dup == OP_SMI_DUPLEX_FULL)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (dup == OP_SMI_DUPLEX_FULL)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_DUPLEX, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortDuplex);
+int setPortDuplex(void *cdata, int len)
+{
+	int port, dup;
+
+	ip1811drv_dbg("ip1811: +setPortDuplex...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	dup =((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortDuplex(port, dup) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortDuplex...\n");
+	return 0;
+}
+
+int switchdGetPortDuplex(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,(3+(port&0x1)*8), 1);
+	ip1811drv_dbg("dup=0x%x\n", *ptrInt);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortDuplex);
+int getPortDuplex(void *cdata, int len)
+{
+	int port, dup;
+
+	ip1811drv_dbg("ip1811: +getPortDuplex...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortDuplex(port, &dup) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = dup;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortDuplex...\n");
+	return 0;
+}
+
+int switchdSetPortPause(int port, int ps)
+{
+	u16 u16dat;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(ps==OP_FUNC_ENABLE || ps==OP_FUNC_DISABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("ps=%d\n", ps);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_PAUSE);
+	if (ps == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (ps == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_PAUSE, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortPause);
+int setPortPause(void *cdata, int len)
+{
+	int port, ps;
+
+	ip1811drv_dbg("ip1811: +setPortPause...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	ps = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortPause(port, ps) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortPause...\n");
+	return 0;
+}
+
+int switchdGetPortPause(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,4+(port&0x1)*8 , 1);
+	ip1811drv_dbg("ps=0x%x\n", *ptrInt);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortPause);
+int getPortPause(void *cdata, int len)
+{
+	int port, ps;
+
+	ip1811drv_dbg("ip1811: +getPortPause...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortPause(port, &ps) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = ps;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortPause...\n");
+	return 0;
+}
+
+int switchdSetPortAsymPause(int port, int aps)
+{
+	u16 u16dat;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(aps==OP_FUNC_ENABLE || aps==OP_FUNC_DISABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("aps=%d\n", aps);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_ASPAUSE);
+	if (aps == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (aps == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_ASPAUSE, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortAsymPause);
+int setPortAsymPause(void *cdata, int len)
+{
+	int port, aps;
+
+	ip1811drv_dbg("ip1811: +setPortAsymPause...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	aps =((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortAsymPause(port, aps) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortAsymPause...\n");
+	return 0;
+}
+
+int switchdGetPortAsymPause(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int) _ReadRegBits(3, P3REG_PORTSTS0 + port/2,5+(port&0x1)*8 , 1);
+	ip1811drv_dbg("aps=0x%x\n", *ptrInt);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortAsymPause);
+int getPortAsymPause(void *cdata, int len)
+{
+	int port, aps;
+
+	ip1811drv_dbg("ip1811: +getPortAsymPause...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortAsymPause(port, &aps) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = aps;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortAsymPause...\n");
+	return 0;
+}
+
+int switchdSetPortLinkStatus(struct LinkStatusSetting *avg)
+{
+	int port, sp, dup, ps, asym, an;
+	u16 u16dat;
+	
+	port= avg->port;
+	sp = avg->speed;
+	dup = avg->duplex;
+	ps = avg->pause;
+	asym= avg->asym;
+	an = avg->an;
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(sp==OP_SMI_SPEED_10 || sp==OP_SMI_SPEED_100 || (sp==OP_SMI_SPEED_1000 && port>8)) )
+		return -EINVAL;
+	if ( !(dup==OP_SMI_DUPLEX_HALF || dup==OP_SMI_DUPLEX_FULL) )
+		return -EINVAL;
+	if ( !(ps==OP_FUNC_DISABLE || ps==OP_FUNC_ENABLE) )
+		return -EINVAL;
+	if ( !(asym==OP_FUNC_DISABLE || asym==OP_FUNC_ENABLE) )
+		return -EINVAL;
+	if ( !(an==OP_FUNC_DISABLE || an==OP_FUNC_ENABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("sp=%d  dup=%d  ps=%d  asym=%d  an=%d\n",
+			sp, dup, ps, asym, an);
+
+	IP2Page(3);
+	if (sp == OP_SMI_SPEED_1000)
+	{
+		u16dat = Read_Reg(P3REG_SPG);
+		u16dat |= (u16)(1 << (port-8));
+#ifdef COMBINED_PORT
+		if (port==9){
+			u16dat |= (u16)(1 << (port+1-8));
+		}
+#endif
+		Write_Reg(P3REG_SPG, u16dat);
+	}
+	else
+	{
+		if (port >= 8)
+		{
+			u16dat = Read_Reg(P3REG_SPG);
+			u16dat &= (u16)~(1 << (port-8));
+#ifdef COMBINED_PORT
+			if (port==9){
+				u16dat &= (u16)~(1 << (port+1-8));
+			}
+#endif
+			Write_Reg(P3REG_SPG, u16dat);
+		}
+
+		u16dat = Read_Reg(P3REG_SP);
+		if (sp == OP_SMI_SPEED_100)
+			u16dat |= (u16)(1 << port);
+		else
+			u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+		if (port==9){
+			if (sp == OP_SMI_SPEED_100)
+				u16dat |= (u16)(1 << port+1);
+			else
+				u16dat &= (u16)~(1 << port+1);
+		}
+#endif
+		Write_Reg(P3REG_SP, u16dat & 0xFFFF);
+	}
+
+	u16dat = Read_Reg(P3REG_DUPLEX);
+	if (dup == OP_SMI_DUPLEX_FULL)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (dup == OP_SMI_DUPLEX_FULL)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_DUPLEX, u16dat & 0xFFFF);
+
+	u16dat = Read_Reg(P3REG_PAUSE);
+	if (ps == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (ps == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_PAUSE, u16dat & 0xFFFF);
+
+	u16dat = Read_Reg(P3REG_ASPAUSE);
+	if (asym == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (asym == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_ASPAUSE, u16dat & 0xFFFF);
+
+	u16dat = Read_Reg(P3REG_AN);
+	if (an == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (an == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_AN, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortLinkStatus);
+int setPortLinkStatus(void *cdata, int len)
+{
+	int port, sp, dup, ps, asym, an;
+	u16 u16dat;
+	struct LinkStatusSetting *avg = (struct LinkStatusSetting *)cdata;
+
+	ip1811drv_dbg("ip1811: +setPortLinkStatus...\n");
+	if (sizeof(struct LinkStatusSetting) != len)
+		return -EINVAL;
+
+	if(switchdSetPortLinkStatus(avg) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortLinkStatus...\n");
+	return 0;
+}
+
+int switchdGetPortLinkStatus(struct LinkStatusSetting *cdata)
+{
+	int port, link, sp, dup, ps, asym, an, fiber;
+	u8  u8dat;
+	u16 u16dat;
+	
+	port = ((struct LinkStatusSetting *)cdata) ->port;
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	IP2Page(3);
+	u8dat = P3REG_PORTSTS0 + port/2;
+	u16dat = Read_Reg(u8dat);
+	ip1811drv_dbg("u16dat=0x%04x\n", u16dat);
+	link=(int)( ( u16dat >> (0+(port&0x1)*8) ) & 0x1 );
+	sp = (int)( ( u16dat >> (1+(port&0x1)*8) ) & 0x3 );
+	if (sp & 0x2)	sp = OP_SMI_SPEED_1000;
+	else
+	{
+		if (sp & 0x1)	sp = OP_SMI_SPEED_100;
+		else			sp = OP_SMI_SPEED_10;
+	}
+	dup =(int)( ( u16dat >> (3+(port&0x1)*8) ) & 0x1 );
+	ps = (int)( ( u16dat >> (4+(port&0x1)*8) ) & 0x1 );
+	asym=(int)( ( u16dat >> (5+(port&0x1)*8) ) & 0x1 );
+	an = (int)( ( u16dat >> (6+(port&0x1)*8) ) & 0x1 );
+	fiber = (int)( ( u16dat >> (7+(port&0x1)*8) ) & 0x1 );
+	ip1811drv_dbg("link=0x%x  sp=%d  dup=0x%x  ps=0x%x  asym=0x%x  an=0x%x  fiber=0x%x\n",
+			link, sp, dup, ps, asym, an, fiber);
+	((struct LinkStatusSetting *)cdata) ->link = link;
+	((struct LinkStatusSetting *)cdata) ->speed = sp;
+	((struct LinkStatusSetting *)cdata) ->duplex = dup;
+	((struct LinkStatusSetting *)cdata) ->pause = ps;
+	((struct LinkStatusSetting *)cdata) ->asym = asym;
+	((struct LinkStatusSetting *)cdata) ->an = an;
+	((struct LinkStatusSetting *)cdata) ->fiber = fiber;
+	ip1811drv_dbg("cdata ->link=%d\n", ((struct LinkStatusSetting *)cdata) ->link);
+	ip1811drv_dbg("cdata ->speed=%d\n", ((struct LinkStatusSetting *)cdata) ->speed);
+	ip1811drv_dbg("cdata ->duplex=%d\n", ((struct LinkStatusSetting *)cdata) ->duplex);
+	ip1811drv_dbg("cdata ->pause=%d\n", ((struct LinkStatusSetting *)cdata) ->pause);
+	ip1811drv_dbg("cdata ->asym=%d\n", ((struct LinkStatusSetting *)cdata) ->asym);
+	ip1811drv_dbg("cdata ->an=%d\n", ((struct LinkStatusSetting *)cdata) ->an);
+	ip1811drv_dbg("cdata ->fiber=%d\n", ((struct LinkStatusSetting *)cdata) ->fiber);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortLinkStatus);
+int getPortLinkStatus(void *cdata, int len)
+{
+	struct LinkStatusSetting *avg = (struct LinkStatusSetting *)cdata;
+
+	ip1811drv_dbg("ip1811: +getPortLinkStatus...\n");
+	if (sizeof(struct LinkStatusSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetPortLinkStatus(avg) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -getPortLinkStatus...\n");
+	return 0;
+}
+
+int switchdSetPortBackpressure(int port, int bp)
+{
+	u16 u16dat;
+
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(bp==OP_FUNC_ENABLE || bp==OP_FUNC_DISABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("bp=%d\n", bp);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_BPRESS);
+	if (bp == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (bp == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_BPRESS, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortBackpressure);
+int setPortBackpressure(void *cdata, int len)
+{
+	int port, bp;
+
+	ip1811drv_dbg("ip1811: +setPortBackpressure...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	bp = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortBackpressure(port, bp) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortBackpressure...\n");
+	return 0;
+}
+
+int switchdGetPortBackpressure(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int)_ReadRegBits(3, P3REG_BPRESS + port/16, port%16, 1);
+	ip1811drv_dbg("bp=0x%x\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortBackpressure);
+int getPortBackpressure(void *cdata, int len)
+{
+	int port, bp;
+
+	ip1811drv_dbg("ip1811: +getPortBackpressure...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortBackpressure(port, &bp) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = bp;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortBackpressure...\n");
+	return 0;
+}
+
+int switchdSetPortPowerDown(int port, int pd)
+{
+	u16 u16dat;
+
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(pd==OP_FUNC_ENABLE || pd==OP_FUNC_DISABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("pd=%d\n", pd);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_POWERDOWN);
+	if (pd == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+	Write_Reg(P3REG_POWERDOWN, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortPowerDown);
+int setPortPowerDown(void *cdata, int len)
+{
+	int port, pd;
+
+	ip1811drv_dbg("ip1811: +setPortPowerDown...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	pd = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortPowerDown(port, pd) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortPowerDown...\n");
+	return 0;
+}
+
+int switchdGetPortPowerDown(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+	*ptrInt = (int)_ReadRegBits(3, P3REG_POWERDOWN + port/16, port%16, 1);
+	ip1811drv_dbg("pd=0x%x\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortPowerDown);
+int getPortPowerDown(void *cdata, int len)
+{
+	int port, pd;
+
+	ip1811drv_dbg("ip1811: +getPortPowerDown...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortPowerDown(port, &pd) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = pd;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortPowerDown...\n");
+	return 0;
+}
+
+int switchdSetPortForceLink(int port, int fl)
+{
+	u16 u16dat;
+
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(fl==OP_FUNC_ENABLE || fl==OP_FUNC_DISABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("fl=%d\n", fl);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_FORCELINK);
+	if (fl == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (fl == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_FORCELINK, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortForceLink);
+int setPortForceLink(void *cdata, int len)
+{
+	int port, fl;
+
+	ip1811drv_dbg("ip1811: +setPortForceLink...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	fl = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortForceLink(port, fl) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortForceLink...\n");
+	return 0;
+}
+
+int switchdGetPortForceLink(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int)_ReadRegBits(3, P3REG_FORCELINK + port/16, port%16, 1);
+	ip1811drv_dbg("fl=0x%x\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortForceLink);
+int getPortForceLink(void *cdata, int len)
+{
+	int port, fl;
+
+	ip1811drv_dbg("ip1811: +getPortForceLink...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortForceLink(port, &fl) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = fl;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortForceLink...\n");
+	return 0;
+}
+
+int switchdSetPortUniDirection(int port, int uni)
+{
+	u16 u16dat;
+
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(uni==OP_FUNC_ENABLE || uni==OP_FUNC_DISABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("uni=%d\n", uni);
+
+	IP2Page(3);
+	u16dat = Read_Reg(P3REG_UNIDIRECT);
+	if (uni == OP_FUNC_ENABLE)
+		u16dat |= (u16)(1 << port);
+	else
+		u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (uni == OP_FUNC_ENABLE)
+			u16dat |= (u16)(1 << port+1);
+		else
+			u16dat &= (u16)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P3REG_UNIDIRECT, u16dat & 0xFFFF);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetPortUniDirection);
+int setPortUniDirection(void *cdata, int len)
+{
+	int port, uni;
+
+	ip1811drv_dbg("ip1811: +setPortUniDirection...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	uni =((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetPortUniDirection(port, uni) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setPortUniDirection...\n");
+	return 0;
+}
+
+int switchdGetPortUniDirection(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int)_ReadRegBits(3, P3REG_UNIDIRECT + port/16, (port-1)%16, 1);
+	ip1811drv_dbg("uni=0x%x\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetPortUniDirection);
+int getPortUniDirection(void *cdata, int len)
+{
+	int port, uni;
+
+	ip1811drv_dbg("ip1811: +getPortUniDirection...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetPortUniDirection(port, &uni) != 0)
+		return -EINVAL;
+	((struct ByPortSetting *)cdata) ->pdata = uni;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getPortUniDirection...\n");
+	return 0;
+}
+
+//------------------------------------------------
+//common_cap
+int switchdSetL2CapAct(int ptcl, int act)
+{
+	u32 u32dat, mask;
+
+	if (ptcl < OP_CAP_PTCL_BPDU || ptcl > OP_CAP_PTCL_GRP3)
+		return -EINVAL;
+	if (act!=OP_CAP_ACT_FORWARD && act!=OP_CAP_ACT_TO_CPU && act!=OP_CAP_ACT_DROP)
+		return -EINVAL;
+	ip1811drv_dbg("ptcl=%d\n", ptcl);
+	ip1811drv_dbg("act=%d\n", act);
+
+	IP2Page(0);
+	u32dat = ( Read_Reg(P0REG_L2FRAMEGETCTRL1) << 16 | Read_Reg(P0REG_L2FRAMEGETCTRL) );
+	mask = (u32)~(0x3 << (ptcl*2));
+	u32dat &= mask;
+	u32dat |= (u32)(act << (ptcl*2));
+	Write_Reg(P0REG_L2FRAMEGETCTRL, (u16)(u32dat & 0xFFFF));
+	Write_Reg(P0REG_L2FRAMEGETCTRL1, (u16)(u32dat >> 16));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetL2CapAct);
+int setL2CapAct(void *cdata, int len)
+{
+	int ptcl, act;
+
+	ip1811drv_dbg("ip1811: +setL2CapAct...\n");
+	if (sizeof(struct CapActSetting) != len)
+		return -EINVAL;
+
+	ptcl= ((struct CapActSetting *)cdata) ->protocol;
+	act = ((struct CapActSetting *)cdata) ->act;
+
+	if(switchdSetL2CapAct(ptcl, act) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setL2CapAct...\n");
+	return 0;
+}
+
+int switchdSetCapInBand(int gdata)
+{
+	if( gdata != OP_CAP_ACT_TO_CPU && gdata != OP_CAP_ACT_DROP ){
+		ip1811drv_err("Error: gdata=%X\n", gdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", gdata);
+
+	_WriteRegBits(0, P0REG_MACBEHAVIOR, 6, 1, (gdata==OP_CAP_ACT_TO_CPU?0x1:0x0));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetCapInBand);
+int setCapInBand(void *cdata, int len)
+{
+	int gdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	gdata = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetCapInBand(gdata) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdSetCapSwitchMac(unsigned char * mac)
+{
+	int i;
+	u16 u16dat;
+
+	for(i=0; i<6; i++)
+		ip1811drv_dbg("cdata ->mac[%d]=%X\n", i, mac[i]);
+	IP2Page(0);
+	for(i=0; i<3; i++){
+		u16dat = ((((u16)mac[i*2])&0xFF)<<8) | (((u16)mac[i*2+1])&0xFF);
+		Write_Reg(P0REG_MACADDRESS+(2-i), u16dat);
+	}
+}
+EXPORT_SYMBOL(switchdSetCapSwitchMac);
+int setCapSwitchMac(void *cdata, int len)
+{
+	char mac[6];
+
+	FUNC_MSG_IN;
+	if (sizeof(struct MACSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	memcpy(mac, ((struct MACSetting *)cdata) ->mac, 6);
+
+	switchdSetCapSwitchMac(mac);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetCapIpv6TcpUdpEnable(int enable)
+{
+	if(enable!=OP_FUNC_ENABLE && enable!=OP_FUNC_DISABLE) {
+		ip1811drv_err("Error: enable=%X\n", enable);
+		return -EINVAL;
+	}
+	
+	ip1811drv_dbg("enable=%d\n", enable);
+
+	_WriteRegBits(0, P0REG_IPV6RLTCFG, 0, 1, enable);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetCapIpv6TcpUdpEnable);
+int setCapIpv6TcpUdpEnable(void *cdata, int len)
+{
+	int ret, en;
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	ret = switchdSetCapIpv6TcpUdpEnable(en);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+//------------------------------------------------
+//common_lut
+int switchdSetSMACLearning(int port, int en)
+{
+	u32 u32dat;
+
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) )
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("en=%d\n", en);
+
+	IP2Page(1);
+	u32dat = (u32)Read_Reg(P1REG_SRCLEARN_ENABLE);
+	if (en == OP_FUNC_ENABLE)
+		u32dat |= (u32)(1 << port);
+	else
+		u32dat &= (u32)~(1 << port);
+#ifdef COMBINED_PORT
+	if (port==9){
+		if (en == OP_FUNC_ENABLE)
+			u32dat |= (u32)(1 << port+1);
+		else
+			u32dat &= (u32)~(1 << port+1);
+	}
+#endif
+	Write_Reg(P1REG_SRCLEARN_ENABLE, (u32dat & 0xFFF));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetSMACLearning);
+int setSMACLearning(void *cdata, int len)
+{
+	int port, en;
+
+	ip1811drv_dbg("ip1811: +setSMACLearning...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	en = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetSMACLearning(port, en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setSMACLearning...\n");
+	return 0;
+}
+
+int switchdGetSMACLearning(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SRCLEARN_ENABLE, port, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetSMACLearning);
+int getSMACLearning(void *cdata, int len)
+{
+	int port, en;
+
+	ip1811drv_dbg("ip1811: +getSMACLearning...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetSMACLearning(port, &en) != 0)
+		return -EINVAL;
+
+	((struct ByPortSetting *)cdata) ->pdata = en;
+
+	ip1811drv_dbg("ip1811: -getSMACLearning...\n");
+	return 0;
+}
+
+int switchdSetLutPortFlush(unsigned long pm, int en)
+{
+	u16 u16dat;
+	
+	if (pm & 0xF000)
+		return -EINVAL;
+	if (	en != OP_LUT_FLUSH_DYNAMIC_ONLY &&
+			en != OP_LUT_FLUSH_STATIC_ONLY &&
+			en != OP_LUT_FLUSH_ALL )
+		return -EINVAL;
+	ip1811drv_dbg("pm=0x%04x\n", (u16)pm);
+	ip1811drv_dbg("en=%d\n", en);
+
+    /* start to flush LUT */
+	IP2Page(1);
+	u16dat = 0x80;
+	if (en == OP_LUT_FLUSH_ALL)
+		u16dat |= (u16)0x40;	// flush static entries
+	Write_Reg(P1REG_PORTFLUSH, (u16)(pm & 0x0FFF));
+	Write_Reg(P1REG_LUTFLUSH_CFG, u16dat);
+	udelay(10000);//flush LUT needs waiting at least 4 ms
+				
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutPortFlush);
+int setLutPortFlush(void *cdata, int len)
+{
+	unsigned long pm;
+	int en;
+
+	ip1811drv_dbg("ip1811: +setLutPortFlush...\n");
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	en = ((struct PortmapSetting *)cdata) ->pmdata;
+
+	if(switchdSetLutPortFlush(pm, en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setLutPortFlush...\n");
+	return 0;
+}
+
+int switchdSetLutAgingTime(int time)
+{
+	if (time > 18000)
+		return -EINVAL;
+	ip1811drv_dbg("time=%d\n", time);
+
+	_WriteRegBits(1, P1REG_LUTAGINGTIME, 0, 15, (u16)(time*1000/AGING_TIME_UNIT));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutAgingTime);
+int setLutAgingTime(void *cdata, int len)
+{
+	int time;
+
+	ip1811drv_dbg("ip1811: +setLutAgingTime...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	time = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetLutAgingTime(time) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setLutAgingTime...\n");
+	return 0;
+}
+
+void switchdGetLutAgingTime(int *ptrInt)
+{
+	*ptrInt = ((int)_ReadRegBits(1, P1REG_LUTAGINGTIME, 0, 15))*AGING_TIME_UNIT/1000;
+}
+EXPORT_SYMBOL(switchdGetLutAgingTime);
+int getLutAgingTime(void *cdata, int len)
+{
+	int time;
+
+	ip1811drv_dbg("ip1811: +getLutAgingTime...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	switchdGetLutAgingTime(&time);
+
+	((struct GeneralSetting *)cdata) ->gdata = time;
+
+    ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getLutAgingTime...\n");
+	return 0;
+}
+
+int switchdSetLutAgingTimeEnable(int en)
+{
+	if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) )
+		return -EINVAL;
+
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(1, P1REG_LUTAGINGTIME, 15, 1, (en==OP_FUNC_ENABLE)?0:1);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutAgingTimeEnable);
+int setLutAgingTimeEnable(void *cdata, int len)
+{
+	int en;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetLutAgingTimeEnable(en) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetLutLearningNullSA(int en)
+{
+	if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) )
+		return -EINVAL;
+
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(1, P1REG_SRCLEARNCFG, 1, 1, en);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutLearningNullSA);
+int setLutLearningNullSA(void *cdata, int len)
+{
+	int en;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetLutLearningNullSA(en) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetLutHashingAlgorithm(int hash)
+{
+	if ( !(hash==OP_HASH_DIRECT || hash==OP_HASH_CRC) )
+		return -EINVAL;
+		
+	ip1811drv_dbg("hash=%d\n", hash);
+
+	_WriteRegBits(1, P1REG_SRCLEARNCFG, 2, 1, (hash==OP_HASH_CRC)?0:1);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutHashingAlgorithm);
+int setLutHashingAlgorithm(void *cdata, int len)
+{
+	int hash;
+
+	ip1811drv_dbg("ip1811: +setLutHashingAlgorithm...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	hash = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetLutHashingAlgorithm(hash) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setLutHashingAlgorithm...\n");
+	return 0;
+}
+
+int switchdSetLutBindingEnable(int en)
+{
+	if ( !(en==OP_FUNC_DISABLE || en==OP_FUNC_ENABLE) )
+		return -EINVAL;
+
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(1, P1REG_SRCLEARNCFG, 5, 1, (en==OP_FUNC_ENABLE)?1:0);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutBindingEnable);
+int setLutBindingEnable(void *cdata, int len)
+{
+	int en;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetLutBindingEnable(en) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetLutBindingEnable(int *ptrInt)
+{
+	*ptrInt = (int)(_ReadRegBits(1, P1REG_SRCLEARNCFG, 5, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE);
+}
+EXPORT_SYMBOL(switchdGetLutBindingEnable);
+int getLutBindingEnable(void *cdata, int len)
+{
+	int en;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	switchdGetLutBindingEnable(&en);
+
+	((struct GeneralSetting *)cdata) ->gdata = en;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+//------------------------------------------------
+//common_sniffer
+int switchdSetSnifferSrc(unsigned long pm)
+{
+	if (pm & 0xFFFFF000)
+		return -EINVAL;
+	ip1811drv_dbg("pm=0x%08x\n",(unsigned long)pm);
+
+	IP2Page(1);
+	Write_Reg(P1REG_SNIFSRC, (u16)(pm & 0xFFF));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetSnifferSrc);
+int setSnifferSrc(void *cdata, int len)
+{
+	unsigned long pm;
+
+	ip1811drv_dbg("ip1811: +setSnifferSrc...\n");
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	pm = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetSnifferSrc(pm) != 0)
+		return -EINVAL;
+	ip1811drv_dbg("ip1811: -setSnifferSrc...\n");
+	return 0;
+}
+
+int switchdGetSnifferSrc(u16 *u16dat)
+{
+	IP2Page(1);
+	*u16dat = (u16)Read_Reg(P1REG_SNIFSRC);
+	
+	ip1811drv_dbg("cdata ->pdata=%d\n", *u16dat);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetSnifferSrc);
+int getSnifferSrc(void *cdata, int len)
+{
+	u16 u16dat;
+
+	ip1811drv_dbg("ip1811: +getSnifferSrc...\n");
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetSnifferSrc(&u16dat) != 0)
+		return -EINVAL;
+		
+	((struct PortMemberSetting *)cdata) ->member = (u16dat & 0xFFF);
+	ip1811drv_dbg("cdata ->gdata=0x%08x\n",(unsigned int)((struct PortMemberSetting *)cdata) ->member);
+	ip1811drv_dbg("ip1811: -getSnifferSrc...\n");
+	return 0;
+}
+
+int switchdSetSnifferDestGrp1(unsigned long pm)
+{
+	u32 u32dat;
+	
+	if (pm & 0xFFFFF000)
+		return -EINVAL;
+	ip1811drv_dbg("pm=0x%08x\n", (unsigned int)pm);
+
+	IP2Page(1);
+	u32dat = (u32)Read_Reg(P1REG_SNIFDEST);
+	u32dat = ((u32dat & 0xFFFFF000) | pm);
+	Write_Reg(P1REG_SNIFDEST, (u16)(u32dat & 0xFFF));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetSnifferDestGrp1);
+int setSnifferDestGrp1(void *cdata, int len)
+{
+	unsigned long pm;
+
+	ip1811drv_dbg("ip1811: +setSnifferDestGrp1...\n");
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	pm = ((struct PortMemberSetting *)cdata) ->member;
+
+	if(switchdSetSnifferDestGrp1(pm) != 0)
+		return -EINVAL;
+	ip1811drv_dbg("ip1811: -setSnifferDestGrp1...\n");
+	return 0;
+}
+
+int switchdGetSnifferDestGrp1(u16 *u16dat)
+{
+	IP2Page(1);
+	*u16dat = (u16)Read_Reg(P1REG_SNIFDEST);
+	ip1811drv_dbg("cdata ->pdata=%d\n", *u16dat);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetSnifferDestGrp1);
+int getSnifferDestGrp1(void *cdata, int len)
+{
+	u16 u16dat;
+
+	ip1811drv_dbg("ip1811: +getSnifferDestGrp1...\n");
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetSnifferDestGrp1(&u16dat) != 0)
+		return -EINVAL;
+		
+	((struct PortMemberSetting *)cdata) ->member = (u16dat & 0xFFF);
+	ip1811drv_dbg("cdata ->gdata=0x%08x\n", (unsigned int)((struct PortMemberSetting *)cdata) ->member);
+	ip1811drv_dbg("ip1811: -getSnifferDestGrp1...\n");
+	return 0;
+}
+
+int switchdSetS1Method(int method)
+{
+	if (method<OP_SNIFFER1_METHOD_DISABLE || method>OP_SNIFFER1_METHOD_BOTHDIR)
+		return -EINVAL;
+	ip1811drv_dbg("method=%d\n", method);
+
+	_WriteRegBits(1, P1REG_SNIFCFG, 0, 2, method);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetS1Method);
+int setS1Method(void *cdata, int len)
+{
+	int method;
+
+	ip1811drv_dbg("ip1811: +setS1Method...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	method = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetS1Method(method) != 0)
+		return -EINVAL;
+	ip1811drv_dbg("ip1811: -setS1Method...\n");
+	return 0;
+}
+
+int switchdGetS1Method(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 0, 2);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetS1Method);
+int getS1Method(void *cdata, int len)
+{
+	int method;
+	
+	ip1811drv_dbg("ip1811: +getS1Method...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetS1Method(&method) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = method;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getS1Method...\n");
+	return 0;
+}
+//------------------------------------------------
+//common_storm
+int switchdSetStormFunc(int storm, int porten)
+{
+	u8 u8dat=0;
+	
+	if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF &&
+			storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	if (porten<0 || (porten&0xFFFFF000))
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+	ip1811drv_dbg("porten=0x%08x\n", (unsigned int)porten);
+
+	IP2Page(1);
+	switch (storm){
+		case OP_STORM_BCST:
+			u8dat = P1REG_BSTORMEN;
+			break;
+		case OP_STORM_MCST:
+			u8dat = P1REG_MSTORMEN;
+			break;
+
+		case OP_STORM_DLF:
+			u8dat = P1REG_DLFSTORMEN;
+			break;
+
+		case OP_STORM_ARP:
+			u8dat = P1REG_ARPSTORMEN;
+			break;
+
+		case OP_STORM_ICMP:
+			u8dat = P1REG_ICMPSTORMEN;
+			break;
+	}
+	Write_Reg(u8dat, (u16)(porten & 0xFFFF));
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetStormFunc);
+int setStormFunc(void *cdata, int len)
+{
+	u8 storm;
+	long porten;
+
+	ip1811drv_dbg("ip1811: +setStormFunc...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+	porten= ((struct StormGeneralSetting *)cdata) ->sdata;
+
+	if(switchdSetStormFunc(storm, porten) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setStormFunc...\n");
+	return 0;
+}
+
+int switchdGetStormFunc(int storm, u32 *u32dat)
+{
+	u8 u8dat=0;
+	
+	if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF &&
+			storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+
+	IP2Page(1);
+	switch (storm){
+		case OP_STORM_BCST:
+			u8dat = P1REG_BSTORMEN;
+			break;
+		case OP_STORM_MCST:
+			u8dat = P1REG_MSTORMEN;
+			break;
+		case OP_STORM_DLF:
+			u8dat = P1REG_DLFSTORMEN;
+			break;
+		case OP_STORM_ARP:
+			u8dat = P1REG_ARPSTORMEN;
+			break;
+		case OP_STORM_ICMP:
+			u8dat = P1REG_ICMPSTORMEN;
+			break;
+	}
+	*u32dat = (u32)Read_Reg(u8dat);
+
+	ip1811drv_dbg("cdata ->sdata=0x%08x\n", *u32dat);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetStormFunc);
+int getStormFunc(void *cdata, int len)
+{
+	u8 storm;
+	u32 u32dat;
+
+	ip1811drv_dbg("ip1811: +getStormFunc...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+
+	if(switchdGetStormFunc(storm, &u32dat) != 0)
+		return -EINVAL;
+	((struct StormGeneralSetting *)cdata) ->sdata = (long)u32dat;
+	
+	ip1811drv_dbg("ip1811: -getStormFunc...\n");
+	return 0;
+}
+
+int switchdSetStormThreshold(u8 storm, long threshold)
+{
+	u8 u8dat=0;
+	
+	if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF &&
+			storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	if (threshold<0 || threshold>0xFF)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+	ip1811drv_dbg("threshold=0x%08x\n", (unsigned int)threshold);
+
+	switch (storm)
+	{
+		case OP_STORM_BCST:
+		case OP_STORM_MCST:
+		case OP_STORM_DLF:
+			u8dat = P1REG_BSTORMTHRESH;	break;
+
+		case OP_STORM_ARP:
+			u8dat = P1REG_ARPSTORMCFG;	break;
+
+		case OP_STORM_ICMP:
+			u8dat = P1REG_ICMPSTORMCFG;	break;
+	}
+	_WriteRegBits(1, u8dat, 0, 8, (u16)threshold);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetStormThreshold);
+int setStormThreshold(void *cdata, int len)
+{
+	u8 storm;
+	long threshold;
+
+	ip1811drv_dbg("ip1811: +setStormThreshold...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+	threshold = ((struct StormGeneralSetting *)cdata) ->sdata;
+	
+	if(switchdSetStormThreshold(storm, threshold) != 0)
+		return -EINVAL;
+	
+	ip1811drv_dbg("ip1811: -setStormThreshold...\n");
+	return 0;
+}
+
+int switchdGetStormThreshold(u8 storm, long *ptrLong)
+{
+	u8 u8dat=0;
+	if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_DLF &&
+			storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+
+	switch (storm)
+	{
+		case OP_STORM_BCST:
+		case OP_STORM_MCST:
+		case OP_STORM_DLF:
+			u8dat = P1REG_BSTORMTHRESH;	break;
+
+		case OP_STORM_ARP:
+			u8dat = P1REG_ARPSTORMCFG;	break;
+
+		case OP_STORM_ICMP:
+			u8dat = P1REG_ICMPSTORMCFG;	break;
+	}
+	*ptrLong = (long)_ReadRegBits(1, u8dat, 0, 8);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetStormThreshold);
+int getStormThreshold(void *cdata, int len)
+{
+	u8 storm;
+	long threshold;
+
+	ip1811drv_dbg("ip1811: +getStormThreshold...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+
+	if(switchdGetStormThreshold(storm, &threshold) != 0)
+		return -EINVAL;
+
+	((struct StormGeneralSetting *)cdata) ->sdata = threshold;
+	ip1811drv_dbg("cdata ->sdata=0x%08x\n", (unsigned int)((struct StormGeneralSetting *)cdata) ->sdata);
+	ip1811drv_dbg("ip1811: -getStormThreshold...\n");
+	return 0;
+}
+
+int switchdSetStormCntrClrPeriod(u8 storm, long period)
+{
+	u8 reg=0;
+	
+	if (		storm!=OP_STORM_BCST
+			&&	storm!=OP_STORM_MCST
+			&&	storm!=OP_STORM_DLF
+			&&	storm!=OP_STORM_ARP
+			&&	storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	if (period<0 || period>3)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+	ip1811drv_dbg("period=0x%X\n", (unsigned int)period);
+
+	switch (storm)
+	{
+		case OP_STORM_BCST:
+		case OP_STORM_MCST:
+		case OP_STORM_DLF:
+			reg = P1REG_BSTORMTHRESH;
+			break;
+		case OP_STORM_ARP:
+			reg = P1REG_ARPSTORMCFG;
+			break;
+		case OP_STORM_ICMP:
+			reg = P1REG_ICMPSTORMCFG;
+			break;
+	}
+	ip1811drv_dbg("cdata ->sdata=0x%X\n", (s16)period);
+	
+	_WriteRegBits(1, reg, 8, 2, period);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetStormCntrClrPeriod);
+int setStormCntrClrPeriod(void *cdata, int len)
+{
+	u8 storm;
+	long period;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+	period = ((struct StormGeneralSetting *)cdata) ->sdata;
+
+	if(switchdSetStormCntrClrPeriod(storm, period) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetStormCntrClrPeriod(u8 storm, long *ptrInt)
+{
+	u8 reg =0;
+	
+	if (		storm!=OP_STORM_BCST
+			&&	storm!=OP_STORM_MCST
+			&&	storm!=OP_STORM_DLF
+			&&	storm!=OP_STORM_ARP
+			&&	storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+	
+	switch (storm)
+	{
+		case OP_STORM_BCST:
+		case OP_STORM_MCST:
+		case OP_STORM_DLF:
+			reg = P1REG_BSTORMTHRESH;
+			break;
+		case OP_STORM_ARP:
+			reg = P1REG_ARPSTORMCFG;
+			break;
+		case OP_STORM_ICMP:
+			reg = P1REG_ICMPSTORMCFG;
+			break;
+	}
+
+	*ptrInt = _ReadRegBits(1, reg, 8, 2);
+	
+	ip1811drv_dbg("cdata ->sdata=0x%X\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetStormCntrClrPeriod);
+int getStormCntrClrPeriod(void *cdata, int len)
+{
+	u8 storm;
+	long period=0;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("ip1811: +getStormCntrClrPeriod...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+
+	if(switchdGetStormCntrClrPeriod(storm, &period) != 0)
+		return -EINVAL;
+
+	((struct StormGeneralSetting *)cdata) ->sdata = period;
+	
+	ip1811drv_dbg("ip1811: -getStormCntrClrPeriod...\n");
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetStormBlockFrm2Cpu(int storm, int en)
+{
+	u8 u8dat=0;
+
+	if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_ARP)
+		return -EINVAL;
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+	ip1811drv_dbg("en=0x%08x\n", (unsigned int)en);
+
+	switch (storm)
+	{
+		case OP_STORM_BCST:
+		case OP_STORM_MCST:
+			u8dat = P1REG_BSTORMTHRESH;	break;
+
+		case OP_STORM_ARP:
+			u8dat = P1REG_ARPSTORMCFG;	break;
+	}
+	_WriteRegBits(1, u8dat, 10, 1, en);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetStormBlockFrm2Cpu);
+int setStormBlockFrm2Cpu(void *cdata, int len)
+{
+	u8 storm = 0;
+	long en;
+
+	ip1811drv_dbg("ip1811: +setStormBlockFrm2Cpu...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+	en = ((struct StormGeneralSetting *)cdata) ->sdata;
+
+	if(switchdSetStormBlockFrm2Cpu(storm, en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setStormBlockFrm2Cpu...\n");
+	return 0;
+}
+
+int switchdGetStormBlockFrm2Cpu(u8 storm, int *ptrInt)
+{
+	u8 u8dat=0;
+	
+	if (storm!=OP_STORM_BCST && storm!=OP_STORM_MCST && storm!=OP_STORM_ARP)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+
+	switch (storm)
+	{
+		case OP_STORM_BCST:
+		case OP_STORM_MCST:
+			u8dat = P1REG_BSTORMTHRESH;	break;
+
+		case OP_STORM_ARP:
+			u8dat = P1REG_ARPSTORMCFG;	break;
+	}
+
+	*ptrInt = (int)_ReadRegBits(1, u8dat, 10, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetStormBlockFrm2Cpu);
+int getStormBlockFrm2Cpu(void *cdata, int len)
+{
+	u8 storm;
+	int en;
+
+	ip1811drv_dbg("ip1811: +getStormBlockFrm2Cpu...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+
+	if(switchdGetStormBlockFrm2Cpu(storm, &en) != 0)
+		return -EINVAL;
+
+	((struct StormGeneralSetting *)cdata) ->sdata = en;
+	ip1811drv_dbg("cdata ->sdata=0x%08x\n", (unsigned int)((struct StormGeneralSetting *)cdata) ->sdata);
+	ip1811drv_dbg("ip1811: -getStormBlockFrm2Cpu...\n");
+	return 0;
+}
+
+int switchdSetStormDropInterrupt(u8 storm, int en)
+{
+	if (storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+	ip1811drv_dbg("en=0x%08x\n", en);
+
+	switch (storm)
+	{
+		case OP_STORM_ARP:
+			_WriteRegBits(1, P1REG_ARPSTORMCFG, 11, 1, (en == OP_FUNC_DISABLE)?0:1);
+			break;
+
+		case OP_STORM_ICMP:
+			_WriteRegBits(1, P1REG_ICMPSTORMCFG, 10, 1, (en == OP_FUNC_DISABLE)?0:1);
+			break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetStormDropInterrupt);
+int setStormDropInterrupt(void *cdata, int len)
+{
+	u8 storm;
+	int en;
+
+	ip1811drv_dbg("ip1811: +setStormDropInterrupt...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+	en = ((struct StormGeneralSetting *)cdata) ->sdata;
+
+	if(switchdSetStormDropInterrupt(storm, en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setStormDropInterrupt...\n");
+	return 0;
+}
+
+int switchdGetStormDropInterrupt(u8 storm, int *ptrInt)
+{
+	if (storm!=OP_STORM_ARP && storm!=OP_STORM_ICMP)
+		return -EINVAL;
+	ip1811drv_dbg("storm=0x%02X\n", storm);
+
+	switch (storm)
+	{
+		case OP_STORM_ARP:
+			*ptrInt = (int)_ReadRegBits(1, P1REG_ARPSTORMCFG, 11, 1);
+			break;
+
+		case OP_STORM_ICMP:
+			*ptrInt = (int)_ReadRegBits(1, P1REG_ICMPSTORMCFG, 10, 1);
+			break;
+	}
+	
+	ip1811drv_dbg("cdata ->sdata=0x%08x\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetStormDropInterrupt);
+int getStormDropInterrupt(void *cdata, int len)
+{
+	u8 storm;
+	int en;
+
+	ip1811drv_dbg("ip1811: +getStormDropInterrupt...\n");
+	if (sizeof(struct StormGeneralSetting) != len)
+		return -EINVAL;
+
+	storm = ((struct StormGeneralSetting *)cdata) ->storm;
+
+	if(switchdGetStormDropInterrupt(storm, &en) != 0)
+		return -EINVAL;
+		
+	((struct StormGeneralSetting *)cdata) ->sdata = en;
+	
+	ip1811drv_dbg("ip1811: -getStormDropInterrupt...\n");
+	return 0;
+}
+
+//------------------------------------------------
+//common_loop_detect
+int switchdSetLdFunc(unsigned int pm, int en)
+{
+	u16 u16dat;
+	if (pm & 0xF000)
+		return -EINVAL;
+
+	ip1811drv_dbg("pm=0x%08x\n", pm);
+	ip1811drv_dbg("en=%d\n", en);
+	_WriteRegBits(1, P1REG_MISCCFG, 11, 1, en);
+
+	IP2Page(0);
+	u16dat = Read_Reg(P0REG_LDEN);
+	u16dat = ((u16dat & 0xF000) | pm);
+	Write_Reg(P0REG_LDEN, u16dat);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLdFunc);
+
+int setLdFunc(void *cdata, int len)
+{
+	unsigned long pm;
+	int en, ret;
+	u32 u32dat;
+
+	ip1811drv_dbg("ip1811: +setLdFunc...\n");
+	if (sizeof(struct PortmapSetting) != len) {
+		ret = -EINVAL;
+		goto out_setLdFunc;
+	}
+
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	en = ((struct PortmapSetting *)cdata) ->pmdata;
+	ret = switchdSetLdFunc(pm, en);
+
+out_setLdFunc:
+	ip1811drv_dbg("ip1811: -setLdFunc...\n");
+	return ret;
+}
+
+int switchdGetLdFunc(unsigned long *portmap, int *pmdata)
+{
+	u16 u16dat;
+	
+	IP2Page(1);
+	u16dat = Read_Reg(P1REG_MISCCFG);
+	if(u16dat & 0x0800)
+		*pmdata = OP_FUNC_ENABLE;
+	else
+		*pmdata = OP_FUNC_DISABLE;
+
+	IP2Page(0);
+	u16dat = Read_Reg(P0REG_LDEN);
+	*portmap = (u16dat & 0xFFF);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLdFunc);
+
+int getLdFunc(void *cdata, int len)
+{
+	int ret;
+	int pmdata;
+	unsigned long portmap;
+
+	ip1811drv_dbg("ip1811: +getLdFunc...\n");
+	if (sizeof(struct PortmapSetting) != len) {
+		ret = -EINVAL;
+		goto out_getLdFunc;
+	}
+
+	ret = switchdGetLdFunc(&portmap, &pmdata);
+
+	((struct PortmapSetting *)cdata) ->portmap = portmap;
+	((struct PortmapSetting *)cdata) ->pmdata = pmdata;
+
+	ip1811drv_dbg("cdata ->portmap=0x%08x\n", ((struct PortmapSetting *)cdata) ->portmap);
+	ip1811drv_dbg("cdata ->pmdata=%d\n", ((struct PortmapSetting *)cdata) ->pmdata);
+
+out_getLdFunc:
+	ip1811drv_dbg("ip1811: -getLdFunc...\n");
+	return ret;
+}
+
+int switchdSetLdTimeUnit(int time_unit)
+{
+	if (time_unit!=OP_LD_TIME_UNIT_500MS && time_unit!=OP_LD_TIME_UNIT_10S)
+		return -EINVAL;
+	ip1811drv_dbg("tunit=%d\n", time_unit);
+
+	_WriteRegBits(0, P0REG_LDCONFIG, 0, 1, time_unit);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLdTimeUnit);
+
+int setLdTimeUnit(void *cdata, int len)
+{
+	int tunit, ret;
+
+	ip1811drv_dbg("ip1811: +setLdTimeUnit...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+		goto out_setLdTimeUnit;
+	}
+
+	tunit = ((struct GeneralSetting *)cdata) ->gdata;
+	ret = switchdSetLdTimeUnit(tunit);
+
+out_setLdTimeUnit:
+	ip1811drv_dbg("ip1811: -setLdTimeUnit...\n");
+	return ret;
+}
+
+int switchdGetLdTimeUnit(int *time_unit_get)
+{
+	*time_unit_get = (int)_ReadRegBits(0, P0REG_LDCONFIG, 0, 1);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLdTimeUnit);
+
+int getLdTimeUnit(void *cdata, int len)
+{
+	int val, ret;
+	ip1811drv_dbg("ip1811: +getLdTimeUnit...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+	}
+
+	ret = switchdGetLdTimeUnit(&val);
+	((struct GeneralSetting *)cdata) ->gdata = val;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+
+out_getLdTimeUnit:
+	ip1811drv_dbg("ip1811: -getLdTimeUnit...\n");
+	return ret;
+}
+
+int switchdSetLdPktSendTimer(int timer)
+{
+	if (timer < 0 || timer > 0xFF)
+		return -EINVAL;
+	ip1811drv_dbg("timer=%d\n", timer);
+
+	_WriteRegBits(0, P0REG_LDTIMER, 0, 8, timer);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLdPktSendTimer);
+
+int setLdPktSendTimer(void *cdata, int len)
+{
+	int timer, ret;
+
+	ip1811drv_dbg("ip1811: +setLdPktSendTimer...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+		goto out_setLdPktSendTimer;
+	}
+
+	timer = ((struct GeneralSetting *)cdata) ->gdata;
+	ret = switchdSetLdPktSendTimer(timer);
+
+out_setLdPktSendTimer:
+	ip1811drv_dbg("ip1811: -setLdPktSendTimer...\n");
+	return ret;
+}
+
+int switchdGetLdPktSendTimer(int *send_timer_get)
+{
+	*send_timer_get = (int)_ReadRegBits(0, P0REG_LDTIMER, 0, 8);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLdPktSendTimer);
+
+int getLdPktSendTimer(void *cdata, int len)
+{
+	int val, ret;
+	ip1811drv_dbg("ip1811: +getLdPktSendTimer...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+		goto out_getLdPktSendTimer;
+	}
+
+	ret = switchdGetLdPktSendTimer(&val);
+	((struct GeneralSetting *)cdata) ->gdata = val;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+
+out_getLdPktSendTimer:
+	ip1811drv_dbg("ip1811: -getLdPktSendTimer...\n");
+	return ret;
+}
+
+int switchdSetLdBlockReleaseTimer(int timer)
+{
+	if (timer < 0 || timer > 0xFF)
+		return -EINVAL;
+	ip1811drv_dbg("timer=%d\n", timer);
+
+	_WriteRegBits(0, P0REG_LDTIMER, 8, 8, timer);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLdBlockReleaseTimer);
+
+int setLdBlockReleaseTimer(void *cdata, int len)
+{
+	int timer, ret;
+
+	ip1811drv_dbg("ip1811: +setLdBlockReleaseTimer...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+		goto out_setLdBlockReleaseTimer;
+	}
+
+	timer = ((struct GeneralSetting *)cdata) ->gdata;
+	ret = switchdSetLdBlockReleaseTimer(timer);
+
+out_setLdBlockReleaseTimer:	
+	ip1811drv_dbg("ip1811: -setLdBlockReleaseTimer...\n");
+	return ret;
+}
+
+int switchdGetLdBlockReleaseTimer(int *release_timer_get)
+{
+	*release_timer_get = (int)_ReadRegBits(0, P0REG_LDTIMER, 8, 8);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLdBlockReleaseTimer);
+
+int getLdBlockReleaseTimer(void *cdata, int len)
+{
+	int val, ret;
+	ip1811drv_dbg("ip1811: +getLdBlockReleaseTimer...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+		goto out_getLdBlockReleaseTimer;
+	}
+
+	ret = switchdGetLdBlockReleaseTimer(&val);
+	((struct GeneralSetting *)cdata) ->gdata = val;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+
+out_getLdBlockReleaseTimer:
+	ip1811drv_dbg("ip1811: -getLdBlockReleaseTimer...\n");
+	return ret;
+}
+
+int switchdGetLdStatus(unsigned long *status)
+{
+	IP2Page(0);
+	*status = Read_Reg(P0REG_LDSTATUS);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLdStatus);
+
+int getLdStatus(void *cdata, int len)
+{
+	unsigned long val;
+	int ret;
+
+	ip1811drv_dbg("ip1811: +getLdStatus...\n");
+	if (sizeof(struct PortMemberSetting) != len) {
+		ret = -EINVAL;
+		goto out_getLdStatus;
+	}
+
+	ret = switchdGetLdStatus(&val);
+	((struct PortMemberSetting *)cdata) ->member = val;
+	ip1811drv_dbg("cdata ->member=%08lX\n", ((struct PortMemberSetting *)cdata) ->member);
+
+out_getLdStatus:
+	ip1811drv_dbg("ip1811: -getLdStatus...\n");
+	return ret;
+}
+
+//ip1811_loop_detect
+int switchdSetLdDMAC(unsigned char *mac)
+{
+	int i;
+	u16 u16dat;
+
+	IP2Page(0);
+	for (i=0; i<3; i++) {
+		u16dat = (u16)( (mac[i*2] << 8) | mac[i*2+1] );
+		Write_Reg(P0REG_LDDA0+2-i, u16dat);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLdDMAC);
+
+int setLdDMAC(void *cdata, int len)
+{
+	int i, ret;
+	u8  da[6];
+
+	ip1811drv_dbg("ip1811: +setLdDMAC...\n");
+	if (sizeof(struct LDDASetting) != len) {
+		ret = -EINVAL;
+		goto out_setLdDMAC;
+	}
+
+	ip1811drv_dbg("da=[");
+	for (i=0; i<6; i++) {
+		da[i] = ((struct LDDASetting *)cdata) ->da[i];
+		ip1811drv_dbg("0x%02X, ", da[i]);
+	}
+	ip1811drv_dbg("]\n");
+	ret = switchdSetLdDMAC(da);
+
+out_setLdDMAC:
+	ip1811drv_dbg("ip1811: -setLdDMAC...\n");
+	return 0;
+}
+
+int switchdSetLdSubType(int stype)
+{
+	IP2Page(0);
+	Write_Reg(P0REG_LDSUBTYPE, (u16)stype);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLdSubType);
+
+int setLdSubType(void *cdata, int len)
+{
+	int stype, ret;
+
+	ip1811drv_dbg("ip1811: +setLdSubType...\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ret = -EINVAL;
+		goto out_setLdSubType;
+	}
+
+	stype = ((struct GeneralSetting *)cdata) ->gdata;
+	if (stype<0 && stype>0xFFFF) {
+		ret = -EINVAL;
+		goto out_setLdSubType;
+	}
+	ip1811drv_dbg("stype=%d\n", stype);
+
+	ret = switchdSetLdSubType(stype);
+
+out_setLdSubType:
+	ip1811drv_dbg("ip1811: -setLdSubType...\n");
+	return 0;
+}
+//------------------------------------------------
+//common_stag
+int switchdSetCpuPortLink(int clink)
+{
+	if (clink!=OP_CPU_PORT_NORMAL && clink!=OP_CPU_PORT_CPU)
+		return -EINVAL;
+	ip1811drv_dbg("clink=%d\n", clink);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetCpuPortLink);
+int setCpuPortLink(void *cdata, int len)
+{
+	int clink;
+
+	ip1811drv_dbg("ip1811: +setCpuPortLink...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	clink = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetCpuPortLink(clink) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setCpuPortLink...\n");
+	return 0;
+}
+
+int switchdSetSTagFunc(int en)
+{
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("en=%d\n", en);
+
+	if(en == OP_FUNC_ENABLE){
+		_WriteRegBits(0xE, PEREG_CPUMODE, 0, 2 , 0x3);
+	}else{
+		_WriteRegBits(0xE, PEREG_CPUMODE, 0, 2 , 0x0);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetSTagFunc);
+int setSTagFunc(void *cdata, int len)
+{
+	int en;
+
+	ip1811drv_dbg("ip1811: +setSTagFunc...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetSTagFunc(en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setSTagFunc...\n");
+	return 0;
+}
+
+void switchdGetSTagTypeLen(unsigned short *ptrLength, unsigned short *ptrType)
+{
+	IP2Page(0xE);
+	*ptrType= Read_Reg(PEREG_SPTAG);
+	*ptrLength = 0;
+	ip1811drv_dbg("cdata ->length=%d\n", *ptrLength);
+	ip1811drv_dbg("cdata ->type=0x%08x\n", *ptrType);
+}
+EXPORT_SYMBOL(switchdGetSTagTypeLen);
+int getSTagTypeLen(void *cdata, int len)
+{
+	unsigned short type, length;
+
+	ip1811drv_dbg("ip1811: +getSTagTypeLen...\n");
+	if (sizeof(struct STagTypeLenSetting) != len)
+		return -EINVAL;
+
+	switchdGetSTagTypeLen(&length, &type);
+
+	((struct STagTypeLenSetting *)cdata) ->length = (unsigned int)length;
+	((struct STagTypeLenSetting *)cdata) ->type = (unsigned int)type;
+	ip1811drv_dbg("ip1811: -getSTagTypeLen...\n");
+	return 0;
+}
+
+//------------ PTP functions:common Start  -----------------------
+int setPTPEnable(void *cdata, int len)
+{
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPEnable(void *cdata, int len)
+{
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPDA011B19000000(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 1);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPDA011B19000000(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 1);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPDA0180C200000E(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 2);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPDA0180C200000E(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 2);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPUdpDP(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 3);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPUdpDP(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 3);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPUdpSP(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 4);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPUdpSP(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_PTPCFG, 4);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPToCPU(void *cdata, int len)
+{
+	int gdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	gdata = ((struct GeneralSetting *)cdata) ->gdata;
+	if( gdata != OP_CAP_ACT_TO_CPU && gdata != OP_CAP_ACT_FORWARD )
+	{
+		ip1811drv_err("Error: gdata=%X\n", gdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", gdata);
+
+	_WriteRegBits(0, P0REG_PTPCFG, 5, 1, gdata==OP_CAP_ACT_TO_CPU?0x0:0x1);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getPTPToCPU(void *cdata, int len)
+{
+	int gdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	gdata = (_ReadRegBits(0, P0REG_PTPCFG, 5, 1)==0x0?OP_CAP_ACT_TO_CPU:OP_CAP_ACT_FORWARD);
+	((struct GeneralSetting *)cdata) ->gdata = gdata;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", gdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setPTPSpecialTag(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x07, P7REG_TXDMA, 5);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPSpecialTag(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0x07, P7REG_TXDMA, 5);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPClockReset(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CLOCK_RESET, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPTimeStamp(void *cdata, int len){
+	unsigned int cmd=0, port=0;
+	struct PTPReadSetting* ps=(struct PTPReadSetting*)cdata;
+
+	if(sizeof(struct PTPReadSetting) != len)
+		return -EINVAL;
+
+	cmd=ps->addr;
+	cmd|=(ps->in_out)<<4;
+	port = ps->port;
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	cmd|=(port)<<5;
+	cmd|=0x8000;
+
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_TIMESTAMP_READ, (u16)cmd);
+
+	while((Read_Reg(P9REG_PTP_TIMESTAMP_READ) >> 15)&0x1);
+
+	ps->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC2);
+	ps->second<<=16;
+	ps->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC1);
+	ps->second<<=16;
+	ps->second|=Read_Reg(P9REG_PTP_TIMEDATA_SEC0);
+	ps->nanosecond=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC1);
+	ps->nanosecond<<=16;
+	ps->nanosecond|=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC0);
+
+	return 0;
+}
+
+int setPTPClockEnable(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPClockEnable(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPOverwriteEnable(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 1);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPOverwriteEnable(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 1);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPProgrammable(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 2);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getPTPProgrammable(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 2);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPProgrammableOut(void *cdata, int len){
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x09, P9REG_PTP_CONFIGURATION, 9);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int setPTPTimestampEnable(void *cdata, int len){
+	unsigned int cmd=0, i=0;
+	struct PTPPortTSSetting* pts=(struct PTPPortTSSetting*)cdata;
+
+	if(sizeof(struct PTPPortTSSetting)!=len)
+		return -EINVAL;
+	IP2Page(0x09);
+	for(i=0;i<MAX_PHY_NUM;i++){
+		if((i%8)==0){
+			cmd=Read_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8));
+		}
+
+		if((pts->portmap&(0x01<<i))!=0){
+			if(pts->pmdata==OP_FUNC_ENABLE){
+				if(pts->in_out){
+					//egress
+					cmd|=0x01<<(1+(2*(i%8)));
+				}
+				else{
+					//ingress
+					cmd|=0x01<<(2*(i%8));
+				}
+			}
+			else{
+				if(pts->in_out){
+					//egress
+					cmd&=~(0x01<<(1+(2*(i%8))));
+				}
+				else{
+					//ingress
+					cmd&=~(0x01<<(2*(i%8)));
+				}
+			}
+		}
+		if((i%8)==7){
+			Write_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8), (u16)cmd);
+		}
+	}
+	Write_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8), (u16)cmd);
+
+	return 0;
+}
+
+int getPTPTimestampEnable(void *cdata, int len){
+	unsigned int cmd=0, i=0;
+	struct PTPPortTSSetting* pts=(struct PTPPortTSSetting*)cdata;
+
+	if(sizeof(struct PTPPortTSSetting)!=len)
+		return -EINVAL;
+
+	pts->pmdata=OP_FUNC_ENABLE;
+	pts->portmap=0;
+	IP2Page(0x09);
+	for(i=0;i<MAX_PHY_NUM;i++){
+		if((i%8)==0)
+			cmd=Read_Reg(P9REG_PTP_PORT_TIMESTAMP0+(i/8));
+
+		if(pts->in_out){
+			//egress
+			if((cmd&(0x01<<(1+(2*(i%8)))))!=0)
+				pts->portmap|=(0x01<<i);
+		}
+		else{
+			//ingress
+			if((cmd&(0x01<<(2*(i%8))))!=0)
+				pts->portmap|=(0x01<<i);
+		}
+	}
+
+	return 0;
+}
+
+int setPTPTimestampClear(void *cdata, int len){
+	unsigned int cmd=0, i=0;
+	struct PTPPortTSSetting* pts=(struct PTPPortTSSetting*)cdata;
+
+	if(sizeof(struct PTPPortTSSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	for(i=0;i<MAX_PHY_NUM;i++){
+		if((pts->portmap&(0x01<<i))!=0){
+			if(pts->in_out){
+				//egress
+				cmd|=0x01<<(1+(2*(i%8)));
+			}
+			else{
+				//ingress
+				cmd|=0x01<<(2*(i%8));
+			}
+		}
+		if((i%8)==7 && cmd!=0){
+			Write_Reg(P9REG_PTP_TIMESTAMP_CLEAR0+(i/8), (u16)cmd);
+			cmd=0;
+		}
+	}
+	if(cmd){
+		Write_Reg(P9REG_PTP_TIMESTAMP_CLEAR0+(i/8), (u16)cmd);
+	}
+
+	return 0;
+}
+
+int setPTPTimeData(void *cdata, int len){
+	struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata;
+
+	if(sizeof(struct PTPTimeSetting)!=len)
+		return -EINVAL;
+	
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC0, (u16)(ts->second&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC1, (u16)((ts->second>>16)&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC2, (u16)((ts->second>>32)&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC0, (u16)(ts->nanosecond&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC1, (u16)((ts->nanosecond>>16)&0x3FFF));
+	Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x03);
+
+	return 0;
+}
+
+int getPTPTimeData(void *cdata, int len){
+	struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata;
+
+	if(sizeof(struct PTPTimeSetting)!=len)
+		return -EINVAL;
+	
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_TIMESTAMP_READ, 0);
+	Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x01);
+
+	ts->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC2);
+	ts->second<<=16;
+	ts->second=Read_Reg(P9REG_PTP_TIMEDATA_SEC1);
+	ts->second<<=16;
+	ts->second|=Read_Reg(P9REG_PTP_TIMEDATA_SEC0);
+
+	ts->nanosecond=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC1);
+	ts->nanosecond<<=16;
+	ts->nanosecond|=Read_Reg(P9REG_PTP_TIMEDATA_NANOSEC0);
+
+	return 0;
+}
+
+int addPTPTimeData(void *cdata, int len){
+	struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata;
+
+	if(sizeof(struct PTPTimeSetting)!=len)
+		return -EINVAL;
+	
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC0, (u16)(ts->second&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC1, (u16)((ts->second>>16)&0xFFFF));
+//	Write_Reg(P9REG_PTP_TIMEDATA_SEC2, (u16)((ts->second>>32)&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC0, (u16)(ts->nanosecond&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC1, (u16)((ts->nanosecond>>16)&0x3FFF));
+	Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x05);
+
+	return 0;
+}
+
+int subPTPTimeData(void *cdata, int len){
+	struct PTPTimeSetting* ts=(struct PTPTimeSetting*)cdata;
+
+	if(sizeof(struct PTPTimeSetting)!=len)
+		return -EINVAL;
+	
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC0, (u16)(ts->second&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_SEC1, (u16)((ts->second>>16)&0xFFFF));
+//	Write_Reg(P9REG_PTP_TIMEDATA_SEC2, (u16)((ts->second>>32)&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC0, (u16)(ts->nanosecond&0xFFFF));
+	Write_Reg(P9REG_PTP_TIMEDATA_NANOSEC1, (u16)((ts->nanosecond>>16)&0x3FFF));
+	Write_Reg(P9REG_PTP_CLOCK_CONTROL, 0x07);
+
+	return 0;
+}
+
+int setPTPFrequencyAdd(void *cdata, int len){
+	struct PTPFrequencySetting* fs=(struct PTPFrequencySetting*)cdata;
+
+	if(sizeof(struct PTPFrequencySetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_FREQUENCY_ADD0, (u16)(fs->frequency&0xFFFF));
+	Write_Reg(P9REG_PTP_FREQUENCY_ADD1, (u16)((fs->frequency>>16)&0xFFFF));
+
+	return 0;
+}
+
+int getPTPFrequencyAdd(void *cdata, int len){
+	struct PTPFrequencySetting* fs=(struct PTPFrequencySetting*)cdata;
+
+	if(sizeof(struct PTPFrequencySetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	fs->frequency=Read_Reg(P9REG_PTP_FREQUENCY_ADD1);
+	fs->frequency<<=16;
+	fs->frequency|=Read_Reg(P9REG_PTP_FREQUENCY_ADD0);
+
+	return 0;
+}
+
+int setPTPClockPeriod(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_CLOCK_PERIOD, (u16)(((struct GeneralSetting*)cdata)->gdata)&0xFFFF);
+
+	return 0;
+}
+
+int getPTPClockPeriod(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_CLOCK_PERIOD);
+
+	return 0;
+}
+
+int setPTPProgrammableConfig(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_PROGRAMMABLE_OUTPUT, (u16)(((struct GeneralSetting*)cdata)->gdata)&0xFFFF);
+
+	return 0;
+}
+
+int setPTPDurationFrequencyCompensation(void *cdata, int len){
+	struct PTPFrequencySetting* fs=(struct PTPFrequencySetting*)cdata;
+
+	if(sizeof(struct PTPFrequencySetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION0, (u16)(fs->frequency&0xFFFF));
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION1, (u16)((fs->frequency>>16)&0x3FF));
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION2, (u16)(fs->clockcycle&0xFFFF));
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION3, (u16)((fs->clockcycle>>16)&0x3FF));
+	if(fs->type==1){
+		//add
+		Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x03);
+	}
+	else{
+		//sub
+		Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x07);
+	}
+	//Wait a period of time
+	ndelay(fs->period_time);
+
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x0);
+
+	return 0;
+}
+
+int setPTPAlwaysFrequencyCompensation(void *cdata, int len){
+	struct PTPFrequencyPPMSetting* fps=(struct PTPFrequencyPPMSetting*)cdata;
+
+	if(sizeof(struct PTPFrequencyPPMSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION0, (u16)(fps->ppm_l));
+	Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION1, (u16)(fps->ppm_h));
+	if(fps->type==1){
+		//add
+		Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x01);
+	}
+	else{
+		//Sub
+		Write_Reg(P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL, 0x05);
+	}
+
+	return 0;
+}
+
+int getPTPIngressLatency10(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_INGRESS_LATENCY_10TP);
+
+	return 0;
+}
+
+int getPTPIngressLatency100(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_INGRESS_LATENCY_100TP);
+
+	return 0;
+}
+
+int getPTPIngressLatencyFiber(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_INGRESS_LATENCY_FIBER);
+
+	return 0;
+}
+
+int getPTPEgressLatency10(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_EGRESS_LATENCY_10TP);
+
+	return 0;
+}
+
+int getPTPEgressLatency100(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_EGRESS_LATENCY_100TP);
+
+	return 0;
+}
+
+int getPTPEgressLatencyFiber(void *cdata, int len){
+	if(sizeof(struct GeneralSetting)!=len)
+		return -EINVAL;
+
+	IP2Page(0x09);
+	((struct GeneralSetting*)cdata)->gdata=Read_Reg(P9REG_PTP_EGRESS_LATENCY_FIBER);
+
+	return 0;
+}
+//------------ PTP functions:common end  -----------------------
+
+int switchdConfigCpuPort(int portid)
+{
+	ip1811drv_dbg("portid=%d\n", portid);
+	if (portid < 0 || portid >= 12)
+		return -EINVAL;
+
+	IP2Page(1);
+	Write_Reg(P1REG_CONFIG_CPUPORT, (portid + 1) | 0x20);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdConfigCpuPort);
+int configCpuPort(void *cdata, int len)
+{
+	int portid;
+
+	ip1811drv_dbg("ip1811: +configCpuPort...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	portid = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdConfigCpuPort(portid) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -configCpuPort...\n");
+	return 0;
+}
+
+int switchdGetCpuPort(int *ptrVal)
+{
+	*ptrVal = Read_Reg(P1REG_CONFIG_CPUPORT);
+	ip1811drv_dbg("portid=%d\n", *ptrVal);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetCpuPort);
+int getCpuPort(void *cdata, int len)
+{
+	int portid;
+
+	ip1811drv_dbg("ip1811: +getCpuPort...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+
+	if(switchdGetCpuPort(&portid) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = portid;
+	ip1811drv_dbg("ip1811: -getCpuPort...\n");
+	return 0;
+}
+//------------------------------------------------
+//common_misc
+
+int switchdSet8021xFunc(int en, unsigned long pm)
+{
+	unsigned long reg16;
+	
+	if (pm & 0xF0000000)
+		return -EINVAL;
+	if (en != OP_FUNC_ENABLE && en != OP_FUNC_DISABLE)
+		return -EINVAL;
+
+	IP2Page(0);
+	if(en == OP_FUNC_ENABLE) {
+		reg16 = Read_Reg(P0REG_PORTLOCKEN);
+		Write_Reg(P0REG_PORTLOCKEN, (u16)(reg16 | pm));
+	} else {//OP_FUNC_DISABLE
+		reg16 = Read_Reg(P0REG_PORTLOCKEN);
+		Write_Reg(P0REG_PORTLOCKEN, (u16)(reg16 & ~pm));
+	}
+	return 0;
+}
+EXPORT_SYMBOL(switchdSet8021xFunc);
+
+int set8021xFunc(void *cdata, int len)
+{
+	unsigned long pm;
+	int en, ret;
+
+	ip1811drv_dbg("ip1811: +set8021xFunc...\n");
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	en = ((struct PortmapSetting *)cdata) ->pmdata;
+	
+	ip1811drv_dbg("pm=0x%08x\n", (unsigned int)pm);
+	ip1811drv_dbg("en=%d\n", en);
+	ret = switchdSet8021xFunc(en, pm);
+
+	ip1811drv_dbg("ip1811: -set8021xFunc...\n");
+	return ret;
+}
+
+int switchdGet8021xFunc(int *gdata_p)
+{
+	IP2Page(0);
+	*gdata_p = (int)Read_Reg(P0REG_PORTLOCKEN);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGet8021xFunc);
+
+int get8021xFunc(void *cdata, int len)
+{
+	int val, ret;
+
+	ip1811drv_dbg("ip1811: +get8021xFunc...\n");
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+
+	ret = switchdGet8021xFunc(&val);
+	((struct PortmapSetting *)cdata) ->portmap = (val & ALL_PHY_PORTS_LIST);
+	((struct PortmapSetting *)cdata) ->pmdata = val?OP_FUNC_ENABLE:OP_FUNC_DISABLE;
+	ip1811drv_dbg("cdata ->portmap=0x%08x\n", (unsigned int)((struct PortmapSetting *)cdata) ->portmap);
+	ip1811drv_dbg("cdata ->pmdata=%d\n", ((struct PortmapSetting *)cdata) ->pmdata);
+	ip1811drv_dbg("ip1811: -get8021xFunc...\n");
+	return ret;
+}
+
+int switchdSetReg(u8 page, u8 reg, u16 val)
+{
+	if (page > 0xE)
+		return -EINVAL;
+	ip1811drv_dbg("page=0x%x\n", page);
+	ip1811drv_dbg("reg=0x%02X\n", reg);
+	ip1811drv_dbg("val=0x%04x\n", val);
+
+	_IP2Page(page);
+	//	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG,
+	//				RegList[pg][P2REG_VLANCFG]);
+	_Write_Reg(reg, val);
+
+	//	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG,
+	//				RegList[pg][P2REG_VLANCFG]);
+	ip1811drv_dbg("ip1811: -setReg...\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetReg);
+int setReg(void *cdata, int len)
+{
+	u8 page, reg;
+	u16 val;
+
+	ip1811drv_dbg("ip1811: +setReg...\n");
+	if (sizeof(struct RegSetting) != len)
+		return -EINVAL;
+
+	page= ((struct RegSetting *)cdata) ->page;
+	reg = ((struct RegSetting *)cdata) ->reg;
+	val = ((struct RegSetting *)cdata) ->val;
+
+	if(switchdSetReg(page, reg, val) != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+
+int switchdGetReg(u8 page, u8 reg, u16 *ptrVal)
+{
+
+	if (page > 0xE)
+		return -EINVAL;
+	ip1811drv_dbg("page=0x%x\n", page);
+	printk("page=0x%x\n", page);
+	ip1811drv_dbg("reg=0x%02X\n", reg);
+	printk("reg=0x%02X\n", reg);
+
+	_IP2Page(page);
+	//	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG,
+	//				RegList[pg][P2REG_VLANCFG]);
+	*ptrVal= _Read_Reg(reg);
+	ip1811drv_dbg("u16dat=0x%04x\n", *ptrVal);
+	printk("u16dat=0x%04x\n", *ptrVal);
+
+	//	ip1811drv_dbg("RegList[%x][0x%02X]=0x%04x\n", pg, P2REG_VLANCFG,
+	//				RegList[pg][P2REG_VLANCFG]);
+	ip1811drv_dbg("cdata ->val=0x%04x\n", *ptrVal);
+	ip1811drv_dbg("ip1811: -getReg...\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetReg);
+int getReg(void *cdata, int len)
+{
+	u8 page, reg;
+	u16 u16dat;
+
+	printk("ip1811: +getReg...\n");
+	ip1811drv_dbg("ip1811: +getReg...\n");
+	if (sizeof(struct RegSetting) != len)
+		return -EINVAL;
+
+	page= ((struct RegSetting *)cdata) ->page;
+	reg = ((struct RegSetting *)cdata) ->reg;
+
+	if(switchdGetReg(page, reg, &u16dat) != 0)
+		return -EINVAL;
+
+	((struct RegSetting *)cdata) ->val = (unsigned short)u16dat;
+	return 0;
+}
+
+void switchdGetCPUReg(unsigned long reg, int * ptrVal)
+{
+	volatile unsigned int *p;
+
+	p = (unsigned int *)(reg);
+	*ptrVal = *p;
+
+	ip1811drv_dbg("reg=%lX\n", reg);
+	ip1811drv_dbg("get val=%X\n", *ptrVal);
+}
+EXPORT_SYMBOL(switchdGetCPUReg);
+int getCPUReg(void *cdata, int len)
+{
+	unsigned long reg;
+	int val;
+
+	FUNC_MSG_IN;
+
+	if (sizeof(struct PortmapSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	reg = ((struct PortmapSetting *)cdata) ->portmap;
+
+	switchdGetCPUReg(reg, &val);
+
+	((struct PortmapSetting *)cdata) ->pmdata = val;
+	ip1811delay();
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdSetCPUReg(unsigned long reg, int val)
+{
+	volatile unsigned int *p;
+
+	p = (unsigned int *)(reg);
+	*p = val;
+
+	ip1811drv_dbg("reg=%lX\n", reg);
+	ip1811drv_dbg("set val=%X\n", val);
+}
+EXPORT_SYMBOL(switchdSetCPUReg);
+int setCPUReg(void *cdata, int len)
+{
+	unsigned long reg;
+	int val;
+
+	FUNC_MSG_IN;
+
+	if (sizeof(struct PortmapSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	reg = ((struct PortmapSetting *)cdata) ->portmap;
+	val = ((struct PortmapSetting *)cdata) ->pmdata;
+
+	switchdSetCPUReg(reg, val);
+
+	ip1811delay();
+
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetSwitchRestart(int en)
+{
+	if(en!=OP_FUNC_ENABLE){
+		ip1811drv_err("Error: en=%d\n", en);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("reset the switch of IP1811, all parameters are maintained\n");
+	_WriteRegBits(0xE, PEREG_SW_RESET, 0, 1, en);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetSwitchRestart);
+int setSwitchRestart(void *cdata, int len)
+{
+	int en;
+	FUNC_MSG_IN;
+
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetSwitchRestart(en) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetSwitchReset(int en)
+{
+
+	if(en!=OP_FUNC_ENABLE){
+		ip1811drv_err("Error: en=%d\n", en);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("reset the switch of IP1811, all parameters are reset to default\n");
+	_WriteRegBits(0xE, PEREG_SW_RESET, 4, 1, en);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetSwitchReset);
+int setSwitchReset(void *cdata, int len)
+{
+	int en;
+
+	FUNC_MSG_IN;
+
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetSwitchReset(en) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdSetCpuIfSpeed(int type)
+{
+	CPU_IF_SPEED_NORMAL = type;
+	printk("\nip1811: set CPU I/F speed to %s\n",CPU_IF_SPEED_NORMAL?"Normal":"High");
+}
+EXPORT_SYMBOL(switchdSetCpuIfSpeed);
+int setCpuIfSpeed(void *cdata, int len)
+{
+	int type;
+	FUNC_MSG_IN;
+
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	switchdSetCpuIfSpeed(type);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+//------------ CoS functions:common -----------------------------
+int setCosTcpUdpUserDefine(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+	act = ((struct CapActSetting *)cdata) ->act;
+
+	if( ptcl >= OP_TCPUDP_USER_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	if( act < 0x0 || act > 0xFFFF )
+	{
+		ip1811drv_err("Error: act=%X\n", act);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl);
+	ip1811drv_dbg("cdata ->act=%X\n", act);
+
+	IP2Page(0);
+	Write_Reg(P0REG_TCPUDPUSERDEF + ptcl, (u16)act);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosTcpUdpUserDefine(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+
+	if( ptcl >= OP_TCPUDP_USER_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	IP2Page(0);
+	act = Read_Reg(P0REG_TCPUDPUSERDEF + ptcl);
+	((struct CapActSetting *)cdata) ->act = act;
+
+	ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol);
+	ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setCosTcpUdpQueue(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+	act = ((struct CapActSetting *)cdata) ->act;
+
+	if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	if( act < OP_TCPUDP_ACT_Q0 || act > OP_TCPUDP_ACT_ALL_PORT || act == 0x8)
+	{
+		ip1811drv_err("Error: act=%X\n", act);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl);
+	ip1811drv_dbg("cdata ->act=%X\n", act);
+
+	_WriteRegBits(0, P0REG_TCPUDPPRICFG + ptcl/4, (ptcl%4)*4, 4, act);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosTcpUdpQueue(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+
+	if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	act = _ReadRegBits(0, P0REG_TCPUDPPRICFG + (ptcl/4), (ptcl%4)*4, 4);
+	((struct CapActSetting *)cdata) ->act = act;
+
+	ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol);
+	ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setCosTcpUdpEnable(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_TCPUDFUNCEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int getCosTcpUdpEnable(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmapMask(cdata, len, 0, P0REG_TCPUDFUNCEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int setCosTcpEnable(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+	act = ((struct CapActSetting *)cdata) ->act;
+
+	if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	if( act != OP_FUNC_ENABLE && act != OP_FUNC_DISABLE)
+	{
+		ip1811drv_err("Error: act=%X\n", act);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl);
+	ip1811drv_dbg("cdata ->act=%X\n", act);
+
+	/* check L3 TCP action */
+	if(_ReadRegBits(0, P0REG_L3FRAMEGETCTRL, 2, 2) == OP_CAP_ACT_DROP)
+	{
+		ip1811drv_err("Error: L3 TCP action is drop\n");
+		return -EINVAL;
+	}
+
+	/* set register */
+	_WriteRegBits(0, P0REG_TCPCHECKEN + (ptcl/16), (ptcl%16), 1, act);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosTcpEnable(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+
+	if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	act = _ReadRegBits(0, P0REG_TCPCHECKEN + (ptcl/16), (ptcl%16), 1);
+	((struct CapActSetting *)cdata) ->act = act;
+
+	ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol);
+	ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setCosUdpEnable(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+	act = ((struct CapActSetting *)cdata) ->act;
+
+	if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	if( act != OP_FUNC_ENABLE && act != OP_FUNC_DISABLE)
+	{
+		ip1811drv_err("Error: act=%X\n", act);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->ptcl=%X\n", ptcl);
+	ip1811drv_dbg("cdata ->act=%X\n", act);
+
+	/* check L3 UDP action */
+	if(_ReadRegBits(0, P0REG_L3FRAMEGETCTRL, 4, 2) == OP_CAP_ACT_DROP)
+	{
+		ip1811drv_err("Error: L3 UDP action is drop\n");
+		return -EINVAL;
+	}
+
+	/* set register */
+	_WriteRegBits(0, (P0REG_UDPCHECKEN + ptcl/16), (ptcl%16), 1, act);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosUdpEnable(void *cdata, int len)
+{
+	unsigned int ptcl;
+	int act;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct CapActSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	ptcl = ((struct CapActSetting *)cdata) ->protocol;
+
+	if( ptcl >= OP_TCPUDP_PTCL_TOTALNUM)
+	{
+		ip1811drv_err("Error: protocol=%X\n", ptcl);
+		return -EINVAL;
+	}
+
+	act = _ReadRegBits(0, (P0REG_UDPCHECKEN + ptcl/16), (ptcl%16), 1);
+	((struct CapActSetting *)cdata) ->act = act;
+
+	ip1811drv_dbg("cdata ->protocol=%X\n", ((struct CapActSetting *)cdata) ->protocol);
+	ip1811drv_dbg("cdata ->act=%X\n", ((struct CapActSetting *)cdata) ->act);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setCosTcpFlagDropNull(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 0);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int getCosTcpFlagDropNull(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 0);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int setCosTcpFlagDropAllset(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 1);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int getCosTcpFlagDropAllset(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_TCPFLGCFGGLB, 1);
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int setCosTcpFlag(void *cdata, int len)
+{
+	unsigned int index;
+	int fdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct TcpFlagSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	index = ((struct TcpFlagSetting *)cdata) ->index;
+	if( index > OP_TCPFLAG_FLAG3 )
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	fdata = ((struct TcpFlagSetting *)cdata) ->fdata;
+	if( fdata < 0x0 || fdata > 0xFF )
+	{
+		ip1811drv_err("Error: flag=%X\n", fdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->index=%X\n", index);
+	ip1811drv_dbg("cdata ->fdata=%X\n", fdata);
+
+	_WriteRegBits(0, P0REG_TCPFLGCFG0 + index, 0, 8, fdata);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosTcpFlag(void *cdata, int len)
+{
+	unsigned int index;
+	int fdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct TcpFlagSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	index = ((struct TcpFlagSetting *)cdata) ->index;
+	if( index > OP_TCPFLAG_FLAG3 )
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	fdata = _ReadRegBits(0, P0REG_TCPFLGCFG0 + index, 0, 8);
+	((struct TcpFlagSetting *)cdata) ->index = fdata;
+	ip1811drv_dbg("cdata ->index=%X\n", index);
+	ip1811drv_dbg("cdata ->fdata=%X\n", fdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setCosTcpFlagAct(void *cdata, int len)
+{
+	unsigned int index;
+	int fdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct TcpFlagSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	index = ((struct TcpFlagSetting *)cdata) ->index;
+	if( index > OP_TCPFLAG_FLAG3 )
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	fdata = ((struct TcpFlagSetting *)cdata) ->fdata;
+	if( fdata < OP_TCPFLAG_ACT_NONE || fdata > OP_TCPFLAG_ACT_DROP )
+	{
+		ip1811drv_err("Error: act=%X\n", fdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->index=%X\n", index);
+	ip1811drv_dbg("cdata ->fdata=%X\n", fdata);
+
+	IP2Page(0);
+
+	/* check L3 TCP action */
+	if(_ReadRegBits(0, P0REG_L3FRAMEGETCTRL, 2, 2) == OP_CAP_ACT_DROP)
+	{
+		ip1811drv_err("Error: L3 TCP action is drop\n");
+		return -EINVAL;
+	}
+
+	/* set register */
+	_WriteRegBits(0, P0REG_TCPFLGCFG0 + index, 12, 2, fdata);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosTcpFlagAct(void *cdata, int len)
+{
+	unsigned int index;
+	int fdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct TcpFlagSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	index = ((struct TcpFlagSetting *)cdata) ->index;
+	if( index > OP_TCPFLAG_FLAG3 )
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	fdata = _ReadRegBits(0, P0REG_TCPFLGCFG0 + index, 12, 2);
+	((struct TcpFlagSetting *)cdata) ->fdata = fdata;
+	ip1811drv_dbg("cdata ->index=%X\n", index);
+	ip1811drv_dbg("cdata ->fdata=%X\n", fdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int setCosTcpFlagPort(void *cdata, int len)
+{
+	unsigned int index;
+	int fdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct TcpFlagSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	index = ((struct TcpFlagSetting *)cdata) ->index;
+	if( index > OP_TCPFLAG_FLAG3 )
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	fdata = ((struct TcpFlagSetting *)cdata) ->fdata;
+	if( fdata & ~0xFFF )
+	{
+		ip1811drv_err("Error: portmap=%X\n", fdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->index=%X\n", index);
+	ip1811drv_dbg("cdata ->fdata=%X\n", fdata);
+
+	IP2Page(0);
+
+	Write_Reg(P0REG_TCPFLGPORTEN+index*2, fdata&0xFFF);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getCosTcpFlagPort(void *cdata, int len)
+{
+	unsigned int index;
+	int fdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct TcpFlagSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	index = ((struct TcpFlagSetting *)cdata) ->index;
+	if( index > OP_TCPFLAG_FLAG3 )
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	IP2Page(0);
+	fdata = Read_Reg(P0REG_TCPFLGPORTEN+index*2);
+	((struct TcpFlagSetting *)cdata) ->fdata = fdata;
+	ip1811drv_dbg("cdata ->index=%X\n", index);
+	ip1811drv_dbg("cdata ->fdata=%X\n", fdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+//------------ CoS functions:common end  ------------------------
+
+//------------------------------------------------
+//common_stp
+int switchdSetMstpFunc(int en)
+{
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(2, P2REG_VLANCFG, 6, 1, en); //MSTP enable
+	_WriteRegBits(2, P2REG_VLANCFG, 2, 1, en); //IVL
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetMstpFunc);
+int setMstpFunc(void *cdata, int len)
+{
+	int en;
+
+	ip1811drv_dbg("ip1811: +setMstpFunc...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetMstpFunc(en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setMstpFunc...\n");
+	return 0;
+}
+
+int switchdGetMstpFunc(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(2, P2REG_VLANCFG, 6, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetMstpFunc);
+int getMstpFunc(void *cdata, int len)
+{
+	int en;
+	
+	ip1811drv_dbg("ip1811: +getMstpFunc...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetMstpFunc(&en) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = en;
+	
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getMstpFunc...\n");
+	return 0;
+}
+
+//common_lacp
+int switchdSetTrunkHashMthd(int mthd)
+{
+	if (mthd < OP_TRUNK_HASH_METHOD_PORT_ID || mthd > OP_TRUNK_HASH_METHOD_SP)
+		return -EINVAL;
+	ip1811drv_dbg("mthd=%d\n", mthd);
+
+	_WriteRegBits(1, P1REG_TRUNKCFG, 0, 3, mthd);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetTrunkHashMthd);
+int setTrunkHashMthd(void *cdata, int len)
+{
+	int mthd;
+
+	ip1811drv_dbg("ip1811: +setTrunkHashMthd...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	mthd = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetTrunkHashMthd(mthd) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setTrunkHashMthd...\n");
+	return 0;
+}
+
+int switchdGetTrunkHashMthd(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, 0, 3);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetTrunkHashMthd);
+int getTrunkHashMthd(void *cdata, int len)
+{
+	int mthd;
+
+	ip1811drv_dbg("ip1811: +getTrunkHashMthd...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetTrunkHashMthd(&mthd) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = mthd;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getTrunkHashMthd...\n");
+	return 0;
+}
+
+int switchdSetTrunkMbr(unsigned long pmask, unsigned long state)
+{
+	unsigned long u32dat;
+	
+	if ((pmask & 0xFFFFF000) || !pmask)
+		return -EINVAL;
+	if ((state & 0xFFFFF000) || (state & ~pmask))
+		return -EINVAL;
+	ip1811drv_dbg("pmask=0x%08X\n", pmask);
+	ip1811drv_dbg("state=0x%08X\n", state);
+
+	IP2Page(1);
+	u32dat= (unsigned long)( Read_Reg(P1REG_TRUNKGRP) );
+	pmask = (unsigned long)( pmask&0xFFF );
+	state = (unsigned long)( state&0xFFF );
+	u32dat &= (~pmask);
+	u32dat |= state;
+#ifdef COMBINED_PORT
+	u32dat |= 0x600;
+#endif
+	
+	Write_Reg(P1REG_TRUNKGRP, (u32dat & 0xFFF));
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetTrunkMbr);
+int setTrunkMbr(void *cdata, int len)
+{
+	unsigned long pmask, state, u32dat;
+
+	ip1811drv_dbg("ip1811: +setTrunkMbr...\n");
+	if (sizeof(struct TrunkMemberSetting) != len)
+		return -EINVAL;
+
+	pmask = ((struct TrunkMemberSetting *)cdata) ->portmask;
+	state = ((struct TrunkMemberSetting *)cdata) ->tstate;
+
+	if(switchdSetTrunkMbr(pmask, state) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setTrunkMbr...\n");
+	return 0;
+}
+
+int switchdGetTrunkMbr(unsigned long pmask, unsigned long *ptrInt)
+{
+	if ((pmask & 0xFFFFF000) || !pmask)
+		return -EINVAL;
+	ip1811drv_dbg("pmask=0x%08X\n", pmask);
+
+	IP2Page(1);
+	*ptrInt = (unsigned long)( (Read_Reg(P1REG_TRUNKGRP) & 0xFFF) & pmask );
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetTrunkMbr);
+int getTrunkMbr(void *cdata, int len)
+{
+	unsigned long pmask, u32dat;
+
+	ip1811drv_dbg("ip1811: +getTrunkMbr...\n");
+	if (sizeof(struct TrunkMemberSetting) != len)
+		return -EINVAL;
+
+	pmask = ((struct TrunkMemberSetting *)cdata) ->portmask;
+
+	if(switchdGetTrunkMbr(pmask, &u32dat) != 0)
+		return -EINVAL;
+
+	((struct TrunkMemberSetting *)cdata) ->tstate = u32dat;
+	ip1811drv_dbg("cdata ->tstate=0x%08x\n", (unsigned int)((struct TrunkMemberSetting *)cdata) ->tstate);
+	ip1811drv_dbg("ip1811: -getTrunkMbr...\n");
+	return 0;
+}
+
+int switchdSetCpuNCareTrunkAndVlan(int en)
+{
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(1, P1REG_TRUNKCFG, 4, 1, en);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetCpuNCareTrunkAndVlan);
+int setCpuNCareTrunkAndVlan(void *cdata, int len)
+{
+	int en;
+
+	ip1811drv_dbg("ip1811: +setCpuNCareTrunkAndVlan...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	switchdSetCpuNCareTrunkAndVlan(en);
+
+	ip1811drv_dbg("ip1811: -setCpuNCareTrunkAndVlan...\n");
+	return 0;
+}
+
+int switchdGetCpuNCareTrunkAndVlan(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, 4, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetCpuNCareTrunkAndVlan);
+int getCpuNCareTrunkAndVlan(void *cdata, int len)
+{
+	int en;
+
+	ip1811drv_dbg("ip1811: +getCpuNCareTrunkAndVlan...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetCpuNCareTrunkAndVlan(&en) != 0)
+		return -EINVAL;
+	
+	((struct GeneralSetting *)cdata) ->gdata = en;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getCpuNCareTrunkAndVlan...\n");
+	return 0;
+}
+
+//------------------------------------------------
+//common_vlan
+int switchdSetVlanEgressFrame(int mode)
+{
+	if (mode > 0x7 )
+	{
+		ip1811drv_err("Error: mode=%X\n", mode);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("mode=0x%08x\n", mode);
+
+	_WriteRegBits(2, P2REG_VLAN_EGRESS_CFG1, 0, 3, mode);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEgressFrame);
+int setVlanEgressFrame(void *cdata, int len)
+{
+	u16 mode;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	mode = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetVlanEgressFrame(mode) != 0)
+		return -EINVAL;
+			
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanEgressFrame(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(2,P2REG_VLAN_EGRESS_CFG1, 0, 3);
+}
+EXPORT_SYMBOL(switchdGetVlanEgressFrame);
+int getVlanEgressFrame(void *cdata, int len)
+{
+	int ftype;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+	
+	switchdGetVlanEgressFrame(&ftype);
+
+	((struct GeneralSetting *)cdata) ->gdata = ftype;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanTagging(int mode)
+{
+	if ((mode != OP_VLAN_TAGGING_BY_PORT) && (mode != OP_VLAN_TAGGING_BY_VID))
+	{
+		ip1811drv_err("Error: mode=%X\n", mode);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("mode=0x%08x\n", mode);
+
+	_WriteRegBits(2, P2REG_VLANCFG, 3, 1, mode);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanTagging);
+int setVlanTagging(void *cdata, int len)
+{
+	u16 mode;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	mode = ((struct GeneralSetting *)cdata) ->gdata;
+
+    if(switchdSetVlanTagging(mode) != 0)
+		return -EINVAL;
+		
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanType(int mode)
+{
+	if ((mode != OP_VLAN_TYPE_TAG) && (mode != OP_VLAN_TYPE_GROUP))
+	{
+		ip1811drv_err("Error: mode=%X\n", mode);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("mode=0x%08x\n", mode);
+
+	/* set vlan type: port/tag base */
+	_WriteRegBits(2, P2REG_VLANCFG, 1, 1, mode);
+	/* set vlan protocol base */
+	_WriteRegBits(2, P2REG_VLANCFG, 0, 1, mode);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanType);
+int setVlanType(void *cdata, int len)
+{
+	u16 mode;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	mode = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetVlanType(mode) != 0)
+		return -EINVAL;	
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanGroup(unsigned long pm, int option)
+{
+	u32 u32dat;
+	int i;
+	
+	if (pm & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: portmap=%08lX\n", pm);
+		return -EINVAL;
+	}
+	if (option & ~0x1)
+	{
+		ip1811drv_err("Error: option=%X\n", option);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("pm=0x%08lx\n", pm);
+	ip1811drv_dbg("option=%x\n", option);
+
+	IP2Page(2);
+	for(i=0;i<MAX_PHY_NUM; i++)
+	{
+		if(!((pm>>i)&0x1))
+			continue;
+
+		u32dat = (u32)Read_Reg(P2REG_VLANGROUP+2*i);
+		if(option)
+			u32dat |= pm;
+		else
+			u32dat &= ~pm;
+
+		Write_Reg(P2REG_VLANGROUP+2*i, (u16)(u32dat & 0xFFFF));
+		//Write_Reg(P2REG_VLANGROUP+1+2*i, (u16)(u32dat >> 16));
+	}
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanGroup);
+int setVlanGroup(void *cdata, int len)
+{
+	unsigned long pm;
+	int option;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+	
+	pm = ((struct PortmapSetting *)cdata) ->portmap;
+	option = ((struct PortmapSetting *)cdata) ->pmdata;
+	
+	if(switchdSetVlanGroup(pm, option) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQPType(int type)
+{
+	if (type&(~0xFFFF))
+	{
+		ip1811drv_err("Error: type=%d\n", type);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("type=0x%08x\n", type);
+
+	IP2Page(7);
+	Write_Reg(P7REG_QINQEGTYPELEN, type);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQPType);
+int setVlanQinQPType(void *cdata, int len)
+{
+	int type;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	type = ((struct GeneralSetting *)cdata) ->gdata;
+	
+	if(switchdSetVlanQinQPType(type) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQPAddtag(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(7);
+	Write_Reg(P7REG_QINQ_ADDTAG, (u16)(member & 0xFFFF));
+	//Write_Reg(P7REG_QINQ_ADDTAG+1, (u16)(member >> 16));
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQPAddtag);
+int setVlanQinQPAddtag(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanQinQPAddtag(member) != 0)
+		return -EINVAL;
+		
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanQinQPAddtag(u32 *u32dat)
+{
+	IP2Page(7);
+	*u32dat = (u32)Read_Reg(P7REG_QINQ_ADDTAG);
+}
+EXPORT_SYMBOL(switchdGetVlanQinQPAddtag);
+int getVlanQinQPAddtag(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanQinQPAddtag(&u32dat);
+	
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQPRmvtag(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(7);
+	Write_Reg(P7REG_QINQ_RMVTAG, (u16)(member & 0xFFFF));
+	//Write_Reg(P7REG_QINQ_RMVTAG+1, (u16)(member >> 16));
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQPRmvtag);
+int setVlanQinQPRmvtag(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanQinQPRmvtag(member) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanQinQPRmvtag(u32 *u32dat)
+{
+	IP2Page(7);
+	*u32dat = (u32)Read_Reg(P7REG_QINQ_RMVTAG);
+}
+EXPORT_SYMBOL(switchdGetVlanQinQPRmvtag);
+int getVlanQinQPRmvtag(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanQinQPRmvtag(&u32dat);
+	
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQPRxdet(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(7);
+	Write_Reg(P7REG_QINQ_DET_RX, (u16)(member & 0xFFFF));
+	//Write_Reg(P7REG_QINQ_DET_RX+1, (u16)(member >> 16));
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQPRxdet);
+int setVlanQinQPRxdet(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanQinQPRxdet(member) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanQinQPRxdet(u32 *u32dat)
+{
+	IP2Page(7);
+	*u32dat = (u32)Read_Reg(P7REG_QINQ_DET_RX);
+}
+EXPORT_SYMBOL(switchdGetVlanQinQPRxdet);
+int getVlanQinQPRxdet(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanQinQPRxdet(&u32dat);
+	
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQPKeep(int member)
+{
+	int i;
+	
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	for(i=0; i<MAX_PHY_NUM; i++)
+	{
+		_WriteRegBits(7, P7REG_QINQ_P_DATA+i, 12, 1, ((member>>i)&0x1));
+	}
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQPKeep);
+int setVlanQinQPKeep(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanQinQPKeep(member) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanQinQPKeep(u32 *u32dat)
+{
+	int i;
+	u16 u16dat;
+		
+	IP2Page(7);
+	for(i=0; i<MAX_PHY_NUM; i++)
+	{
+		u16dat = Read_Reg(P7REG_QINQ_P_DATA+i);
+		*u32dat |= ((u16dat>>12)&0x1)<<i;
+	}
+}
+EXPORT_SYMBOL(switchdGetVlanQinQPKeep);
+int getVlanQinQPKeep(void *cdata, int len)
+{
+	u32 member=0;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanQinQPKeep(&member);
+	
+	((struct PortMemberSetting *)cdata) ->member = member;
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQPIndex(int port, int index)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+	{
+		ip1811drv_err("Error: port=%X\n", port);
+		return -EINVAL;
+	}
+
+	if (index < 0 || index > 15)
+	{
+		ip1811drv_err("Error: pmdata=%X\n", index);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("index=%d\n", index);
+
+	//index |= (0x0001 << 8);
+	_WriteRegBits(7, P7REG_QINQ_P_DATA+port, 0, 4, index);
+#ifdef COMBINED_PORT
+	if (port==9)
+		_WriteRegBits(7, P7REG_QINQ_P_DATA+port+1, 0, 4, index);
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQPIndex);
+int setVlanQinQPIndex(void *cdata, int len)
+{
+	int port, index;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	index= ((struct ByPortSetting *)cdata) ->pdata;
+	
+	if(switchdSetVlanQinQPIndex(port, index) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetVlanQinQPIndex(int port, int *index)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+	{
+		ip1811drv_err("Error: port=%X\n", port);
+		return -EINVAL;
+	}
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*index= _ReadRegBits(7,P7REG_QINQ_P_DATA+port, 0, 4);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetVlanQinQPIndex);
+int getVlanQinQPIndex(void *cdata, int len)
+{
+	int port;
+	int index;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	
+	if(switchdGetVlanQinQPIndex(port, &index) != 0)
+		return -EINVAL;	
+
+	((struct ByPortSetting *)cdata) ->pdata = index;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanQinQIndex(int index, int value)
+{
+	if (index<0 || index>15) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	if (value & (~0xFFFF)) {
+		ip1811drv_err("Error: data=%x\n", value);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("value=0x%x\n", value);
+
+	IP2Page(7);
+
+	Write_Reg(P7REG_QINQ_DATA+index, (u16)value);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQIndex);
+int setVlanQinQIndex(void *cdata, int len)
+{
+	int type, data, ret;
+	struct VlanSetting *vs = (struct VlanSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	type = vs ->vtype;
+	data = vs ->vdata;
+	ret = switchdSetVlanQinQIndex(type, data);
+
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdSetVlanQinQStagSelectMethod(int port, int method)
+{
+	if (port<0 || port>=MAX_PHY_NUM) {
+		ip1811drv_err("Error: port=%X\n", port);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("method=%d\n", method);
+
+	_WriteRegBits(7, P7REG_QINQ_P_DATA+port, 8, 4, method);
+#ifdef COMBINED_PORT
+	if (port==9)
+		_WriteRegBits(7, P7REG_QINQ_P_DATA+port+1, 8, 4, method);
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanQinQStagSelectMethod);
+int setVlanQinQStagSelectMethod(void *cdata, int len)
+{
+	int port, method, ret;
+	struct ByPortSetting *bps = (struct ByPortSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	port = bps ->port;
+	method = bps ->pdata;
+	ret = switchdSetVlanQinQStagSelectMethod(port, method) ;
+
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdSetVlanPortAddtag(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_ADDTAG, (u16)(member & 0xFFFF));
+	//Write_Reg(P2REG_VLAN_ADDTAG+1, (u16)(member >> 16));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortAddtag);
+int setVlanPortAddtag(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanPortAddtag(member) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortAddtag(u32 *u32dat)
+{
+	IP2Page(2);
+	*u32dat = (u32)Read_Reg(P2REG_VLAN_ADDTAG);
+}
+EXPORT_SYMBOL(switchdGetVlanPortAddtag);
+int getVlanPortAddtag(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+		
+	switchdGetVlanPortAddtag(&u32dat);
+	
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortRmvtag(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_RMVTAG, (u16)(member & 0xFFFF));
+	//Write_Reg(P2REG_VLAN_RMVTAG+1, (u16)(member >> 16));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortRmvtag);
+int setVlanPortRmvtag(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanPortRmvtag(member) != 0)
+		return -EINVAL;
+		
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortRmvtag(u32 *u32dat)
+{
+	IP2Page(2);
+	*u32dat = (u32)Read_Reg(P2REG_VLAN_RMVTAG);
+}
+EXPORT_SYMBOL(switchdGetVlanPortRmvtag);
+int getVlanPortRmvtag(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+		
+	switchdGetVlanPortRmvtag(&u32dat);
+
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortForce(int member)
+{
+	int i;
+	
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	for(i=0; i<MAX_PHY_NUM; i++)
+	{
+		_WriteRegBits(2, P2REG_VLANGROUP+2*i, 12, 1, (member>>i)&0x1);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortForce);
+int setVlanPortForce(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanPortForce(member) != 0)
+		return -EINVAL;
+		
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortForce(u32 *u32dat)
+{
+	u16 u16dat;
+	int i;
+	
+	IP2Page(2);
+	for(i=0; i<MAX_PHY_NUM; i++)
+	{
+		u16dat = Read_Reg(P2REG_VLANGROUP+2*i);
+		*u32dat |= ((u16dat>>12)&0x1)<<i;
+	}
+}
+EXPORT_SYMBOL(switchdGetVlanPortForce);
+int getVlanPortForce(void *cdata, int len)
+{
+	u32 member=0;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+    switchdGetVlanPortForce(&member);
+	
+	((struct PortMemberSetting *)cdata) ->member = member;
+	
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortUplink(int member)
+{
+	//u16 u16dat;
+	
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_UPLINK, (u16)((member & 0xFFFF) | 0x1000));
+	//u16dat = (u16)(member >> 16);
+	//u16dat |= (u16)0x1<<13;		//enable uplink
+	//_WriteRegBits(2, P2REG_VLAN_UPLINK+1, 0, 14, u16dat);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortUplink);
+int setVlanPortUplink(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanPortUplink(member) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortUplink(u32 *u32dat)
+{
+	IP2Page(2);
+	*u32dat = (u32)Read_Reg(P2REG_VLAN_UPLINK);
+	*u32dat &= 0x0FFF;
+}
+EXPORT_SYMBOL(switchdGetVlanPortUplink);
+int getVlanPortUplink(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanPortUplink(&u32dat);
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortExclusive(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_EXCLUSIVE, (u16)(member & 0xFFFF));
+	//Write_Reg(P2REG_VLAN_EXCLUSIVE+1, (u16)(member >> 16));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortExclusive);
+int setVlanPortExclusive(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+
+	if(switchdSetVlanPortExclusive(member) != 0)
+		return -EINVAL;
+		
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortExclusive(u32 *u32dat)
+{
+	IP2Page(2);
+	*u32dat = (u32)Read_Reg(P2REG_VLAN_EXCLUSIVE);
+}
+EXPORT_SYMBOL(switchdGetVlanPortExclusive);
+int getVlanPortExclusive(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanPortExclusive(&u32dat);
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortEgress(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_EGRESS_CFG, (u16)(member & 0xFFFF));
+	//_WriteRegBits(2, P2REG_VLAN_EGRESS_CFG+1, 0, 13, (u16)(member >> 16));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortEgress);
+int setVlanPortEgress(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanPortEgress(member) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortEgress(u32 *u32dat)
+{
+	IP2Page(2);
+	*u32dat = (u32)Read_Reg(P2REG_VLAN_EGRESS_CFG);
+	//u32dat &= 0x1FFFFFFF;
+}
+EXPORT_SYMBOL(switchdGetVlanPortEgress);
+int getVlanPortEgress(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+	
+	switchdGetVlanPortEgress(&u32dat);
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortIngressFrame(int port, int pdata)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+	{
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+
+	if (pdata < 0 || pdata > 0x3)
+	{
+		ip1811drv_err("Error: pdata=0x%X\n", pdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("pdata=0x%X\n", pdata);
+
+	_WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_0, port, 1, (pdata&0x1));
+	_WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_1, port, 1, ((pdata>>1)&0x1));
+#ifdef COMBINED_PORT
+	if (port==9){
+		_WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_0, port+1, 1, (pdata&0x1));
+		_WriteRegBits(2, P2REG_VLAN_INGRESS_FRAME_1, port+1, 1, ((pdata>>1)&0x1));
+	}
+#endif	
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortIngressFrame);
+int setVlanPortIngressFrame(void *cdata, int len)
+{
+	int port, pdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	pdata = ((struct ByPortSetting *)cdata) ->pdata;
+
+    if(switchdSetVlanPortIngressFrame(port, pdata) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortIngressCheck(int member)
+{
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%08X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("member=0x%08x\n", member);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_INGRESS_CHK, (u16)(member & 0xFFFF));
+	//Write_Reg(P2REG_VLAN_INGRESS_CHK+1, (u16)(member >> 16));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortIngressCheck);
+int setVlanPortIngressCheck(void *cdata, int len)
+{
+	int member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	member = ((struct PortMemberSetting *)cdata) ->member;
+	
+	if(switchdSetVlanPortIngressCheck(member) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+void switchdGetVlanPortIngressCheck(u32 *u32dat)
+{
+	IP2Page(2);
+	*u32dat = (u32)Read_Reg(P2REG_VLAN_INGRESS_CHK);
+}
+EXPORT_SYMBOL(switchdGetVlanPortIngressCheck);
+int getVlanPortIngressCheck(void *cdata, int len)
+{
+	u32 u32dat;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortMemberSetting) != len)
+		return -EINVAL;
+
+	switchdGetVlanPortIngressCheck(&u32dat);
+	
+	((struct PortMemberSetting *)cdata) ->member = (int)u32dat;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", (u16)((struct PortMemberSetting *)cdata) ->member);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanPortVid(int port, int pvid)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+	{
+		ip1811drv_err("Error: port=%X\n", port);
+		return -EINVAL;
+	}
+
+	if (pvid < 0 || pvid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: pmdata=%X\n", pvid);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("pvid=%d\n", pvid);
+
+	_WriteRegBits(2, P2REG_VLAN_PVIDCFG+port, 0, 12, pvid);
+#ifdef COMBINED_PORT
+	if (port==9)
+		_WriteRegBits(2, P2REG_VLAN_PVIDCFG+port+1, 0, 12, pvid);
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanPortVid);
+int setVlanPortVid(void *cdata, int len)
+{
+	int port, pvid;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	pvid= ((struct ByPortSetting *)cdata) ->pdata;
+	
+	if(switchdSetVlanPortVid(port, pvid) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanProtocolMode(int index, int mode)
+{
+	if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM)
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	if(	(mode!=OP_VLAN_PROTOCOL_INVALID)
+			&&	(mode!=OP_VLAN_PROTOCOL_ETHER)
+			&&	(mode!=OP_VLAN_PROTOCOL_LLC)
+			&&	(mode!=OP_VLAN_PROTOCOL_1042) )
+	{
+		ip1811drv_err("Error: mode=%X\n", mode);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("mode=%d\n", mode);
+
+	_WriteRegBits(2, P2REG_VLAN_PROCOTOL_CFG+1+index*2, 12, 2, mode);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanProtocolMode);
+int setVlanProtocolMode(void *cdata, int len)
+{
+	int index, mode;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len)
+		return -EINVAL;
+
+	index = (((struct VlanSetting *)cdata) ->vtype) - 1;
+	mode= ((struct VlanSetting *)cdata) ->vdata;
+	
+	if(switchdSetVlanProtocolMode(index, mode) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanProtocolVid(int index, int vid)
+{
+	if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM)
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	if(	(vid < 0) || (vid>=MAX_PVID_NUM) )
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("vid=%d\n", vid);
+
+	_WriteRegBits(2, P2REG_VLAN_PROCOTOL_CFG+1+index*2, 0, 12, vid);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanProtocolVid);
+int setVlanProtocolVid(void *cdata, int len)
+{
+	int index, vid;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len)
+		return -EINVAL;
+
+	index = (((struct VlanSetting *)cdata) ->vtype) - 1;
+	vid= ((struct VlanSetting *)cdata) ->vdata;
+	
+	if(switchdSetVlanProtocolVid(index, vid) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanProtocolType(int index, int type)
+{
+	if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM)
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	if (type & (~0xFFFF))
+	{
+		ip1811drv_err("Error: type=%X\n", type);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("type=%d\n", type);
+
+	IP2Page(2);
+
+	Write_Reg(P2REG_VLAN_PROCOTOL_CFG+index*2, (u16)type);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanProtocolType);
+int setVlanProtocolType(void *cdata, int len)
+{
+	int index, type;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len)
+		return -EINVAL;
+
+	index = (((struct VlanSetting *)cdata) ->vtype) - 1;
+	type= ((struct VlanSetting *)cdata) ->vdata;
+	
+	if(switchdSetVlanProtocolType(index, type) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanProtocolClear(int index)
+{
+	if (index < 0 || index >= MAX_PRO_VLAN_ENTRY_NUM)
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=0x%08x\n", index);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_PROCOTOL_CFG+index*2, 0 );
+	Write_Reg(P2REG_VLAN_PROCOTOL_CFG+index*2+1, 0 );
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanProtocolClear);
+int setVlanProtocolClear(void *cdata, int len)
+{
+	int index;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	index = (((struct GeneralSetting *)cdata) ->gdata) - 1;
+	
+	if(switchdSetVlanProtocolClear(index) != 0)
+		return -EINVAL;
+	
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanMACBased(int mode)
+{
+	if (mode!=OP_FUNC_DISABLE && mode!=OP_FUNC_ENABLE){
+		ip1811drv_err("Error: mode=%X\n", mode);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("mode=0x%08x\n", mode);
+
+	_WriteRegBits(2, P2REG_VLANCFG, 11, 1, mode);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanMACBased);
+int setVlanMACBased(void *cdata, int len)
+{
+	int mode;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+	
+	mode = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetVlanMACBased(mode) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanMACBasedtableconfig(unsigned int index, unsigned int data)
+{
+	if (index < 0 || index >= MAX_FID_NUM)
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	if (data & (~0x1FFF))
+	{
+		ip1811drv_err("Error: data=%X\n", data);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d data=0x%08x\n", index, data);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_MACBASED_ENTRY_0+index, (u16)data);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanMACBasedtableconfig);
+int setVlanMACBasedtableconfig(void *cdata, int len)
+{
+	unsigned int index, data;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct MACVlanSetting) != len)
+		return -EINVAL;
+
+	index = ((struct MACVlanSetting *)cdata) ->index;
+	data = ((struct MACVlanSetting *)cdata) ->mvdata;
+	
+	if(switchdSetVlanMACBasedtableconfig(index, data) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetVlanMACBasedtableconfig(unsigned int index, unsigned int *data)
+{
+	if (index < 0 || index >= MAX_FID_NUM)
+	{
+		ip1811drv_err("Error: index=%X\n", index);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	
+	IP2Page(2);
+	*data = (unsigned int)Read_Reg(P2REG_VLAN_MACBASED_ENTRY_0+index);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetVlanMACBasedtableconfig);
+int getVlanMACBasedtableconfig(void *cdata, int len)
+{
+	unsigned int index, data;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct MACVlanSetting) != len)
+		return -EINVAL;
+	
+	index = ((struct MACVlanSetting *)cdata) ->index;
+	
+	if(switchdGetVlanMACBasedtableconfig(index, &data) != 0)
+		return -EINVAL;
+
+	((struct MACVlanSetting *)cdata) ->mvdata = data;
+
+	ip1811drv_dbg("cdata ->mvdata=%d\n", ((struct MACVlanSetting *)cdata) ->mvdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanMACBasedunknown(unsigned int data)
+{
+	if (data & (~0x1FFF))
+	{
+		ip1811drv_err("Error: data=%X\n", data);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("data=0x%08x\n", data);
+
+	IP2Page(2);
+	Write_Reg(P2REG_VLAN_MACBASED_UNKNOWN, (u16)data);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanMACBasedunknown);
+int setVlanMACBasedunknown(void *cdata, int len)
+{
+	unsigned int data;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	data = ((struct GeneralSetting *)cdata) ->gdata;
+	
+	if(switchdSetVlanMACBasedunknown(data) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+//ip1811_vlan
+int switchdSetVlanEntryMember(int vid, int member)
+{
+	u16 u16dat;
+	
+	if (vid < 0 || vid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	if (member & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: member=%X\n", member);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+	ip1811drv_dbg("member=%d\n", member);
+
+	IP2Page(2);
+	/* read data from VLAN table */
+	u16dat = 0x8000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+
+	/* set entry memeber */
+	u16dat = Read_Reg(P2REG_VLANDAT0);
+	u16dat &= ~0xFFF;
+	u16dat |= (u16)member&0x0FFF;
+	Write_Reg(P2REG_VLANDAT0, u16dat);
+	
+	u16dat = Read_Reg(P2REG_VLANDAT0+1);
+	Write_Reg(P2REG_VLANDAT0+1, u16dat);
+	u16dat = Read_Reg(P2REG_VLANDAT0+2);
+	Write_Reg(P2REG_VLANDAT0+2, u16dat);
+
+	/* set valid bit to 1 */
+	u16dat = (u16)0x1;
+	Write_Reg(P2REG_VLANDAT0+3, u16dat);
+
+	/* Write data to VLAN table */
+	u16dat = 0xC000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEntryMember);
+int setVlanEntryMember(void *cdata, int len)
+{
+	int vid, member;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct PortmapSetting *)cdata) ->pmdata;
+	member= ((struct PortmapSetting *)cdata) ->portmap;
+	
+	if(switchdSetVlanEntryMember(vid, member) != 0)
+		return -EINVAL;	
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanEntryAddtag(int vid, int addtag)
+{
+	u16 u16dat;
+	
+	if (vid < 0 || vid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	if (addtag & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: addtag=%X\n", addtag);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+	ip1811drv_dbg("addtag=%d\n", addtag);
+
+	IP2Page(2);
+	/* read data from VLAN table */
+	u16dat = 0x8000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+
+	/* set entry addtag */
+	u16dat = Read_Reg(P2REG_VLANDAT0);
+	u16dat &= ~0xF000;
+	u16dat |= (u16)(addtag&0xF)<<12;
+	Write_Reg(P2REG_VLANDAT0, u16dat);
+
+	u16dat = Read_Reg(P2REG_VLANDAT0+1);
+	u16dat &= ~0x00FF;
+	u16dat |= (u16)(addtag>>4)&0x00FF;
+	Write_Reg(P2REG_VLANDAT0+1, u16dat);
+
+	u16dat = Read_Reg(P2REG_VLANDAT0+2);
+	Write_Reg(P2REG_VLANDAT0+2, u16dat);
+
+	/* set valid bit to 1 */
+	u16dat = (u16)0x1;
+	Write_Reg(P2REG_VLANDAT0+3, u16dat);
+
+	/* Write data to VLAN table */
+	u16dat = 0xC000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEntryAddtag);
+int setVlanEntryAddtag(void *cdata, int len)
+{
+	int vid, addtag;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct PortmapSetting *)cdata) ->pmdata;
+	addtag= ((struct PortmapSetting *)cdata) ->portmap;
+	
+	if(switchdSetVlanEntryAddtag(vid, addtag) != 0)
+		return -EINVAL;		
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanEntryRmvtag(int vid, int rmvtag)
+{
+	u16 u16dat;
+	
+	if (vid < 0 || vid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	if (rmvtag & ~(0x0FFF))
+	{
+		ip1811drv_err("Error: rmvtag=%X\n", rmvtag);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+	ip1811drv_dbg("rmvtag=%d\n", rmvtag);
+
+	IP2Page(2);
+	/* read data from VLAN table */
+	u16dat = 0x8000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	u16dat = Read_Reg(P2REG_VLANDAT0);
+	Write_Reg(P2REG_VLANDAT0, u16dat);
+
+	/* set entry rmvtag */
+	u16dat = Read_Reg(P2REG_VLANDAT0+1);
+	u16dat &= ~0xFF00;
+	u16dat |= (u16)(rmvtag&0xFF)<<8;
+	Write_Reg(P2REG_VLANDAT0+1, u16dat);
+
+	u16dat = Read_Reg(P2REG_VLANDAT0+2);
+	u16dat &= ~0xF;
+	u16dat |= (u16)(rmvtag>>8)&0xF;
+	Write_Reg(P2REG_VLANDAT0+2, u16dat);
+
+	/* set valid bit to 1 */
+	u16dat = (u16)0x1;
+	Write_Reg(P2REG_VLANDAT0+3, u16dat);
+
+	/* Write data to VLAN table */
+	u16dat = 0xC000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEntryRmvtag);
+int setVlanEntryRmvtag(void *cdata, int len)
+{
+	int vid, rmvtag;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct PortmapSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct PortmapSetting *)cdata) ->pmdata;
+	rmvtag= ((struct PortmapSetting *)cdata) ->portmap;
+	
+	if(switchdSetVlanEntryRmvtag(vid, rmvtag) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanEntryPriority(int vid, int priority)
+{
+	u16 u16dat;
+	
+	if (vid < 0 || vid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	if (priority & ~(0xF))
+	{
+		ip1811drv_err("Error: priority=%X\n", priority);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+	ip1811drv_dbg("priority=%d\n", priority);
+
+	IP2Page(2);
+	/* read data from VLAN table */
+	u16dat = 0x8000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	u16dat = Read_Reg(P2REG_VLANDAT0);
+	Write_Reg(P2REG_VLANDAT0, u16dat);
+	u16dat = Read_Reg(P2REG_VLANDAT0+1);
+	Write_Reg(P2REG_VLANDAT0+1, u16dat);
+
+	/* set entry priority */
+	u16dat = Read_Reg(P2REG_VLANDAT0+2);
+	u16dat &= ~0x00F0;
+	u16dat |= (u16)(priority&0xF)<<4;
+	Write_Reg(P2REG_VLANDAT0+2, u16dat);
+
+	/* set valid bit to 1 */
+	u16dat = (u16)0x1;
+	Write_Reg(P2REG_VLANDAT0+3, u16dat);
+
+	/* Write data to VLAN table */
+	u16dat = 0xC000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEntryPriority);
+int setVlanEntryPriority(void *cdata, int len)
+{
+	int vid, priority;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct VlanSetting *)cdata) ->vtype;
+	priority= ((struct VlanSetting *)cdata) ->vdata;
+	
+	if(switchdSetVlanEntryPriority(vid, priority) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanEntryFid(int vid, int fid)
+{
+	u16 u16dat;
+	
+	if (vid < 0 || vid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	if (fid & ~(0xF))
+	{
+		ip1811drv_err("Error: fid=%X\n", fid);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+	ip1811drv_dbg("fid=%d\n", fid);
+
+	IP2Page(2);
+	/* read data from VLAN table */
+	u16dat = 0x8000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	u16dat = Read_Reg(P2REG_VLANDAT0);
+	Write_Reg(P2REG_VLANDAT0, u16dat);
+	u16dat = Read_Reg(P2REG_VLANDAT0+1);
+	Write_Reg(P2REG_VLANDAT0+1, u16dat);
+
+	/* set entry fid */
+	u16dat = Read_Reg(P2REG_VLANDAT0+2);
+	u16dat &= ~0xFF00;
+	u16dat |= (u16)(fid&0xF)<<8;
+	u16dat |= (u16)(fid&0xF)<<12;
+	Write_Reg(P2REG_VLANDAT0+2, u16dat);
+
+	/* set valid bit to 1 */
+	u16dat = (u16)0x1;
+	Write_Reg(P2REG_VLANDAT0+3, u16dat);
+
+	/* Write data to VLAN table */
+	u16dat = 0xC000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEntryFid);
+int setVlanEntryFid(void *cdata, int len)
+{
+	int vid, fid;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct VlanSetting *)cdata) ->vtype;
+	fid= ((struct VlanSetting *)cdata) ->vdata;
+	
+	if(switchdSetVlanEntryFid(vid, fid) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetVlanEntryFid(int vid, int *ptrFid)
+{
+	u16 u16dat;
+
+	if (vid < 0 || vid >= MAX_PVID_NUM){
+		ip1811drv_err("Error: vtype=%X\n", vid);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+
+	IP2Page(2);
+	/* read data from VLAN table */
+	u16dat = 0x8000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+
+	/* get entry fid */
+	u16dat = Read_Reg(P2REG_VLANDAT0+2);
+	*ptrFid = (int)(u16dat>>8)&0xF;
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetVlanEntryFid);
+int getVlanEntryFid(void *cdata, int len)
+{
+	int vid, fid=0;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct VlanSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct VlanSetting *)cdata) ->vtype;
+
+	if(switchdGetVlanEntryFid(vid, &fid) != 0)
+		return -EINVAL;
+
+	((struct VlanSetting *)cdata) ->vdata = fid;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct VlanSetting *)cdata) ->vdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetVlanEntryClear(int vid)
+{
+	u16 u16dat;
+	int i;
+
+	if (vid < 0 || vid >= MAX_PVID_NUM)
+	{
+		ip1811drv_err("Error: vid=%X\n", vid);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("vid=%d\n", vid);
+
+	IP2Page(2);
+
+	/* clear entry data */
+	for(i=0; i<4; i++)
+		Write_Reg(P2REG_VLANDAT0+i, 0 );
+
+	/* Write data from VLAN table */
+	u16dat = 0xC000 | vid;
+	Write_Reg(P2REG_VLANCMD, u16dat);
+	/* wait for command ack */
+	while(Read_Reg(P2REG_VLANCMD)&0x8000);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetVlanEntryClear);
+int setVlanEntryClear(void *cdata, int len)
+{
+	int vid;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	vid = ((struct GeneralSetting *)cdata) ->gdata;
+	
+	if(switchdSetVlanEntryClear(vid) != 0)
+		return -EINVAL;	
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+//------------------------------------------------
+//ip1811_lut
+int switchdSetLutUnknownSARule(int rule)
+{
+	if ( !(	rule==OP_LUT_UNKNOWN_SA_DROP ||
+			rule==OP_LUT_UNKNOWN_SA_FWD_2_CPU ||
+			rule==OP_LUT_UNKNOWN_SA_FWD) )
+		return -EINVAL;
+
+	ip1811drv_dbg("rule=%d\n", rule);
+
+	_WriteRegBits(1, P1REG_SRCLEARNCFG, 3, 2, rule);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutUnknownSARule);
+int setLutUnknownSARule(void *cdata, int len)
+{
+	int rule;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	rule = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetLutUnknownSARule(rule) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetLutEntry(struct IP1811LUTSetting *luts)
+{
+	int i;
+	unsigned char f_notMatch = 0;
+	u16 u16dat, index;
+	u8 block;
+	int temp_offset = -1;
+	struct IP1811LUTSetting tmp_luts;
+	
+	if(		luts ->action!=OP_ENTRY_CREATE &&
+			luts ->action!=OP_ENTRY_CONFIG &&
+			luts ->action!=OP_ENTRY_DELETE &&
+			luts ->action!=OP_ENTRY_CREATE_REG)
+	{
+		ip1811drv_err("action error:%d\n", luts ->action);
+		return -EINVAL;
+	}
+	if(		luts ->action == OP_ENTRY_CREATE ||
+			luts ->action == OP_ENTRY_CONFIG)
+	{
+		if(luts ->entry.fid > 15)
+		{
+			ip1811drv_err("fid error:%d\n", luts ->entry.fid);
+			return -EINVAL;
+		}
+		if(luts ->entry.srcport > 31)
+		{
+			ip1811drv_err("srcport error:%d\n", luts ->entry.srcport);
+			return -EINVAL;
+		}
+		if(luts ->entry.aging > 15)
+		{
+			ip1811drv_err("aging error:%d\n", luts ->entry.aging);
+			return -EINVAL;
+		}
+		if(luts ->entry.priority > 15)
+		{
+			ip1811drv_err("priority error:%d\n", luts ->entry.priority);
+			return -EINVAL;
+		}
+		if(luts ->entry.cfg > OP_LUT_CFG_MVT)
+		{
+			ip1811drv_err("cfg error:%d\n", luts ->entry.cfg);
+			return -EINVAL;
+		}
+	}
+
+	/* initialize retval value */ 
+	luts ->retval = 0;
+	/* calculate hash value */
+	index = 0;//LUT_hash(luts ->entry.mac, luts ->entry.fid);
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("MAC=\n");
+	for(i=0; i<6; i++)
+		ip1811drv_dbg("[%02X]\n", luts ->entry.mac[i]);
+	ip1811drv_dbg("fid=%d\n", luts ->entry.fid);
+	ip1811drv_dbg("srcport=%d\n", luts ->entry.srcport);
+	ip1811drv_dbg("aging=%d\n", luts ->entry.aging);
+	ip1811drv_dbg("priority=%d\n", luts ->entry.priority);
+	ip1811drv_dbg("drop=%d\n", luts ->entry.flag.drop);
+	ip1811drv_dbg("snif=%d\n", luts ->entry.flag.snif);
+	ip1811drv_dbg("sflow=%d\n", luts ->entry.flag.sflow);
+	ip1811drv_dbg("cfg=%d\n", luts ->entry.cfg);
+
+	IP2Page(1);
+	if(luts ->action==OP_ENTRY_CREATE_REG)
+	{
+		ip1811drv_dbg("OP_ENTRY_CREATE_REG\n");
+		for(i=0; i<5; i++)
+			Write_Reg(P1REG_LUTDATA_0+i, luts ->data[i] );
+		Write_Reg(P1REG_LUTDATA_0+5, luts ->data[5]|0x0800 );	//hw_calc
+
+		u16dat = 0;
+		u16dat |= (u16)0x3<<14;		//set write command & command trigger
+		Write_Reg(P1REG_LUTCFG, u16dat );
+		/* need to check does trigger bit has been pull up */
+		while(!(Read_Reg(P1REG_LUTCFG)&0x8000));
+		return 0;
+	}
+
+	/* search the index of target entry */
+	/* cause use hw_calc bit can't get entry index */	
+//	if((luts ->action==OP_ENTRY_CONFIG) || (luts ->action==OP_ENTRY_DELETE))
+	{
+		memset(&tmp_luts, 0, sizeof(struct IP1811LUTSetting));
+		/* search all entries */
+		tmp_luts.action = OP_LUT_STATE_ALL;
+		tmp_luts.tarports = ALL_PHY_PORTS_LIST;
+		while(1)
+		{
+			/* try to get a valid MAC entry */
+			tmp_luts.retval = 0;
+			getLutValidEntry(&tmp_luts, sizeof(struct IP1811LUTSetting));
+			if(tmp_luts.retval != OP_ENTRY_EXISTS)
+				break;
+	
+			/* get a valid static entry */
+
+			/* check MAC address & FID */
+			f_notMatch = 0;
+			for(i=0; i<6; i++)
+			{
+				if(luts ->entry.mac[i] != tmp_luts.entry.mac[i])
+				{
+					f_notMatch = 1;
+					break;
+				}
+			}
+			if(luts ->entry.fid != tmp_luts.entry.fid)
+				f_notMatch = 1;
+	
+			if(!f_notMatch){
+				/* if match, record the index */
+				temp_offset = tmp_luts.index;
+				break;
+			}
+	
+			/* search next valid entry */		
+			tmp_luts.index++;
+		}
+	}
+
+	if(luts ->action==OP_ENTRY_CREATE)
+	{
+		ip1811drv_dbg("OP_ENTRY_CREATE\n");
+		if(tmp_luts.entry.aging == 0xf)
+		{
+			ip1811drv_dbg("target entry has existed!!\n");
+			luts ->retval = OP_ENTRY_EXISTS;
+			return 0;
+		}
+		for(i=0; i<3; i++)
+		{
+			u16dat = (u16)(luts ->entry.mac[4 - i*2])<<8 | (u16)(luts ->entry.mac[5 - i*2]);
+			Write_Reg(P1REG_LUTDATA_0+i, u16dat );
+		}
+		u16dat = 0;
+		u16dat = luts ->entry.fid;
+		u16dat |= (u16)luts ->entry.srcport<<4;
+		u16dat |= (u16)0x0f<<9;	//set aging to static
+		u16dat |= (u16)((luts ->entry.priority & 0x7)<<13);
+		Write_Reg(P1REG_LUTDATA_3, u16dat );
+		
+		u16dat = (u16)((luts ->entry.priority >> 3)&0x1);
+		u16dat |= (u16)luts ->entry.flag.sflow<<1;
+		u16dat |= (u16)luts ->entry.flag.snif<<2;
+		u16dat |= (u16)luts ->entry.flag.drop<<3;
+		if (luts ->entry.cfg < OP_LUT_CFG_TRAN)
+			u16dat |= (u16)((luts ->entry.cfg & 0x3)<<4);
+		else
+		{
+			u16dat |= (u16)0x0020;	// cfg[1] = 1
+			if (luts ->entry.cfg == OP_LUT_CFG_MVT)
+				u16dat |= (u16)0x0008;	// drop = 1
+		}
+		Write_Reg(P1REG_LUTDATA_4, u16dat );
+
+		u16dat = 0x01<<11;//hw_calc
+		Write_Reg(P1REG_LUTDATA_5, u16dat );
+
+		u16dat = 0;					//set index
+		u16dat |= (u16)0x3<<14;		//set write command & command trigger
+		Write_Reg(P1REG_LUTCFG, u16dat );
+
+		/* need to check does trigger bit has been pull up */
+		while(!(Read_Reg(P1REG_LUTCFG)&0x8000));
+	}
+	else if(luts ->action==OP_ENTRY_CONFIG)
+	{
+		ip1811drv_dbg("OP_ENTRY_CONFIG\n");
+		/* if MAC or FID isn't match, we should abort this configuration */
+		if(f_notMatch)
+		{
+			ip1811drv_dbg("MAC or FID not match!!\n");
+			luts ->retval = OP_ENTRY_NOT_MATCH;
+			return 0;
+		}
+
+		for (i=0; i < 3; i++)
+			Write_Reg(P1REG_LUTDATA_0+i, tmp_luts.data[i]);
+
+		u16dat = luts ->entry.fid;
+		u16dat |= (u16)luts ->entry.srcport<<4;
+		u16dat |= (u16)0x0f<<9;	//set aging to static
+		u16dat |= (u16)((luts ->entry.priority & 0x7)<<13);
+		Write_Reg(P1REG_LUTDATA_3, u16dat );
+		
+		u16dat = (u16)((luts ->entry.priority >> 3)&0x1);
+		u16dat |= (u16)luts ->entry.flag.sflow<<1;
+		u16dat |= (u16)luts ->entry.flag.snif<<2;
+		if (luts ->entry.cfg < OP_LUT_CFG_TRAN)
+		{
+			u16dat |= (u16)luts ->entry.flag.drop<<3;
+			u16dat |= (u16)((luts ->entry.cfg & 0x3)<<4);
+		}
+		else
+		{
+			u16dat |= (u16)0x0020;	// cfg[1] = 1
+			if (luts ->entry.cfg == OP_LUT_CFG_MVT)
+				u16dat |= (u16)0x0008;	// drop = 1
+		}
+		Write_Reg(P1REG_LUTDATA_4, u16dat );
+
+		u16dat = 0x01<<11;//hw_calc
+		Write_Reg(P1REG_LUTDATA_5, u16dat );
+
+		u16dat = 0;					//set index
+		u16dat |= (u16)0x3<<14;		//set write command & command trigger
+		Write_Reg(P1REG_LUTCFG, u16dat );
+		
+		/* need to check does trigger bit has been pull up */
+		while(!(Read_Reg(P1REG_LUTCFG)&0x8000));
+	}
+	else if(luts ->action==OP_ENTRY_DELETE)
+	{
+		ip1811drv_dbg("OP_ENTRY_DELETE\n");
+		if(f_notMatch)
+		{
+			ip1811drv_dbg("MAC or FID not match!!\n");
+			luts ->retval = OP_ENTRY_NOT_MATCH;
+			return 0;
+		}
+		if(tmp_luts.entry.aging != 0xf)
+		{
+			/* only static entry can be deleted */
+			ip1811drv_dbg("not static entry!!\n");
+			luts ->retval = OP_ENTRY_NOT_FOUND;
+			return 0;
+		}
+		
+		for (i=0; i < 3; i++)
+			Write_Reg(P1REG_LUTDATA_0+i, tmp_luts.data[i]);
+
+		u16dat = 0x0;	//set aging to invalid
+		Write_Reg(P1REG_LUTDATA_3, u16dat );
+		
+		u16dat = 0x01<<11;//hw_calc
+		Write_Reg(P1REG_LUTDATA_5, u16dat );
+
+		u16dat = 0;					//set index
+		u16dat |= (u16)0x3<<14;		//set write command & command trigger
+		Write_Reg(P1REG_LUTCFG, u16dat );
+
+		/* need to check does trigger bit has been pull up */
+		while(!(Read_Reg(P1REG_LUTCFG)&0x8000));
+	}
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetLutEntry);
+int setLutEntry(void *cdata, const int len)
+{
+	struct IP1811LUTSetting *luts;
+
+	FUNC_MSG_IN;
+	/* check cdata length */
+	if (sizeof(struct IP1811LUTSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	luts = (struct IP1811LUTSetting *)cdata;
+
+	if(switchdSetLutEntry(luts) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+u8 getLutCfgFromReg(u16 reg)
+{
+	if (reg & 0x0020)	// cfg[1] = 1
+	{
+		if (reg & 0x8)	// drop = 1
+			return (u8)OP_LUT_CFG_MVT;
+		else
+			return (u8)OP_LUT_CFG_TRAN;
+	}
+	else	// cfg[1] = 0
+		return (u8)((reg >> 4) & 0x1);
+}
+
+int switchdGetLutEntry(struct IP1811LUTSetting *luts)
+{
+	int i;
+	bool f_notMatch = 0;
+	u16 u16dat, lutdat_3, lutdat_4;
+	int val_aging;
+	u8 op_cfg;
+
+	/* check index range */
+	if(luts ->index >= MAX_LUT_ENTRY_NUM){
+		ip1811drv_err("Error: index=%d\n", luts ->index);
+		return -EINVAL;
+	}
+
+	/* set to register page 1 */
+	IP2Page(1);
+
+	/* check command action */
+	if(luts ->action == OP_ENTRY_GET_BY_INFO){
+		if(luts ->entry.fid >= MAX_FID_NUM){
+			ip1811drv_err("Error: fid=%d\n", luts ->entry.fid);
+			return -EINVAL;
+		}
+
+		/* copy mac to register from cdata */
+		for(i=0; i<3; i++){
+			u16dat = (u16)(luts ->entry.mac[4 - i*2])<<8 | (u16)(luts ->entry.mac[5 - i*2]);
+			Write_Reg(P1REG_LUTDATA_0 + i, u16dat );
+		}
+
+		/* set fid to register from cdata */
+		Write_Reg(P1REG_LUTDATA_3, luts ->entry.fid );
+
+		/* setup table address access method by HW */
+		Write_Reg(P1REG_LUTDATA_5, 0x0800 );
+	}
+	else if(luts ->action == OP_ENTRY_GET_BY_INDEX){
+		/* setup table address access method by CPU */
+		Write_Reg(P1REG_LUTDATA_5, 0 );
+	}
+	else{
+		ip1811drv_err("Error: action=%d\n", luts ->action);
+		return -EINVAL;
+	}
+
+	/* initialize return value */
+	luts ->retval = 0;
+
+	u16dat = luts ->index;		//set index
+	u16dat |= (u16)0x2<<14;		//set read command & command trigger
+	Write_Reg(P1REG_LUTCFG, u16dat );
+
+	/* check does trigger bit has been pull up */
+	while(!(Read_Reg(P1REG_LUTCFG)&0x8000));
+
+	/* catch aging time to check entry state */
+	lutdat_3 = Read_Reg(P1REG_LUTDATA_3);
+	lutdat_4 = Read_Reg(P1REG_LUTDATA_4);
+	val_aging = (lutdat_3 >> 9) & 0x0F;
+	if(val_aging  == 0x0){
+		luts ->retval = OP_ENTRY_NOT_FOUND;
+		return 0;
+	}
+	
+	/* get lut cfg */
+	op_cfg = getLutCfgFromReg(lutdat_4);
+
+	if(luts ->action == OP_ENTRY_GET_BY_INFO){
+		/* if action is get by entry info, check if register value is same with input data */
+		/* catch MAC address */
+		for(i=0; i<3; i++){
+			u16dat = Read_Reg(P1REG_LUTDATA_0 + i);
+			if( luts ->entry.mac[5 - i*2] != (u8)(u16dat&0xFF) )
+				f_notMatch = 1;
+			if( luts ->entry.mac[4 - i*2] != (u8)((u16dat>>8)&0xFF) )
+				f_notMatch = 1;
+		}
+
+		/* check whether fid is matched to input cdata */
+		if( luts ->entry.fid != (lutdat_3 & 0x000f))
+			f_notMatch = 1;
+			
+		/* check whether cfg is matched to input cdata */
+		if( luts ->entry.cfg != op_cfg)
+			f_notMatch = 1;
+
+		if(val_aging == 0xf){//static entry
+			if(f_notMatch){
+				ip1811drv_err("Error: MAC or FID is not match\n");
+				luts ->retval = OP_ENTRY_NOT_MATCH;
+				return 0;
+			}
+			else
+				luts ->retval = OP_ENTRY_EXISTS;
+		}
+		else{//dynamic entry
+			if(f_notMatch){
+				ip1811drv_err("Error: MAC or FID is not match\n");
+				luts ->retval = OP_ENTRY_NOT_MATCH;
+				return 0;
+			}
+			else
+				luts ->retval = OP_ENTRY_EXISTS_DYNAMIC;
+		}
+	}
+	else{//if(luts ->action == OP_ENTRY_GET_BY_INDEX)
+		if( ((lutdat_3 >> 9) & 0x000F ) == 0x000F )
+			luts ->retval = OP_ENTRY_EXISTS;
+		else
+			luts ->retval = OP_ENTRY_EXISTS_DYNAMIC;
+
+		/* if action is get by entry index, copy the register value into output data */
+		/* catch MAC address */
+		for(i=0; i<3; i++){
+			u16dat = Read_Reg(P1REG_LUTDATA_0 + i);
+			luts ->entry.mac[5 - i*2] = (u8)(u16dat&0xFF);
+			luts ->entry.mac[4 - i*2] = (u8)((u16dat>>8)&0xFF);
+		}
+
+		lutdat_3 = Read_Reg(P1REG_LUTDATA_3);
+		luts ->entry.fid	= lutdat_3 & 0x000F;
+	}
+
+	luts ->entry.priority	= ((lutdat_4 & 0x0001) << 3) | ((lutdat_3>>13) & 0x0007);
+	if (op_cfg < OP_LUT_CFG_TRAN)
+		luts ->entry.flag.drop	= (lutdat_4>>3) & 0x0001;
+	else
+		luts ->entry.flag.drop	= 0;
+	luts ->entry.flag.sflow	= (lutdat_4>>1) & 0x0001;
+	luts ->entry.flag.snif	= (lutdat_4>>2) & 0x0001;
+	luts ->entry.srcport	= (lutdat_3>>4) & 0x001F;
+
+	luts ->entry.aging	= val_aging;
+	luts ->entry.cfg	= op_cfg;
+
+	ip1811drv_dbg("cdata ->MAC=");
+	for(i=0; i<6; i++)
+		ip1811drv_dbg("[%02X]", luts ->entry.mac[i]);
+	ip1811drv_dbg("\ncdata ->fid=%d\n", luts ->entry.fid);
+	ip1811drv_dbg("cdata ->srcport=%d\n", luts ->entry.srcport);
+	ip1811drv_dbg("cdata ->aging=%d\n", luts ->entry.aging);
+	ip1811drv_dbg("cdata ->priority=%d\n", luts ->entry.priority);
+	ip1811drv_dbg("cdata ->drop=%d\n", luts ->entry.flag.drop);
+	ip1811drv_dbg("cdata ->snif=%d\n", luts ->entry.flag.snif);
+	ip1811drv_dbg("cdata ->sflow=%d\n", luts ->entry.flag.sflow);
+	ip1811drv_dbg("cdata ->cfg=%d\n", luts ->entry.cfg);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLutEntry);
+int getLutEntry(void *cdata, const int len)
+{
+	struct IP1811LUTSetting *luts;
+
+	FUNC_MSG_IN;
+	/* check cdata length */
+	if (sizeof(struct IP1811LUTSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	luts = (struct IP1811LUTSetting *)cdata;
+
+	if(switchdGetLutEntry(luts) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetLutValidEntry(struct IP1811LUTSetting *luts)
+{
+	int i, retrytimes=25;
+	u16 u16dat, lutdat[6];
+	unsigned short index;
+	unsigned char block;
+	int temp_offset;
+	
+	u16 hashvid;
+	
+	/* check index range */
+	if(luts ->index >= MAX_LUT_ENTRY_NUM)
+	{
+		ip1811drv_err("Error: index=%d\n", luts ->index);
+		return -EINVAL;
+	}
+	index = luts ->index;
+
+	ip1811drv_dbg("action=%d\n", luts ->action);
+	/* set to register page 1 */
+	IP2Page(1);
+
+	/* setup table address access method by CPU */
+	Write_Reg(P1REG_LUTDATA_5, 0 );
+
+	/* initialize return value */
+	luts ->retval = 0;
+	
+	u16dat = index;				//set index
+	u16dat |= (u16)0x2000;		//sequential search for valid entry
+	u16dat |= (u16)0x2<<14;		//set read command & command trigger
+	Write_Reg(P1REG_LUTCFG, u16dat );
+
+	while (1)
+	{
+		memset(lutdat, 0, sizeof(lutdat));
+		
+		/* check does trigger bit has been pull up */
+		for (i=0; i < retrytimes; i++)
+		{
+			udelay(100);
+			u16dat = Read_Reg(P1REG_LUTCFG);
+			if (u16dat & 0x8000)
+				break;
+		}
+		if (i == retrytimes)
+			goto out_switchdGetLutValidEntry;
+		
+		/* read out all registers of lut data */
+		for (i=0; i < 6; i++)
+			lutdat[i] = Read_Reg(P1REG_LUTDATA_0+i);
+			
+		/* check if there is any entry data */
+		if (lutdat[0]==0 && lutdat[1]==0 && lutdat[2]==0){
+			/* no data in lut table */
+			goto out_switchdGetLutValidEntry;
+		}
+		
+		/* check if there is no more new data */
+		if (!(u16dat & 0x2000)){
+			/* lut table has been scanned to the end */
+			goto out_switchdGetLutValidEntry;
+		}
+		
+		/* catch aging time to check entry state */
+		if((lutdat[3] &0x1e00) == 0x0){
+			/* invalid entry */
+			continue;
+		}
+		if(		((lutdat[3] >> 9) & 0xf) == 0xf &&
+				!(luts ->action & OP_LUT_STATE_STATIC)
+				)
+		{
+			/* action don't need static entry */
+			continue;
+		}
+		if(		((lutdat[3] >> 9) & 0xf) != 0xf &&
+				!(luts ->action & OP_LUT_STATE_DYNAMIC) )
+		{
+			/* action don't need dynamic entry */
+			continue;
+		}
+	
+		/* check whether source port bigger than CPU port num */
+		if((((lutdat[3]>>4) & 0x001f) + 1) > MAX_PHY_NUM)
+			continue;
+	
+		/* check whether this entry is in target portlist */
+		if(!((1UL << ((lutdat[3]>>4) & 0x001f))&luts ->tarports))
+			continue;
+			
+		break;
+	}
+		
+	/* if find a valid entry, copy the register value into output data */
+	/* catch MAC address */
+	for(i=0; i<6; i++)
+	{
+		luts ->data[i] = lutdat[i];
+		if (i < 3)
+		{
+			luts ->entry.mac[5 - i*2] = (u8)(lutdat[i]&0xFF);
+			luts ->entry.mac[4 - i*2] = (u8)((lutdat[i]>>8)&0xFF);
+		}
+	}
+	
+	luts ->entry.fid		= lutdat[3] & 0x000f;
+	luts ->entry.srcport	= (lutdat[3]>>4) & 0x001f;
+	luts ->entry.aging		= (lutdat[3]>>9) & 0x000f;
+	luts ->entry.priority	= (lutdat[3]>>13) & 0x0007;
+	luts ->entry.priority	|= ((lutdat[4] & 0x0001) << 3);
+	
+	luts ->entry.flag.sflow	= (lutdat[4]>>1) & 0x0001;
+	luts ->entry.flag.snif	= (lutdat[4]>>2) & 0x0001;
+    luts -> entry.cfg		= getLutCfgFromReg(lutdat[4]);
+    if (luts -> entry.cfg < OP_LUT_CFG_TRAN)
+		luts ->entry.flag.drop	= (lutdat[4]>>3) & 0x0001;
+	else
+		luts ->entry.flag.drop	= 0;
+
+	luts ->retval = OP_ENTRY_EXISTS;
+
+	ip1811drv_dbg("=====================================\n");
+	ip1811drv_dbg("index=%d\n", luts ->index);
+	ip1811drv_dbg("retval=%lX\n", luts ->retval);
+	ip1811drv_dbg("MAC=");
+	for(i=0; i<6; i++)
+		ip1811drv_dbg("[%02X]", luts ->entry.mac[i]);
+	ip1811drv_dbg("\nfid=%d\n", luts ->entry.fid);
+	ip1811drv_dbg("srcport=%d\n", luts ->entry.srcport);
+	ip1811drv_dbg("aging=%d\n", luts ->entry.aging);
+	ip1811drv_dbg("priority=%d\n", luts ->entry.priority);
+	ip1811drv_dbg("drop=%d\n", luts ->entry.flag.drop);
+	ip1811drv_dbg("snif=%d\n", luts ->entry.flag.snif);
+	ip1811drv_dbg("sflow=%d\n", luts ->entry.flag.sflow);
+	ip1811drv_dbg("cfg=%d\n", luts ->entry.cfg);
+
+out_switchdGetLutValidEntry:
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetLutValidEntry);
+int getLutValidEntry(void *cdata, const int len)
+{
+	struct IP1811LUTSetting *luts;
+
+	FUNC_MSG_IN;
+	/* check cdata length */
+	if (sizeof(struct IP1811LUTSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	luts = (struct IP1811LUTSetting *)cdata;
+
+	if(switchdGetLutValidEntry(luts) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+//------------------------------------------------
+//ip1811_igmp
+int switchdSetIGMPSnooping(int enable)
+{
+	switch(enable) {
+	case OP_FUNC_ENABLE:
+		ip1811drv_dbg("Enable IGMP\n");
+		break;
+	case OP_FUNC_DISABLE:
+		ip1811drv_dbg("Disable IGMP\n");
+		break;
+	default:
+		ip1811drv_dbg("Option can't find\n");
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("Set IGMPSNOP: %x\n", enable);
+	_WriteRegBits(1, P1REG_IGMPSNOP, 0, 1, enable);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPSnooping);
+
+int setIGMPSnooping(void *cdata, int len)
+{
+	int ret, func_en;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPSnoopin.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	func_en = igmp ->gdata;
+	ret = switchdSetIGMPSnooping(func_en);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPSnooping(int *gdata_p)
+{
+	*gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 0, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE;
+	ip1811drv_dbg("IGMP %s",(*gdata_p==OP_FUNC_ENABLE)?"ENABLE":"DISABLE");
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPSnooping);
+
+int getIGMPSnooping(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPSnoopin.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	ret = switchdGetIGMPSnooping(&(igmp ->gdata))
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdSetIGMPMctByCPU(int enable)
+{
+	switch(enable) {
+	case OP_FUNC_ENABLE:
+		ip1811drv_dbg("Enable MCT By CPU\n");
+		break;
+	case OP_FUNC_DISABLE:
+		ip1811drv_dbg("Disable MCT By CPU\n");
+		break;
+	default:
+		ip1811drv_dbg("Option can't find\n");
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("Set MCT By CPU: %x\n", enable);
+	_WriteRegBits(1, P1REG_IGMPSNOP, 1, 1, enable);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPMctByCPU);
+
+int setIGMPMctByCPU(void *cdata, int len)
+{
+	int ret, func_en;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPMctByCPU.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	func_en = igmp ->gdata;
+	ret = switchdSetIGMPMctByCPU(func_en);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPMctByCPU(int *gdata_p)
+{
+	*gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 1, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE;
+	ip1811drv_dbg("IGMPMctByCPU %s",(*gdata_p==OP_FUNC_ENABLE)?"ENABLE":"DISABLE");
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPMctByCPU);
+
+int getIGMPMctByCPU(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPMctByCPU.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	ret = switchdGetIGMPMctByCPU(&(igmp ->gdata));
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdSetIGMPRltByCPU(int enable)
+{
+	switch(enable) {
+	case OP_FUNC_ENABLE:
+		ip1811drv_dbg("Enable router list by CPU\n");
+		break;
+	case OP_FUNC_DISABLE:
+		ip1811drv_dbg("Disable router list by CPU\n");
+		break;
+	default:
+		ip1811drv_dbg("Option can't find\n");
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("Set router list by CPU: %x\n", enable);
+	_WriteRegBits(1, P1REG_IGMPSNOP, 5, 1, enable);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPRltByCPU);
+
+int setIGMPRltByCPU(void *cdata, int len)
+{
+	int ret, func_en;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPRltByCPU.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	func_en = igmp ->gdata;
+	ret = switchdSetIGMPRltByCPU(func_en);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+
+int switchdGetIGMPRltByCPU(int *gdata_p)
+{
+	*gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 5, 1)?OP_FUNC_ENABLE:OP_FUNC_DISABLE;
+	ip1811drv_dbg("IGMPRltByCPU %s",(*gdata_p==OP_FUNC_ENABLE)?"ENABLE":"DISABLE");
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPRltByCPU);
+
+int getIGMPRltByCPU(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPRltByCPU.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	ret = switchdGetIGMPRltByCPU(&(igmp ->gdata));
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+
+int switchdSetIGMPPktForward(unsigned int type, unsigned int rule)
+{
+	u16 regdata;
+	u16 rule_t;
+
+	IP2Page(1);
+	switch(type){
+	case OP_IGMP_PACKET_QUERY:
+	case OP_IGMP_PACKET_LEAVE:
+	case OP_IGMP_PACKET_UN_REG_DATA:
+	case OP_IGMP_PACKET_UN_DEFINED:
+		if(rule >= OP_IGMP_RULE_GROUP_MEM){
+			ip1811drv_dbg("Select Type can't support Rule 'OP_IGMP_RULE_GROUP_MEM'.\n");
+			return -EINVAL;
+		}
+		regdata = Read_Reg(P1REG_IGMPPKTFWD_0);
+		ip1811drv_dbg("Read IGMPPktForward_0 : %x\n", regdata);
+		rule_t = 0x000F<<type;
+		regdata &= ~rule_t;
+		regdata |= rule<<type;
+		ip1811drv_dbg("type : %d\n", type);
+		ip1811drv_dbg("rule : %x\n", rule);
+		ip1811drv_dbg("Write IGMPPktForward_0 : %x\n",regdata);
+		Write_Reg(P1REG_IGMPPKTFWD_0, regdata);
+		break;
+	case OP_IGMP_PACKET_REPORT:
+	case OP_IGMP_PACKET_GROUP_SPECIFIC_QUERY:
+	case OP_IGMP_PACKET_REG_DATA:
+		regdata = Read_Reg(P1REG_IGMPPKTFWD_1);
+		ip1811drv_dbg("Read IGMPPktForward_1 : %x\n", regdata);
+		rule_t = 0x001F<<(type-1);
+		regdata &= ~rule_t;
+		regdata |=rule<<(type-1);
+		ip1811drv_dbg("type : %d\n", type);
+		ip1811drv_dbg("rule : %x\n", rule);
+		ip1811drv_dbg("Write IGMPPktForward_1 : %x\n", regdata);
+		Write_Reg(P1REG_IGMPPKTFWD_1, regdata);
+		break;
+	default:
+		ip1811drv_dbg("Option can't find.\n");
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPPktForward);
+
+int setIGMPPktForward(void *cdata, int len)
+{
+	int ret;
+	struct IgmpPacketRule *igmp;
+	unsigned int pkt_type;
+	unsigned int pkt_rule;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPPktForward.\n");
+	if (sizeof(struct IgmpPacketRule) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+	igmp = (struct IgmpPacketRule *)cdata;
+	pkt_type = igmp ->packet_type;
+	pkt_rule = igmp ->rule;
+	ret = switchdSetIGMPPktForward(pkt_type, pkt_rule);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPPktForward(unsigned int type, int *rule_p)
+{
+	u16 regdata;
+	u16 rule_t;
+
+	IP2Page(1);
+	switch(type){
+	case OP_IGMP_PACKET_QUERY:
+	case OP_IGMP_PACKET_LEAVE:
+	case OP_IGMP_PACKET_UN_REG_DATA:
+	case OP_IGMP_PACKET_UN_DEFINED:
+		regdata = Read_Reg(P1REG_IGMPPKTFWD_0);
+		ip1811drv_dbg("Read IGMPPktForward_0 : %x\n", regdata);
+		rule_t = 0x000F<<type;
+		regdata &= rule_t;
+		*rule_p = regdata>>(type);
+		ip1811drv_dbg("type : %d\n", type);
+		ip1811drv_dbg("Get rule : %x\n", *rule_p);
+		break;
+	case OP_IGMP_PACKET_REPORT:
+	case OP_IGMP_PACKET_GROUP_SPECIFIC_QUERY:
+	case OP_IGMP_PACKET_REG_DATA:
+		regdata = Read_Reg(P1REG_IGMPPKTFWD_1);
+		ip1811drv_dbg("Read IGMPPktForward_1 : %x\n", regdata);
+		rule_t = 0x001F<<(type-1);
+		regdata &= rule_t;
+		*rule_p = regdata>>(type-1);
+		ip1811drv_dbg("type : %d\n", type);
+		ip1811drv_dbg("Get rule : %x\n", *rule_p);
+		break;
+	default:
+		ip1811drv_dbg("Option can't find.\n");
+		return -EINVAL;
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPPktForward);
+
+int getIGMPPktForward(void *cdata, int len)
+{
+	unsigned int pkt_type;
+	struct IgmpPacketRule *igmp;
+	int ret;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPPktForward.\n");
+	if (sizeof(struct IgmpPacketRule) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+	igmp = (struct IgmpPacketRule *)cdata;
+	pkt_type = igmp ->packet_type;
+	ret = switchdGetIGMPPktForward(pkt_type, &(igmp ->rule));
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetIGMPRlt(unsigned int map, unsigned int tstate)
+{
+	u16 regdata;
+	u16 i, mask;
+	
+	IP2Page(1);
+	regdata = Read_Reg(P1REG_ROUTLIST);
+	ip1811drv_dbg("Read [12-01] : %x\n", regdata);
+	mask = 0x01;
+	for(i=0; i<12;i++){
+		if((map&mask)!=0) {
+			if((tstate&mask)!=0)
+				regdata |= mask;
+			else
+				regdata &= ~mask;
+		}
+		mask <<= 1;
+	}
+	ip1811drv_dbg("Write new [12-01] : %x\n", regdata);
+	Write_Reg(P1REG_ROUTLIST, regdata);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPRlt);
+
+int setIGMPRlt(void *cdata, int len)
+{
+	u16 map, value;
+	struct IgmpRouterListSetting *igmp;
+	int ret;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPRlt.\n");
+	if (sizeof(struct IgmpRouterListSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+	
+	igmp = (struct IgmpRouterListSetting *)cdata;
+	map = 0xFFF&(igmp ->portmask);
+	value = 0xFFF&(igmp ->tstate);
+
+	ip1811drv_dbg("map [12-01] : %x\n", map);
+	ip1811drv_dbg("val [12-01] : %x\n", value);
+
+	ret = switchdSetIGMPRlt(map, value);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPRlt(unsigned int map, int *value_p)
+{
+	u16 regdata, value, i, mask;
+	
+	IP2Page(1);
+	regdata = Read_Reg(P1REG_ROUTLIST);
+	ip1811drv_dbg("Read [12-01] : %x\n", regdata&0xFFF);
+	mask = 0x01;
+	for(i=0; i<12; i++) {
+		if((map&mask)!=0){
+			if((regdata&mask)!=0)
+				value |= mask;
+			else
+				value &= ~mask;
+		}
+		mask <<= 1;
+	}
+
+	*value_p = value;
+	ip1811drv_dbg("Return value : %lx\n", *value_p);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPRlt);
+
+int getIGMPRlt(void *cdata, int len)
+{
+	u16 map, value, i, mask;
+	struct IgmpRouterListSetting *igmp;
+	int ret;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPRlt.\n");
+	if (sizeof(struct IgmpRouterListSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+	igmp = (struct IgmpRouterListSetting *)cdata;
+
+	map = 0xFFF&(igmp ->portmask);
+	ip1811drv_dbg("map [12-01] : %x\n", map);
+
+	ret = switchdGetIGMPRlt(map, &(igmp ->tstate));
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetIGMPHashMethod(int hash_method)
+{
+	if (!(hash_method==OP_HASH_DIRECT || hash_method==OP_HASH_CRC))
+		return -EINVAL;
+
+	ip1811drv_dbg("Set Hash Method: %s\n", (hash_method==OP_HASH_DIRECT)?"DIRECT":"CRC");
+	_WriteRegBits(1, P1REG_IGMPSNOP, 6, 1,(hash_method==OP_HASH_DIRECT)?1:0);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPHashMethod);
+
+int setIGMPHashMethod(void *cdata, int len)
+{
+	int hash, ret;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	hash = ((struct GeneralSetting *)cdata) ->gdata;
+	ret = switchdSetIGMPHashMethod(hash);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPHashMethod(int *gdata_p)
+{
+	*gdata_p = (int)_ReadRegBits(1, P1REG_IGMPSNOP, 6, 1)?OP_HASH_DIRECT:OP_HASH_CRC;
+	ip1811drv_dbg("HASH METHOD %s",(*gdata_p==OP_HASH_DIRECT)?"DIRECT":"CRC");
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPHashMethod);
+
+int getIGMPHashMethod(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *igmp;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPHashMethod.\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	igmp = (struct GeneralSetting *)cdata;
+	ret = switchdGetIGMPHashMethod(&(igmp ->gdata));
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetIGMPMldRule(int forwarding)
+{
+
+	ip1811drv_dbg("set ICMPv6 MLD forwarding: %x\n", forwarding);
+	_WriteRegBits(0, P0REG_IPV6RLTFWD, 8, 2, forwarding);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPMldRule);
+
+int setIGMPMldRule(void *cdata, int len)
+{
+	struct GeneralSetting *igmp;
+	int ret, forward;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPMldRule.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	forward = igmp ->gdata;
+	ret = switchdSetIGMPMldRule(forward);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPMldRule(int *gdata_p)
+{
+	*gdata_p = (int)_ReadRegBits(0, P0REG_IPV6RLTFWD, 8, 2);
+	ip1811drv_dbg("get ICMPv6 MLD forwarding: %x\n", *gdata_p);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPMldRule);
+
+int getIGMPMldRule(void *cdata, int len)
+{
+	struct GeneralSetting *igmp;
+	int ret;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPMldRule.\n");
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct GeneralSetting *)cdata;
+	ret = switchdGetIGMPMldRule(&(igmp ->gdata));
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+void makeTable(u16 *tmpbuf, u16 offset, u32 value, u8 len)
+{
+	u16 ptr, set, tmpvalue;
+
+	ptr = offset/16;
+	set = offset%16;
+	ip1811drv_dbg("\n\nMakeTable:\noffset : %d\nvalue : %x\nlen : %d\n", offset, value, len);
+	ip1811drv_dbg("\nbuf[%d]=%x buf[%d]=%x\n", ptr, tmpbuf[ptr], ptr+1, tmpbuf[ptr+1]);
+	tmpvalue = (0xFFFF&value)<<set;
+	tmpbuf[ptr] |= tmpvalue;
+	ip1811drv_dbg("Result:\nbuf[%d] | %x = %x\n", ptr, tmpvalue, tmpbuf[ptr]);
+	if(len>(16-set)) {
+		len -= (16-set);
+		tmpvalue = 0xFFFF&(value>>(16-set));
+		tmpbuf[ptr+1] |= tmpvalue;
+		ip1811drv_dbg("buf[%d] | %x = %x\n", ptr+1, tmpvalue, tmpbuf[ptr+1]);
+		if(len>16){
+			tmpvalue = 0xFFFF&(value>>(32-set));
+			tmpbuf[ptr+2] |= tmpvalue;
+			ip1811drv_dbg("buf[%d] | %x = %x\n", ptr+2, tmpvalue, tmpbuf[ptr+2]);
+		}
+	}
+}
+
+u32 getTable(u16 *tmpbuf, u16 offset, u8 len)
+{
+	u32 value;
+	u16 ptr, set, tmpvalue, i, mask;
+	u16 debug;
+	ip1811drv_dbg("getTable:\n");
+	ip1811drv_dbg("offset = %d, len = %d", offset, len);
+	debug = offset/16;
+	ip1811drv_dbg("tmpbuf[%d] offset value:\n", debug);
+	for(i=0; i<3; i++)
+		ip1811drv_dbg("%04x ", tmpbuf[debug+i]);
+	ptr = (offset+len)/16;
+	set = (offset+len)%16;
+
+	if(len>=set){
+		mask = 0;
+		for(i=0; i<set; i++){
+			mask <<= 1;
+			mask |= 0x01;
+		}
+		tmpvalue = tmpbuf[ptr]&mask;
+		value = tmpvalue;
+		if((len-set)>=16) {
+			value <<= 16;
+			value |= tmpbuf[ptr-1];
+			if((len-set-16)>0){
+				value <<= (len-set-16);
+				value |= tmpbuf[ptr-2]>>(16-(len-set-16));
+			}
+		} else {
+			if(len!=set) {
+				value <<= (len-set);
+				value |= tmpbuf[ptr-1]>>(16-(len-set));
+			}
+		}
+	} else {
+		mask = 0;
+		for(i=0; i<set; i++){
+			mask <<= 1;
+			mask |= 0x01;
+		}
+		tmpvalue = tmpbuf[ptr]&mask;
+		value = tmpvalue>>(set-len);
+	}
+	ip1811drv_dbg("return %x\n",value);
+	return value;
+}
+
+/*	ipv:	4:	IPv4
+ *		6:	IPv6
+ *	addr:	IP	address
+ *	method:	1:	Direct
+ *		0:	CRC
+ * */
+u8 tb_calc_index(u8 ipv, void *addr, u8 method)
+{
+	u8 index = 0;
+	u8 *u8_addr = (u8*)addr;
+
+	// Direct
+	if(method) {
+		if(ipv == 4) {
+			index = u8_addr[3];
+		} else if(ipv == 6) {
+			index = u8_addr[15];
+		}
+	} else { // CRC
+		int i;
+		bool crc[8], d[32];
+		bool c[8] = {1,1,1,1,1,1,1,1};
+
+		// init data
+		if(ipv == 4) {
+			for(i=0; i<32; i++)
+				d[i] = (bool)((u8_addr[i/8] >> (7-(i%8))) & 0x1);
+		} else if(ipv == 6) {
+			for(i=0; i<32; i++)
+				d[i] = (bool)((u8_addr[12+(i/8)] >> (7-(i%8))) & 0x1);
+		}
+
+		// calculate crc
+		crc[0] = d[31] ^ d[30] ^ d[28] ^ d[23] ^ d[21] ^ d[19] ^ d[18] ^ d[16] ^ d[14] ^ d[12] ^ d[8] ^ d[7] ^ d[6] ^ d[0] ^ c[4] ^ c[6] ^ c[7];
+
+		crc[1] = d[30] ^ d[29] ^ d[28] ^ d[24] ^ d[23] ^ d[22] ^ d[21] ^ d[20] ^ d[18] ^ d[17] ^ d[16] ^ d[15] ^ d[14] ^ d[13] ^ d[12] ^ d[9] ^ d[6] ^ d[1] ^ d[0] ^ c[0] ^ c[4] ^ c[5] ^ c[6];
+
+		crc[2] = d[29] ^ d[28] ^ d[25] ^ d[24] ^ d[22] ^ d[17] ^ d[15] ^ d[13] ^ d[12] ^ d[10] ^ d[8] ^ d[6]^ d[2] ^ d[1] ^ d[0] ^ c[0] ^ c[1] ^ c[4] ^ c[5];
+
+		crc[3] = d[30] ^ d[29] ^ d[26] ^ d[25] ^ d[23] ^ d[18] ^ d[16] ^ d[14] ^ d[13] ^ d[11] ^ d[9] ^ d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[1] ^ c[2] ^ c[5] ^ c[6];
+
+		crc[4] = d[31] ^ d[30] ^ d[27] ^ d[26] ^ d[24] ^ d[19] ^ d[17] ^ d[15] ^ d[14] ^ d[12] ^ d[10] ^ d[8] ^ d[4] ^ d[3] ^ d[2] ^ c[0] ^ c[2] ^ c[3] ^ c[6] ^ c[7];
+
+		crc[5] = d[31] ^ d[28] ^ d[27] ^ d[25] ^ d[20] ^ d[18] ^ d[16] ^ d[15] ^ d[13] ^ d[11] ^ d[9] ^ d[5] ^ d[4] ^ d[3] ^ c[1] ^ c[3] ^ c[4] ^ c[7];
+
+		crc[6] = d[29] ^ d[28] ^ d[26] ^ d[21] ^ d[19] ^ d[17] ^ d[16] ^ d[14] ^ d[12] ^ d[10] ^ d[6] ^ d[5] ^ d[4] ^ c[2] ^ c[4] ^ c[5];
+
+		crc[7] = d[30] ^ d[29] ^ d[27] ^ d[22] ^ d[20] ^ d[18] ^ d[17] ^ d[15] ^ d[13] ^ d[11] ^ d[7] ^ d[6] ^ d[5] ^ c[3] ^ c[5] ^ c[6];
+
+		// get index
+		for(i=0; i<8; i++)
+			index |= ((u8)crc[i])<<i;
+	}
+
+	ip1811drv_dbg("tb_calc_index() index = %02u\n", index);
+	return index;
+}
+
+int switchdSetIGMPMctTable(int index, struct mt_rule *mt_data)
+{
+	u16 regdata[6] = {0};
+	u16 i, tmpvalue;
+
+	memset(regdata, 0, 11);
+	ip1811drv_dbg("driver:index: %x\n", index);
+	ip1811drv_dbg("driver:group: %x : %x : %x : %x\n", mt_data->group[0], mt_data->group[1], mt_data->group[2], mt_data->group[3]);
+	ip1811drv_dbg("driver:Set FID: %x\n", mt_data->fid);
+	ip1811drv_dbg("driver:Set age port:: %lx\n", mt_data->port_mem);
+	ip1811drv_dbg("driver:Set SIP: %x\n", mt_data->slt_index);
+	ip1811drv_dbg("driver:Set flag: %x\n", mt_data->flag);
+
+	//set Group
+	regdata[0] = (mt_data->group[2] << 8) | mt_data->group[3];
+	regdata[1] = (mt_data->group[0] << 8) | mt_data->group[1];
+	//set FID
+	makeTable(regdata, 32, mt_data->fid, 4);
+	//set Aging Member
+	for(i=0; i<12; i++) {
+		if(mt_data->port_mem & BIT(i)) {
+			makeTable(regdata, 36+i, 0x1, 1);
+			makeTable(regdata, 36+i+12, 0x1, 1);
+			makeTable(regdata, 36+i+24, 0x1, 1);
+		}
+	}
+	//set Pri
+	makeTable(regdata, 72, mt_data->pri, 4);
+	//set SIP
+	makeTable(regdata, 76, mt_data->slt_index, 5);
+	//set ver and CPU
+	makeTable(regdata, 81, mt_data->flag, 2);
+
+	IP2Page(1);
+	ip1811drv_dbg("driver:Write Mct Table Data:\n");
+	for(i=0; i<6; i++) {
+		ip1811drv_dbg("%04x ", regdata[i]);
+		Write_Reg(P1REG_MEM_MCT_TABLE_0+i, regdata[i]);
+	}
+	ip1811drv_dbg("\n");
+
+	tmpvalue = index;
+	tmpvalue |= 0xC000;
+	ip1811drv_dbg("\ndirver:Start Write [%04x]", tmpvalue);
+	Write_Reg(P1REG_MEM_MCT_COMMAND, tmpvalue);
+
+	tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND);
+	while((tmpvalue&0x8000)!=0)
+		tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPMctTable);
+
+int setIGMPMctTable(void *cdata, int len){
+	
+	int ret, index;
+	struct MtRuleSetting *igmp;
+	struct mt_rule *mt;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPMctTable.\n");
+	if (sizeof(struct MtRuleSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct MtRuleSetting *)cdata;
+	index = igmp ->index;
+	mt = &(igmp ->mt_data);
+	ret = switchdSetIGMPMctTable(index, mt);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+
+int switchdGetIGMPMctTable(int index, struct mt_rule *mt_data)
+{
+	u16 regdata[6] = {0};
+	u16 i, j, tmpvalue;
+	u32 mask;
+	
+	tmpvalue = index;
+	tmpvalue |= 0x8000;
+	IP2Page(1);
+	Write_Reg(P1REG_MEM_MCT_COMMAND, tmpvalue);
+	ip1811drv_dbg("driver:start read: %x\n", tmpvalue);
+
+	tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND);
+	while((tmpvalue&0x8000)!=0)
+		tmpvalue = Read_Reg(P1REG_MEM_MCT_COMMAND);
+
+	ip1811drv_dbg("driver:index: %x\n", index);
+	ip1811drv_dbg("driver:Read Table Data:\n");
+	for(i=0; i<6; i++) {
+		regdata[i] = Read_Reg(P1REG_MEM_MCT_TABLE_0+i);
+		ip1811drv_dbg("%04x ", regdata[i]);
+	}
+	ip1811drv_dbg("\nRead Group:\n");
+	for(i=0; i<4; i++) {
+		mt_data->group[i] = getTable(regdata, (0+(8*i)), 8);
+		ip1811drv_dbg("%x ", mt_data->group[i]);
+	}
+
+	ip1811drv_dbg("\nRead FID:\n");
+	mt_data->fid = getTable(regdata, 32, 4);
+	ip1811drv_dbg("%x\n",mt_data->fid);
+
+	ip1811drv_dbg("Read Aging:\n");
+	mask = 0;
+	for(i=0; i<12; i++){
+		int val = 0;
+		for(j=0; j<3; j++) {
+			if(getTable(regdata, (36+i+(12*j)), 1)!=0 )
+				val++;
+		}
+		if(val)
+			mask |= 0x01<<i;
+	}
+	ip1811drv_dbg("%x\n", mask);
+	mt_data->port_mem = mask;
+
+	ip1811drv_dbg("Read Priority:\n");
+	mt_data->pri = getTable(regdata, 72, 4);
+	ip1811drv_dbg("%x\n",mt_data->pri);
+	
+	ip1811drv_dbg("Read SLT index:\n");
+	mt_data->slt_index = getTable(regdata, 76, 5);
+	ip1811drv_dbg("%x\n",mt_data->slt_index);
+
+	ip1811drv_dbg("Read flag:\n");
+	mt_data->flag = getTable(regdata, 81, 2);
+	ip1811drv_dbg("%x\n",mt_data->flag);
+
+	printk(KERN_ERR "\nGroup:");
+	for(i=0;i<4;i++)
+		printk(KERN_ERR " %d", mt_data->group[i]);
+	printk(KERN_ERR "\nFID: %x", mt_data->fid);
+	printk(KERN_ERR "\nPort member: %lx", (unsigned long)mt_data->port_mem);
+	printk(KERN_ERR "\nPriority: %d", (mt_data->pri&0x07));
+	printk(KERN_ERR "\nSLT index: %x", mt_data->slt_index);
+	printk(KERN_ERR "\nFlag: %x\n", mt_data->flag);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPMctTable);
+
+int getIGMPMctTable(void *cdata, int len){
+	int ret, index;
+	struct MtRuleSetting *igmp;
+	struct mt_rule *mt;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPMctTable.\n");
+	if (sizeof(struct MtRuleSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct MtRuleSetting *)cdata;
+	index = igmp ->index;
+	mt = &(igmp ->mt_data);
+	ret = switchdGetIGMPMctTable(index, mt);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetIGMPSltTable(int index, struct slt_rule *slt_data)
+{
+	u16 regdata[19] = {0};
+	u16 i, j, tmpvalue;
+
+	if(slt_data->type == OP_IGMP_SLT_IPV4) {
+		//set IP
+		for(i=0; i<6; i++){
+			regdata[i*2] = (slt_data->data.ipv4.ip[i][2] << 8) | slt_data->data.ipv4.ip[i][3];
+			regdata[i*2+1] = (slt_data->data.ipv4.ip[i][0] << 8) | slt_data->data.ipv4.ip[i][1];
+		}
+		//set User Define
+		for(i=0; i<6; i++)
+			makeTable(regdata, (192+(12*i)), slt_data->data.ipv4.used_port[i], 12);
+	}else{
+		//set IP
+		for(i=0; i<2; i++){
+			for(j=0; j<8; j++)
+				makeTable(regdata, ((128*i)+(16*j)), slt_data->data.ipv6.ip[i][7-j], 16);
+		}
+		//set User Define
+		for(i=0; i<2 ;i++)
+			makeTable(regdata, (256+(12*i)), slt_data->data.ipv6.used_port[i], 12);
+	}
+
+	ip1811drv_dbg("SLT Table Data:");
+	IP2Page(1);
+	for(i=0; i<19; i++) {
+		if((i%16)==0)
+			ip1811drv_dbg("\n");
+		ip1811drv_dbg("%04x ", regdata[i]);
+		Write_Reg(P1REG_MEM_SLT_TABLE_0+i, regdata[i]);
+	}
+	tmpvalue = index;
+	tmpvalue |= 0xC000;
+	ip1811drv_dbg("\ndirver:Start Write [%04x]", tmpvalue);
+	Write_Reg(P1REG_MEM_SLT_COMMAND, tmpvalue);
+
+    return 0;
+}
+EXPORT_SYMBOL(switchdSetIGMPSltTable);
+
+int setIGMPSltTable(void *cdata, int len){
+	int ret, index;
+	struct SltRuleSetting *igmp;
+	struct slt_rule *slt;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In setIGMPSltTable.\n");
+	if (sizeof(struct SltRuleSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct SltRuleSetting *)cdata;
+	index = igmp ->index;
+	slt = &(igmp ->slt_data);
+	ret = switchdSetIGMPSltTable(index, slt);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetIGMPSltTable(int index, struct slt_rule *slt_data)
+{
+	u16 regdata[19] = {0};
+	u16 i, j, tmpvalue;
+	
+	tmpvalue = index;
+	tmpvalue |= 0x8000;
+	IP2Page(1);
+	Write_Reg(P1REG_MEM_SLT_COMMAND, tmpvalue);
+
+	tmpvalue = Read_Reg(P1REG_MEM_SLT_COMMAND);
+	while( (tmpvalue&0x8000)!=0 )
+		tmpvalue = Read_Reg(P1REG_MEM_SLT_COMMAND);
+
+	ip1811drv_dbg("Read SLT Table:");
+	for(i=0; i<19; i++) {
+		regdata[i] = Read_Reg(P1REG_MEM_SLT_TABLE_0+i);
+		if(i%16==0)
+			ip1811drv_dbg("\n");
+		ip1811drv_dbg("%04x ", regdata[i]);
+	}
+
+	if(slt_data->type == OP_IGMP_SLT_IPV4){
+		ip1811drv_dbg("Read IPv4:\n");
+		printk(KERN_ERR "\nRead IPv4:");
+		for(i=0; i<6; i++) {
+			printk(KERN_ERR "\n");
+			for(j=0; j<4; j++) {
+				slt_data->data.ipv4.ip[i][j] = getTable(regdata, ((32*i)+(8*j)), 8 );
+				printk(KERN_ERR " %d", slt_data->data.ipv4.ip[i][j]);
+			}
+		}
+		ip1811drv_dbg("Read Used Define:\n");
+		printk(KERN_ERR "\nUsed Define:\n");
+		for(i=0; i<6; i++) {
+			slt_data->data.ipv4.used_port[i] = getTable(regdata, (192+(12*i)), 12);
+			printk(KERN_ERR " %04lx", (unsigned long)slt_data->data.ipv4.used_port[i]);
+		}
+	}else{
+		ip1811drv_dbg("Read IPv6:\n");
+		printk(KERN_ERR "\nRead IPv6:");
+		for(i=0; i<2; i++) {
+			printk(KERN_ERR "\n");
+			for(j=0; j<8; j++) {
+				slt_data->data.ipv6.ip[i][j] = getTable(regdata, ((128*i)+(16*j)), 16);
+				printk(KERN_ERR " %04x", slt_data->data.ipv6.ip[i][j]);
+			}
+		}
+		ip1811drv_dbg("Read Used Define:\n");
+		printk(KERN_ERR "\nUsed Define:\n");
+		for(i=0; i<2;i++) {
+			slt_data->data.ipv6.used_port[i] = getTable(regdata, (256+(12*i)), 12);
+			printk(KERN_ERR " %04lx", (unsigned long)slt_data->data.ipv6.used_port[i]);
+		}
+	}
+	printk(KERN_ERR "\n");
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetIGMPSltTable);
+
+int getIGMPSltTable(void *cdata, int len){
+	int ret, index;
+	struct SltRuleSetting *igmp;
+	struct slt_rule *slt;
+
+	FUNC_MSG_IN;
+	ip1811drv_dbg("In getIGMPSltTable.\n");
+	if (sizeof(struct SltRuleSetting) != len) {
+		ip1811drv_err("length error!\n");
+		return -EINVAL;
+	}
+
+	igmp = (struct SltRuleSetting *)cdata;
+	index = igmp ->index;
+	slt = &(igmp ->slt_data);
+	ret = switchdGetIGMPSltTable(index, slt);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+
+//------------------------------------------------
+//ip1811_sniffer
+int switchdSetS1PktModify(int modify)
+{
+	if (modify!=OP_SNIFFER1_PKT_MODIFY && modify!=OP_SNIFFER1_PKT_KEEP)
+		return -EINVAL;
+	ip1811drv_dbg("modify=%d\n", modify);
+
+	_WriteRegBits(1, P1REG_SNIFCFG, 2, 1, modify);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetS1PktModify);
+int setS1PktModify(void *cdata, int len)
+{
+	int modify;
+
+	ip1811drv_dbg("ip1811: +setS1PktModify...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	modify = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetS1PktModify(modify) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setS1PktModify...\n");
+	return 0;
+}
+
+int switchdGetS1PktModify(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 2, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetS1PktModify);
+int getS1PktModify(void *cdata, int len)
+{
+	int modify;
+	
+	ip1811drv_dbg("ip1811: +getS1PktModify...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetS1PktModify(&modify) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = modify;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getS1PktModify...\n");
+	return 0;
+}
+
+int switchdSetS1TM4CpuSTag(int modify)
+{
+	if (modify!=OP_SNIFFER1_TAG_KEEP && modify!=OP_SNIFFER1_TAG_MODIFY)
+		return -EINVAL;
+	ip1811drv_dbg("modify=%d\n", modify);
+
+	_WriteRegBits(1, P1REG_SNIFCFG, 5, 1, modify);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetS1TM4CpuSTag);
+int setS1TM4CpuSTag(void *cdata, int len)
+{
+	int modify;
+
+	ip1811drv_dbg("ip1811: +setS1TM4CpuSTag...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	modify = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetS1TM4CpuSTag(modify) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setS1TM4CpuSTag...\n");
+	return 0;
+}
+
+int switchdGetS1TM4CpuSTag(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 5, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetS1TM4CpuSTag);
+int getS1TM4CpuSTag(void *cdata, int len)
+{
+	int modify;
+	
+	ip1811drv_dbg("ip1811: +getS1TM4CpuSTag...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetS1TM4CpuSTag(&modify) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = modify;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getS1TM4CpuSTag...\n");
+	return 0;
+}
+
+int switchdSetS1TM4Acl2Cpu(int modify)
+{
+	if (modify!=OP_SNIFFER1_TAG_KEEP && modify!=OP_SNIFFER1_TAG_MODIFY)
+		return -EINVAL;
+	ip1811drv_dbg("modify=%d\n", modify);
+
+	_WriteRegBits(1, P1REG_SNIFCFG, 6, 1, modify);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetS1TM4Acl2Cpu);
+int setS1TM4Acl2Cpu(void *cdata, int len)
+{
+	int modify;
+
+	ip1811drv_dbg("ip1811: +setS1TM4Acl2Cpu...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	modify = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetS1TM4Acl2Cpu(modify) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setS1TM4Acl2Cpu...\n");
+	return 0;
+}
+
+int switchdGetS1TM4Acl2Cpu(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 6, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetS1TM4Acl2Cpu);
+int getS1TM4Acl2Cpu(void *cdata, int len)
+{
+	int modify;
+	
+	ip1811drv_dbg("ip1811: +getS1TM4Acl2Cpu...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetS1TM4Acl2Cpu(&modify) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = modify;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getS1TM4Acl2Cpu...\n");
+	return 0;
+}
+
+int switchdSetS1TM4Pkt2MPort(int modify)
+{
+	if (modify!=OP_SNIFFER1_TAG_KEEP && modify!=OP_SNIFFER1_TAG_MODIFY)
+		return -EINVAL;
+	ip1811drv_dbg("modify=%d\n", modify);
+
+	_WriteRegBits(1, P1REG_SNIFCFG, 7, 1, modify);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetS1TM4Pkt2MPort);
+int setS1TM4Pkt2MPort(void *cdata, int len)
+{
+	int modify;
+
+	ip1811drv_dbg("ip1811: +setS1TM4Pkt2MPort...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	modify = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetS1TM4Pkt2MPort(modify) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setS1TM4Pkt2MPort...\n");
+	return 0;
+}
+
+int switchdGetS1TM4Pkt2MPort(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 7, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetS1TM4Pkt2MPort);
+int getS1TM4Pkt2MPort(void *cdata, int len)
+{
+	int modify;
+	
+	ip1811drv_dbg("ip1811: +getS1TM4Pkt2MPort...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetS1TM4Pkt2MPort(&modify) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = modify;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getS1TM4Pkt2MPort...\n");
+	return 0;
+}
+
+int switchdSetS2LTT4Grp1(int ltt)
+{
+	if (ltt!=OP_SNIFFER2_LUT_TRIGGER_TARGET_DA && ltt!=OP_SNIFFER2_LUT_TRIGGER_TARGET_SA)
+		return -EINVAL;
+	ip1811drv_dbg("ltt=%d\n", ltt);
+
+	_WriteRegBits(1, P1REG_SNIFCFG, 3, 1, ltt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetS2LTT4Grp1);
+int setS2LTT4Grp1(void *cdata, int len)
+{
+	int ltt;
+
+	ip1811drv_dbg("ip1811: +setS2LTT4Grp1...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	ltt = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetS2LTT4Grp1(ltt) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setS2LTT4Grp1...\n");
+	return 0;
+}
+
+int switchdGetS2LTT4Grp1(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_SNIFCFG, 3, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetS2LTT4Grp1);
+int getS2LTT4Grp1(void *cdata, int len)
+{
+	int ltt;
+	
+	ip1811drv_dbg("ip1811: +getS2LTT4Grp1...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetS2LTT4Grp1(&ltt) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = ltt;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getS2LTT4Grp1...\n");
+	return 0;
+}
+
+//------------------------------------------------
+//ip1811_storm
+int switchdSetMStormNBlockIpPkt(int nb)
+{
+	if (nb!=OP_FUNC_DISABLE && nb!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("nb=%d\n", nb);
+
+	_WriteRegBits(1, P1REG_BSTORMTHRESH, 11, 1, nb);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetMStormNBlockIpPkt);
+int setMStormNBlockIpPkt(void *cdata, int len)
+{
+	int nb;
+
+	ip1811drv_dbg("ip1811: +setMStormNBlockIpPkt...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	nb = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetMStormNBlockIpPkt(nb) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setMStormNBlockIpPkt...\n");
+	return 0;
+}
+
+int switchdGetMStormNBlockIpPkt(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_BSTORMTHRESH, 11, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetMStormNBlockIpPkt);
+int getMStormNBlockIpPkt(void *cdata, int len)
+{
+	int nb;
+	
+	ip1811drv_dbg("ip1811: +getMStormNBlockIpPkt...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+		
+	if(switchdGetMStormNBlockIpPkt(&nb) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = nb;
+
+	ip1811drv_dbg("ip1811: -getMStormNBlockIpPkt...\n");
+	return 0;
+}
+
+int switchdSetMStormIgnr01005EXXXXXX(int ignr)
+{
+	if (ignr!=OP_FUNC_DISABLE && ignr!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("ignr=%d\n", ignr);
+
+	_WriteRegBits(1, P1REG_BSTORMTHRESH, 12, 1, ignr);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetMStormIgnr01005EXXXXXX);
+int setMStormIgnr01005EXXXXXX(void *cdata, int len)
+{
+	int ignr;
+
+	ip1811drv_dbg("ip1811: +setMStormIgnr01005EXXXXXX...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	ignr = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetMStormIgnr01005EXXXXXX(ignr) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setMStormIgnr01005EXXXXXX...\n");
+	return 0;
+}
+
+int switchdGetMStormIgnr01005EXXXXXX(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_BSTORMTHRESH, 12, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetMStormIgnr01005EXXXXXX);
+int getMStormIgnr01005EXXXXXX(void *cdata, int len)
+{
+	int en=0;
+	
+	ip1811drv_dbg("ip1811: +getMStormIgnr01005EXXXXXX...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+		
+	if(switchdGetMStormIgnr01005EXXXXXX(&en) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = en;
+
+	ip1811drv_dbg("ip1811: -getMStormIgnr01005EXXXXXX...\n");
+	return 0;
+}
+
+//ip1811_stp
+int switchdSetBpduCapMode(int bcmode)
+{
+	if (bcmode!=OP_BPDU_CMODE_GLOBAL && bcmode!=OP_BPDU_CMODE_BY_PORT)
+		return -EINVAL;
+	ip1811drv_dbg("bcmode=%d\n", bcmode);
+
+	_WriteRegBits(0, P0REG_MACBEHAVIOR, 10, 1, bcmode);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetBpduCapMode);
+int setBpduCapMode(void *cdata, int len)
+{
+	int bcmode;
+
+	ip1811drv_dbg("ip1811: +setBpduCapMode...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	bcmode = ((struct GeneralSetting *)cdata) ->gdata;
+	
+	if(switchdSetBpduCapMode(bcmode) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setBpduCapMode...\n");
+	return 0;
+}
+
+int switchdGetBpduCapMode(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(0, P0REG_MACBEHAVIOR, 10, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetBpduCapMode);
+int getBpduCapMode(void *cdata, int len)
+{
+	int bcmode;
+
+	ip1811drv_dbg("ip1811: +getBpduCapMode...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetBpduCapMode(&bcmode) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = bcmode;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getBpduCapMode...\n");
+	return 0;
+}
+
+int switchdSetBpduPortAct(int port, int state)
+{
+	u16 u16dat;
+	
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if (state!=OP_CAP_ACT_FORWARD && state!=OP_CAP_ACT_TO_CPU && state!=OP_CAP_ACT_DROP)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("state=%d\n", state);
+
+	IP2Page(0);
+	u16dat = Read_Reg(P0REG_BPDUPORTCAPCFG);
+	u16dat |= (u16)((state&0x1) << (port));
+#ifdef COMBINED_PORT
+	if (port==9)
+		u16dat |= (u16)((state&0x1) << (port+1));
+#endif
+	Write_Reg(P0REG_BPDUPORTCAPCFG, u16dat);
+	
+	u16dat = Read_Reg(P0REG_BPDUPORTCAPCFG+2);
+	u16dat |= (u16)(((state>>1)&0x1) << (port));
+#ifdef COMBINED_PORT
+	if (port==9)
+		u16dat |= (u16)(((state>>1)&0x1) << (port+1));
+#endif
+	Write_Reg(P0REG_BPDUPORTCAPCFG+2, u16dat);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetBpduPortAct);
+int setBpduPortAct(void *cdata, int len)
+{
+	int port, state;
+
+	ip1811drv_dbg("ip1811: +setBpduPortAct...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	state= ((struct ByPortSetting *)cdata) ->pdata;
+
+	if(switchdSetBpduPortAct(port, state) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setBpduPortAct...\n");
+	return 0;
+}
+
+int switchdGetBpduPortAct(int port, int *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (int)(_ReadRegBits(0, P0REG_BPDUPORTCAPCFG+2, port, 1) | _ReadRegBits(0, P0REG_BPDUPORTCAPCFG, port, 1));
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetBpduPortAct);
+int getBpduPortAct(void *cdata, int len)
+{
+	int port, state;
+
+	ip1811drv_dbg("ip1811: +getBpduPortAct...\n");
+	if (sizeof(struct ByPortSetting) != len)
+		return -EINVAL;
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+
+	if(switchdGetBpduPortAct(port, &state) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = state;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	ip1811drv_dbg("ip1811: -getBpduPortAct...\n");
+	return 0;
+}
+
+int switchdSetStpPortState(int fid, int port, int state)
+{
+	u16 u16dat=0;
+	
+	if (fid < 1 || fid > 16)
+		return -EINVAL;
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if (state < OP_STP_STATE_DISCARD || state > OP_STP_STATE_FORWARD)
+		return -EINVAL;
+	ip1811drv_dbg("fid=%d\n", fid);
+	ip1811drv_dbg("port=%d\n", port);
+	ip1811drv_dbg("state=%d\n", state);
+
+	fid--;
+	IP2Page(2);
+	Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8010 | fid));
+	u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA);
+	switch(state){
+		case OP_STP_STATE_DISCARD:
+		case OP_STP_STATE_BLOCK:
+			u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+			if (port==9)
+				u16dat &= (u16)~(1 << port+1);
+#endif
+			break;
+		case OP_STP_STATE_LEARN:
+		case OP_STP_STATE_FORWARD:
+			u16dat |= (u16)(1 << port);
+#ifdef COMBINED_PORT
+			if (port==9)
+				u16dat |= (u16)(1 << port+1);
+#endif
+			break;
+	}
+	Write_Reg(P2REG_SPANTREE_PORTDTA, u16dat & 0xFFFF);
+	Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0xC010 | fid));
+	
+	Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8000 | fid));
+	u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA);
+	switch(state){
+		case OP_STP_STATE_DISCARD:
+		case OP_STP_STATE_LEARN:
+			u16dat &= (u16)~(1 << port);
+#ifdef COMBINED_PORT
+			if (port==9)
+				u16dat &= (u16)~(1 << port+1);
+#endif
+			break;
+		case OP_STP_STATE_BLOCK:
+		case OP_STP_STATE_FORWARD:
+			u16dat |= (u16)(1 << port);
+#ifdef COMBINED_PORT
+			if (port==9)
+				u16dat |= (u16)(1 << port+1);
+#endif
+			break;
+	}
+	Write_Reg(P2REG_SPANTREE_PORTDTA, u16dat & 0xFFFF);
+	Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0xC000 | fid));
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetStpPortState);
+int setStpPortState(void *cdata, int len)
+{
+	int fid, port, state;
+
+	ip1811drv_dbg("ip1811: +setStpPortState...\n");
+	if (sizeof(struct StpByFPSetting) != len)
+		return -EINVAL;
+
+	fid = ((struct StpByFPSetting *)cdata) ->fid;
+	port= ((struct StpByFPSetting *)cdata) ->port;
+	state=((struct StpByFPSetting *)cdata) ->pstate;
+
+	if(switchdSetStpPortState(fid, port, state) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setStpPortState...\n");
+	return 0;
+}
+
+int switchdGetStpPortState(int fid, int port, int *ptrInt)
+{
+	int state;
+	u16 u16dat=0;
+	
+	if (fid < 1 || fid > 16)
+		return -EINVAL;
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	ip1811drv_dbg("fid=%d\n", fid);
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	fid--;
+	IP2Page(2);
+	Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8010 | fid));
+	u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA);
+	state = ((u16dat>>port)&0x1)<<1;
+	Write_Reg(P2REG_SPANTREE_PORTCMD, (u16)(0x8000 | fid));
+	u16dat = Read_Reg(P2REG_SPANTREE_PORTDTA);
+	state |= ((u16dat>>port)&0x1);
+	
+	*ptrInt = state;
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetStpPortState);
+int getStpPortState(void *cdata, int len)
+{
+	int fid, port, state;
+
+	ip1811drv_dbg("ip1811: +getStpPortState...\n");
+	if (sizeof(struct StpByFPSetting) != len)
+		return -EINVAL;
+
+	fid = ((struct StpByFPSetting *)cdata) ->fid;
+	port= ((struct StpByFPSetting *)cdata) ->port;
+
+	if(switchdGetStpPortState(fid, port, &state) != 0)
+		return -EINVAL;
+
+	((struct StpByFPSetting *)cdata) ->pstate = state;
+	ip1811drv_dbg("cdata ->pstate=%d\n", ((struct StpByFPSetting *)cdata) ->pstate);
+	ip1811drv_dbg("ip1811: -getStpPortState...\n");
+	return 0;
+}
+
+//ip1811_lacp
+int switchdSetTrunkHashMthdSeq(int en)
+{
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(1, P1REG_TRUNKCFG, 3, 1, en);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetTrunkHashMthdSeq);
+int setTrunkHashMthdSeq(void *cdata, int len)
+{
+	int en;
+
+	ip1811drv_dbg("ip1811: +setTrunkHashMthdSeq...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	if(switchdSetTrunkHashMthdSeq(en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setTrunkHashMthdSeq...\n");
+	return 0;
+}
+
+int switchdGetTrunkHashMthdSeq(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, 3, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetTrunkHashMthdSeq);
+int getTrunkHashMthdSeq(void *cdata, int len)
+{
+	int en;
+
+	ip1811drv_dbg("ip1811: +getTrunkHashMthdSeq...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	if(switchdGetTrunkHashMthdSeq(&en) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata) ->gdata = en;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getTrunkHashMthdSeq...\n");
+	return 0;
+}
+
+int switchdSetTrunkGrpCombine(int grps, int en)
+{
+	if (grps < OP_TRUNK_COMBINE_G1_G2 || grps > OP_TRUNK_COMBINE_G3_G4)
+		return -EINVAL;
+	if (en!=OP_FUNC_DISABLE && en!=OP_FUNC_ENABLE)
+		return -EINVAL;
+	ip1811drv_dbg("grps=%d\n", grps);
+	ip1811drv_dbg("en=%d\n", en);
+
+	_WriteRegBits(1, P1REG_TRUNKCFG, grps, 1, en);
+	
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetTrunkGrpCombine);
+int setTrunkGrpCombine(void *cdata, int len)
+{
+	int grps, en;
+
+	ip1811drv_dbg("ip1811: +setTrunkGrpCombine...\n");
+	if (sizeof(struct TrunkCombineSetting) != len)
+		return -EINVAL;
+
+	grps=((struct TrunkCombineSetting *)cdata) ->tgrps;
+	en = ((struct TrunkCombineSetting *)cdata) ->cen;
+
+	if(switchdSetTrunkGrpCombine(grps, en) != 0)
+		return -EINVAL;
+
+	ip1811drv_dbg("ip1811: -setTrunkGrpCombine...\n");
+	return 0;
+}
+
+int switchdGetTrunkGrpCombine(int grps, int *ptrInt)
+{
+	if (grps < OP_TRUNK_COMBINE_G1_G2 || grps > OP_TRUNK_COMBINE_G3_G4)
+		return -EINVAL;
+	ip1811drv_dbg("grps=%d\n", grps);
+	
+	*ptrInt = (int)_ReadRegBits(1, P1REG_TRUNKCFG, grps, 1);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetTrunkGrpCombine);
+int getTrunkGrpCombine(void *cdata, int len)
+{
+	int grps, en;
+
+	ip1811drv_dbg("ip1811: +getTrunkGrpCombine...\n");
+	if (sizeof(struct TrunkCombineSetting) != len)
+		return -EINVAL;
+
+	grps=((struct TrunkCombineSetting *)cdata) ->tgrps;
+
+	if(switchdGetTrunkGrpCombine(grps, &en) != 0)
+		return -EINVAL;
+
+	((struct TrunkCombineSetting *)cdata) ->cen = en;
+	ip1811drv_dbg("cdata ->cen=%d\n", ((struct TrunkCombineSetting *)cdata) ->cen);
+	ip1811drv_dbg("ip1811: -getTrunkGrpCombine...\n");
+	return 0;
+}
+
+//------------ MIB Counter functions:ip1811 ---------------------
+int switchdSetMibCounterEnable(int en)
+{
+	if( en!=OP_FUNC_ENABLE && en!=OP_FUNC_DISABLE ){
+		ip1811drv_err("Error: en=%X\n", en);
+		return -EINVAL;
+	}
+	_WriteRegBits(0, P0REG_MACBEHAVIOR, 9, 1, en);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetMibCounterEnable);
+
+int setMibCounterEnable(void *cdata, int len)
+{
+	int ret, en;
+	FUNC_MSG_IN;
+
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	en = ((struct GeneralSetting *)cdata) ->gdata;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", en);
+	ret = switchdSetMibCounterEnable(en);
+	
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdGetMibCounterEnable(int *gdata_p)
+{
+	*gdata_p = _ReadRegBits(0, P0REG_MACBEHAVIOR, 9, 1);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetMibCounterEnable);
+
+int getMibCounterEnable(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	ret = switchdGetMibCounterEnable(&(gs ->gdata));
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdGetMibCounterAll(void *uptr)
+{
+	int i, j, ret=0;
+	struct MIBCounterEntry_all *dptr;
+
+	dptr = kmalloc(sizeof(struct MIBCounterEntry_all), GFP_KERNEL);
+	if (!dptr) {
+		ret =  -ENOMEM;
+		goto out_mib_counter_all;
+	}
+	
+	IP2Page(0);
+	for(j=0; j<MAX_PHY_NUM; j++) {
+		for(i=0; i<NUM_MIB_COUNTER_RX; i++) {
+			//statistic counter read , read clear rx counter
+			Write_Reg(POREG_MIBCOUN_CMD, 0xC000|(u16)i|((u16)j<<5));
+			/* need to check does trigger bit has been put down */
+			while((Read_Reg(POREG_MIBCOUN_CMD) >> 15)&0x1);
+			
+			dptr ->entry[j].RX_counter[i] =  (u32)Read_Reg(POREG_MIBCOUN_DATA_L);
+			dptr ->entry[j].RX_counter[i] |= ((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16);
+		}
+		for(i=0; i<NUM_MIB_COUNTER_TX; i++) {
+			//statistic counter read , read clear tx counter
+			Write_Reg(POREG_MIBCOUN_CMD,0xC400|(u16)i|((u16)j<<5));
+			/* need to check does trigger bit has been put down */
+			while((Read_Reg(POREG_MIBCOUN_CMD) >> 15)&0x1);
+			
+			dptr ->entry[j].TX_counter[i] =  (u32)Read_Reg(POREG_MIBCOUN_DATA_L);
+			dptr ->entry[j].TX_counter[i] |= ((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16);
+		}
+	}
+	if (copy_to_user(uptr, dptr, sizeof(struct MIBCounterEntry_all))) {
+		ret = -EFAULT;
+		goto out_mib_counter_all;
+	}
+out_mib_counter_all:
+	if(dptr){ 
+		kfree(dptr);
+	}
+	return (ret < 0) ? ret : 0;
+}
+EXPORT_SYMBOL(switchdGetMibCounterAll);
+
+int getMibCounterAll(void *cdata, int len)
+{
+	int ret;
+	void *uptr;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	uptr = (void *)(((struct GeneralSetting *)cdata) ->gdata);
+	ret = switchdGetMibCounterAll(uptr);
+
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdGetMibCounterByPort(void *uptr, int port)
+{
+	int i, ret;
+	struct MIBCounterEntry *dptr;
+	
+	dptr = kmalloc(sizeof(struct MIBCounterEntry), GFP_KERNEL);
+	if (!dptr) {
+		ret = -ENOMEM;
+		goto out_mib_counter;
+	}
+	IP2Page(0);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	for(i=0; i<NUM_MIB_COUNTER_RX; i++) {
+		//statistic counter read , read clear rx counter
+		Write_Reg(POREG_MIBCOUN_CMD, 0xC000|(u16)i|((u16)port<<5));
+		/* need to check does trigger bit has been put down */
+		while((Read_Reg(POREG_MIBCOUN_CMD) >> 15)&0x1);
+		dptr ->RX_counter[i] = (u32)(((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16)|Read_Reg(POREG_MIBCOUN_DATA_L));
+	}
+	for(i=0; i<NUM_MIB_COUNTER_TX; i++) {
+		//statistic counter read , read clear tx counter
+		Write_Reg(POREG_MIBCOUN_CMD, 0xC400|(u16)i|((u16)port<<5));
+		/* need to check does trigger bit has been put down */
+		while((Read_Reg(POREG_MIBCOUN_CMD) >> 15)&0x1);
+		dptr ->TX_counter[i] = (u32)(((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16)|Read_Reg(POREG_MIBCOUN_DATA_L));
+	}
+	if (copy_to_user(uptr, dptr, sizeof(struct MIBCounterEntry))) {
+		ret = -EFAULT;
+		goto out_mib_counter;
+	}
+out_mib_counter:
+	if(dptr) { 
+		kfree(dptr);
+	}
+
+	return (ret < 0) ? ret : 0;
+}
+EXPORT_SYMBOL(switchdGetMibCounterByPort);
+
+int getMibCounterByPort(void *cdata, int len)
+{
+	int port, ret;
+	void *uptr;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	uptr = (void *)(((struct ByPortSetting *)cdata) ->pdata);
+	port = ((struct ByPortSetting *)cdata) ->port;
+	
+	ret = switchdGetMibCounterByPort(uptr, port);
+	
+	FUNC_MSG_OUT;
+	return ret;
+}
+
+int switchdGetMibCounterByItem(int port, int is_tx, int idx, unsigned long *cnt)
+{
+	IP2Page(0);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	//statistic counter read , read clear rx counter
+	Write_Reg(POREG_MIBCOUN_CMD, (is_tx?0xC400:0xC000)|(u16)idx|((u16)port<<5));
+	/* need to check does trigger bit has been put down */
+	while((Read_Reg(POREG_MIBCOUN_CMD) >> 15)&0x1);
+
+	*cnt = (u32)(((u32)Read_Reg(POREG_MIBCOUN_DATA_H)<<16)|Read_Reg(POREG_MIBCOUN_DATA_L));
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetMibCounterByItem);
+
+int getMibCounterByItem(void *cdata, int len)
+{
+	int port, dir, idx, ret;
+	unsigned long mibcnt;
+	struct MIBCounterData *mcd = (struct MIBCounterData *)cdata;
+
+	FUNC_MSG_IN;
+
+	if (sizeof(struct MIBCounterData) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	port = mcd ->port;
+	dir = mcd ->dir;
+	idx = mcd ->idx;
+
+	ret = switchdGetMibCounterByItem(port, dir, idx, &mibcnt);
+	mcd ->counter = mibcnt; 
+
+	FUNC_MSG_OUT;
+	return ret;
+
+}
+
+//------------ MIB Counter functions:ip1811 end------------------
+//------------ QOS functions:ip1811 -----------------------------
+int setQOSAgingFunction(void *cdata, int len)
+{
+	int port,aging;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	port=((struct ByPortSetting *)cdata) ->port;
+	aging =((struct ByPortSetting *)cdata) ->pdata;
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+
+	if (aging < 0 || aging > 0xff)
+		return -EINVAL;
+
+	_WriteRegBits(8, P8REG_QOSPORTAGINGEN0+(port/2), (port%2)*8, 8, aging);
+#ifdef COMBINED_PORT
+	if (port==9){
+		_WriteRegBits(8, P8REG_QOSPORTAGINGEN0+((port+1)/2), ((port+1)%2)*8, 8, aging);
+	}
+#endif
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSAgingFunction(void *cdata, int len)
+{
+	int port;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	port=((struct ByPortSetting *)cdata) ->port;
+	if (port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	((struct ByPortSetting *)cdata) ->pdata=(u32)_ReadRegBits(8,P8REG_QOSPORTAGINGEN0+(port/2),(port%2)*8,8);
+
+	FUNC_MSG_OUT;
+	ip1811drv_dbg("cdata ->pdata=%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	return 0;
+}
+int setQOSAgingTime(void *cdata, int len)
+{
+	int aging;
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	aging = ((struct GeneralSetting *)cdata) ->gdata;
+	if (aging < 0 || aging > 0xff)
+		return -EINVAL;
+
+	_WriteRegBits(8, P8REG_QOSAGINGTIME, 0, 8, aging);
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSAgingTime(void *cdata, int len)
+{
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	((struct GeneralSetting *)cdata) ->gdata = (u16)_ReadRegBits(8, P8REG_QOSAGINGTIME, 0, 8);
+
+	FUNC_MSG_OUT;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	return 0;
+}
+int setQOSFastAging(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 8, P8REG_QOSAGINGTIME, 8);
+	FUNC_MSG_OUT;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	return ret;
+}
+int getQOSFastAging(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 8, P8REG_QOSAGINGTIME, 8);
+	FUNC_MSG_OUT;
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	return ret;
+}
+int setCOSIGMP(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COSIGMPBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSIGMP(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COSIGMPBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOSMACAddress(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COSMACBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSMACAddress(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COSMACBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOSVID(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COSVIDBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSVID(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COSVIDBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOSTCPUDPPort(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COSTCPUDPBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSTCPUDPPort(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COSTCPUDPBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOSDSCP(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COSDSCPBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSDSCP(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COSDSCPBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOS8021P(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COS8021PBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOS8021P(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COS8021PBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOSPhsicalPort(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 0, P0REG_COSPORTBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSPhsicalPort(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 0, P0REG_COSPORTBASEPRIEN);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setCOSPortQueue(void *cdata, int len)
+{
+	int port;
+	u8 queue;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	port = ((struct ByPortSetting *)cdata) ->port;
+	queue = ((struct ByPortSetting *)cdata) ->pdata;
+
+	if ((port < 0) || (port >= MAX_PHY_NUM))
+	{
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+	if(queue>7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+	
+	_WriteRegBits(0, P0REG_COSPORTBASEQUEUE0+(port/5), (port%5)*3, 3, queue);
+#ifdef COMBINED_PORT
+	if (port==9)
+		_WriteRegBits(0, P0REG_COSPORTBASEQUEUE0+((port+1)/5), ((port+1)%5)*3, 3, queue);
+#endif
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getCOSPortQueue(void *cdata, int len)
+{
+	int port;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting *)cdata) ->port;
+	if ((port < 0) || (port >= MAX_PHY_NUM))
+	{
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+	
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	((struct ByPortSetting *)cdata) ->pdata = (u16)_ReadRegBits(0, P0REG_COSPORTBASEQUEUE0+(port/5), (port%5)*3, 3);
+	ip1811drv_dbg("cdata ->pdata=0x%04X\n", ((struct ByPortSetting *)cdata) ->pdata);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int setCOS8021PEdtion(void *cdata, int len)
+{
+	int gdata;
+	u16 regdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	gdata = ((struct GeneralSetting *)cdata) ->gdata;
+	if( gdata != OP_QOS_8021PEDTION_2005 && gdata != OP_QOS_8021PEDTION_2005_EX && gdata != OP_QOS_8021PEDTION_EARLY )
+	{
+		ip1811drv_err("Error: gdata=%X\n", gdata);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", gdata);
+	IP2Page(0);
+	regdata = Read_Reg(P0REG_COS8021PBASEPRIEN);
+	regdata &= (u16)~0x6000;
+	switch(gdata)
+	{
+		case OP_QOS_8021PEDTION_2005:
+			break;
+		case OP_QOS_8021PEDTION_2005_EX:
+			regdata |= 0x4000;  break;
+		case OP_QOS_8021PEDTION_EARLY:
+			regdata |= 0x2000;  break;
+	}
+	Write_Reg(P0REG_COS8021PBASEPRIEN,regdata);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getCOS8021PEdtion(void *cdata, int len)
+{
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	u16dat =_ReadRegBits(0, P0REG_COS8021PBASEPRIEN, 13, 2);
+
+	if(u16dat&0x1)
+	{ ((struct GeneralSetting *)cdata) ->gdata = OP_QOS_8021PEDTION_EARLY; }
+	else
+	{
+		if(u16dat&0x2)
+		{ ((struct GeneralSetting *)cdata) ->gdata = OP_QOS_8021PEDTION_2005_EX; }
+		else
+		{ ((struct GeneralSetting *)cdata) ->gdata = OP_QOS_8021PEDTION_2005; }
+	}
+	ip1811drv_dbg("cdata ->gdata=0x%08x\n", ((struct GeneralSetting *)cdata) ->gdata);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int setCOSDSCPBaseDSCP(void *cdata, int len)
+{
+	u8 entryno,value,queue;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_dscp_setting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+
+	entryno = ((struct qos_dscp_setting *)cdata) ->dscpentry;
+	value = ((struct qos_dscp_setting *)cdata) ->dscpvalue;
+	queue = ((struct qos_dscp_setting *)cdata) ->dscpqueue;
+
+	if(entryno<1 || entryno>8)
+	{
+		ip1811drv_err("Error: entryno=%d\n", entryno);
+		return -EINVAL;
+	}
+	if(value & ~0x3f)
+	{
+		ip1811drv_err("Error: value=%X\n", value);
+		return -EINVAL;
+	}
+	if(queue>7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+
+	entryno-=1;
+
+	_WriteRegBits(0, P0REG_COSDSCPVALUE0+(entryno/2), (entryno%2)*6, 6, value);
+	_WriteRegBits(0, P0REG_COSDSCPPRISETTING0+(entryno/5), (entryno%5)*3, 3, queue);
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getCOSDSCPBaseDSCP(void *cdata, int len)
+{
+	u8 entryno;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_dscp_setting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	entryno = ((struct qos_dscp_setting *)cdata) ->dscpentry;
+	if(entryno>7)
+	{
+		ip1811drv_err("Error: entryno=%d\n", entryno);
+		return -EINVAL;
+	}
+	((struct qos_dscp_setting *)cdata) ->dscpvalue = (u16)_ReadRegBits(0, P0REG_COSDSCPVALUE0+(entryno/2), (entryno%2)*5, 6);
+	((struct qos_dscp_setting *)cdata) ->dscpqueue = (u16)_ReadRegBits(0, P0REG_COSDSCPPRISETTING0+(entryno/5), (entryno%5)*3, 3);
+	ip1811drv_dbg("cdata ->dscpvalue=0x%04X\n", ((struct qos_dscp_setting *)cdata) ->dscpvalue);
+	ip1811drv_dbg("cdata ->dscpqueue=0x%04X\n", ((struct qos_dscp_setting *)cdata) ->dscpqueue);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+int setCOSDSCPBaseNoMatchAction(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0, P0REG_COSDSCPPRISETTING1, 9);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getCOSDSCPBaseNoMatchAction(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0, P0REG_COSDSCPPRISETTING1, 9);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setQOSmodeGroupMember(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 8, P8REG_QOSGROUPSEL);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getQOSmodeGroupMember(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 8, P8REG_QOSGROUPSEL);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setQOSGroupBEn(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP2, 9);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getQOSGroupBEn(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP2, 9);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setQOSMode(void *cdata, int len)
+{
+	int gpnum,mode;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	mode = ((struct qos_modesettings *)cdata) ->modesettings;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	if(mode<OP_QOS_MODE_FIFO || mode>OP_QOS_MODE_SP8)
+	{
+		ip1811drv_err("Error: mode=%d\n", mode);
+		return -EINVAL;
+	}
+	_WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 0, 3, mode);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSMode(void *cdata, int len)
+{
+	int gpnum;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+
+	((struct qos_modesettings *)cdata) ->modesettings= (int)_ReadRegBits(8,(gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 0, 3);
+
+	ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum);
+	ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+int setQOSMethod(void *cdata, int len)
+{
+	int gpnum,mode;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	mode = ((struct qos_modesettings *)cdata) ->modesettings;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	if(mode<OP_QOS_METHOD_WRR || mode>OP_QOS_METHOD_TWRR)
+	{
+		ip1811drv_err("Error: mode=%d\n", mode);
+		return -EINVAL;
+	}
+	IP2Page(8);
+
+	u16dat = Read_Reg((gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2);
+	u16dat &= 0xFF9F;
+	switch(mode)
+	{
+		case OP_QOS_METHOD_WRR:
+			break;
+		case OP_QOS_METHOD_BW:
+			u16dat |= ((u16)0x1<<5);
+			break;
+		case OP_QOS_METHOD_WFQ:
+			u16dat |= ((u16)0x2<<5);
+			break;
+		case OP_QOS_METHOD_TWRR:
+			u16dat |= ((u16)0x3<<5);
+			break;
+	}
+	Write_Reg((gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2,u16dat);
+
+
+	if(mode==OP_QOS_METHOD_BW)
+		Write_Reg(P8REG_QOSMODESELGROUP1,Read_Reg(P8REG_QOSMODESELGROUP1)|0x8000);//stop & hold pkt
+	else
+		Write_Reg(P8REG_QOSMODESELGROUP1,Read_Reg(P8REG_QOSMODESELGROUP1)&0x7FFF);
+
+	ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum);
+	ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings);
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSMethod(void *cdata, int len)
+{
+	int gpnum;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+
+	u16dat = _ReadRegBits(8, (gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 5, 3);
+
+	((struct qos_modesettings *)cdata) ->modesettings = u16dat;
+
+	ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum);
+	ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings);
+	FUNC_MSG_OUT;
+	return 0;
+}
+int setQOSWeight(void *cdata, int len)
+{
+	int gpnum,mode,queue;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	queue = ((struct qos_modesettings *)cdata) ->queuenum;
+	mode = ((struct qos_modesettings *)cdata) ->modesettings;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	if(queue<OP_QOS_NUM_Q0 || queue>OP_QOS_NUM_Q7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+	if(mode & ~(int)0xff)
+	{
+		ip1811drv_err("Error: mode=%d\n", mode);
+		return -EINVAL;
+	}
+
+	_WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_WEIGHT0+(queue/2)):(P8REG_QOSGP2_WEIGHT0+(queue/2)), (queue%2)*8, 8, mode);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSWeight(void *cdata, int len)
+{
+	int gpnum,queue;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	queue = ((struct qos_modesettings *)cdata) ->queuenum;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	u16dat = _ReadRegBits(8,(gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_WEIGHT0+(queue/2)):(P8REG_QOSGP2_WEIGHT0+(queue/2)), ((queue%2)*8), 8);
+
+	((struct qos_modesettings *)cdata) ->modesettings=(int)u16dat;
+
+	ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum);
+	ip1811drv_dbg("cdata ->queuenum=0x%04X\n", ((struct qos_modesettings *)cdata) ->queuenum);
+	ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+int setQOSMaxBandwidth(void *cdata, int len)
+{
+	int gpnum,mode,queue;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	queue = ((struct qos_modesettings *)cdata) ->queuenum;
+	mode = ((struct qos_modesettings *)cdata) ->modesettings;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	if(queue<OP_QOS_NUM_Q0 || queue>OP_QOS_NUM_Q7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+	if(mode & ~(int)0xff)
+	{
+		ip1811drv_err("Error: mode=%d\n", mode);
+		return -EINVAL;
+	}
+
+	_WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_MAXBDWT0+(queue/2)):(P8REG_QOSGP2_MAXBDWT0+(queue/2)), (queue%2)*8, 8, mode);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getQOSMaxBandwidth(void *cdata, int len)
+{
+	int gpnum,queue;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	queue = ((struct qos_modesettings *)cdata) ->queuenum;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	if(queue<OP_QOS_NUM_Q0 || queue>OP_QOS_NUM_Q7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+
+	u16dat = _ReadRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSGP1_MAXBDWT0+(queue/2)):(P8REG_QOSGP2_MAXBDWT0+(queue/2)), ((queue%2)*8), 8);
+
+	((struct qos_modesettings *)cdata) ->modesettings=(int)u16dat;
+
+	ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum);
+	ip1811drv_dbg("cdata ->queuenum=0x%04X\n", ((struct qos_modesettings *)cdata) ->queuenum);
+	ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+int setQOSUnit(void *cdata, int len)
+{
+	int gpnum,mode;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	mode = ((struct qos_modesettings *)cdata) ->modesettings;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+	if(mode<OP_QOS_UNIT_64KBS || mode>OP_QOS_UNIT_4MBS)
+	{
+		ip1811drv_err("Error: mode=%d\n", mode);
+		return -EINVAL;
+	}
+	_WriteRegBits(8, (gpnum==OP_QOS_GROUP1)?(P8REG_QOSMODESELGROUP1):(P8REG_QOSMODESELGROUP2), 3, 2, mode);
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSUnit(void *cdata, int len)
+{
+	int gpnum;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_modesettings) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	gpnum = ((struct qos_modesettings *)cdata) ->groupnum;
+	if(gpnum!=OP_QOS_GROUP1 && gpnum!=OP_QOS_GROUP2)
+	{
+		ip1811drv_err("Error: gpnum=%d\n", gpnum);
+		return -EINVAL;
+	}
+
+	((struct qos_modesettings *)cdata) ->modesettings= (int)_ReadRegBits(8,(gpnum==OP_QOS_GROUP1)?P8REG_QOSMODESELGROUP1:P8REG_QOSMODESELGROUP2, 3, 2);
+
+	ip1811drv_dbg("cdata ->groupnum=0x%04X\n", ((struct qos_modesettings *)cdata) ->groupnum);
+	ip1811drv_dbg("cdata ->modesettings=0x%04X\n", ((struct qos_modesettings *)cdata) ->modesettings);
+	FUNC_MSG_OUT;
+	return 0;
+}
+int setQOSRatioValue0Def(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP1, 15);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int getQOSRatioValue0Def(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 8, P8REG_QOSMODESELGROUP1, 15);
+	FUNC_MSG_OUT;
+	return ret;
+}
+int setQOSSBMDBM(void *cdata, int len)
+{
+	int port,mode;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting *)cdata) ->port;
+	mode = ((struct ByPortSetting *)cdata) ->pdata;
+	if(port < 0 || port >= MAX_PHY_NUM)
+		return -EINVAL;
+	if(mode!=OP_QOS_QBASE_DBM && mode!=OP_QOS_QBASE_SBM)
+	{
+		ip1811drv_err("Error: mode=%d\n", mode);
+		return -EINVAL;
+	}
+	ip1811drv_dbg(" port=%d\n", port);
+	ip1811drv_dbg(" mode=%d\n", mode);
+
+	IP2Page(8);
+
+	// set all queue(per port) to same mode
+	u16dat=Read_Reg(P8REG_QOS_SBMDBMSEL0+(port/2));
+	u16dat&=((port%2)?0x00FF:0xFF00);
+	if(mode==OP_QOS_QBASE_SBM)
+	{ u16dat|=((port%2)?0xFF00:0x00FF); }
+	Write_Reg(P8REG_QOS_SBMDBMSEL0+(port/2),u16dat);
+#ifdef COMBINED_PORT
+	if (port==9){
+		u16dat=Read_Reg(P8REG_QOS_SBMDBMSEL0+((port+1)/2));
+		u16dat&=(((port+1)%2)?0x00FF:0xFF00);
+		if(mode==OP_QOS_QBASE_SBM)
+		{ u16dat|=(((port+1)%2)?0xFF00:0x00FF); }
+		Write_Reg(P8REG_QOS_SBMDBMSEL0+((port+1)/2),u16dat);
+	}
+#endif
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSSBMDBM(void *cdata, int len)
+{
+	int port;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting *)cdata) ->port;
+	if(port<0 || port>=MAX_PHY_NUM)
+		return -EINVAL;
+	
+	IP2Page(8);
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	u16dat=Read_Reg(P8REG_QOS_SBMDBMSEL0+(port/2));
+	u16dat>>=((port%2)*8);
+	if(u16dat&0xff)
+	{ ((struct ByPortSetting *)cdata) ->pdata=OP_QOS_QBASE_SBM;  }
+	else
+	{ ((struct ByPortSetting *)cdata) ->pdata=OP_QOS_QBASE_DBM;  }
+
+	ip1811drv_dbg("cdata ->port=0x%d\n", ((struct ByPortSetting *)cdata) ->port);
+	ip1811drv_dbg("cdata ->pdata=0x%d\n", ((struct ByPortSetting *)cdata) ->pdata);
+	FUNC_MSG_OUT;
+
+	return 0;
+}
+int setQOSDBMEn(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _setPortmap(cdata, len, 8, P8REG_QOSQUEUEDBMEN);
+	FUNC_MSG_IN;
+	return ret;
+}
+int getQOSDBMEn(void *cdata, int len)
+{
+	int ret;
+	FUNC_MSG_IN;
+	ret = _getPortmap(cdata, len, 8, P8REG_QOSQUEUEDBMEN);
+	FUNC_MSG_IN;
+	return ret;
+}
+int setQOSRemap(void *cdata, int len)
+{
+	int port;
+	u8 queue,remap;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_remap) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct qos_remap *)cdata) ->port;
+	queue = ((struct qos_remap *)cdata) ->queue;
+	remap = ((struct qos_remap *)cdata) ->remap;
+
+	if(port<0 || port>=MAX_PHY_NUM)
+		return -EINVAL;
+	if(queue>OP_QOS_REMAP_TX_Q7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+	if(remap>7)
+	{
+		ip1811drv_err("Error: remap=%d\n", remap);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("cdata ->port=0x%d\n", ((struct qos_remap *)cdata) ->port);
+	ip1811drv_dbg("cdata ->queue=0x%d\n", ((struct qos_remap *)cdata) ->queue);
+	ip1811drv_dbg("cdata ->remap=0x%d\n", ((struct qos_remap *)cdata) ->remap);
+	
+	if(queue<=OP_QOS_REMAP_RX_Q7)//RX
+	{
+		if ((queue/5) == 0)
+		{
+			IP2Page(6);
+			u16dat = Read_Reg(P6REG_QOS_REMAP_RX0+(port*2)+1);
+		}
+		_WriteRegBits(6, P6REG_QOS_REMAP_RX0+(port*2)+(queue/5), (queue%5)*3, 3, remap);
+		if ((queue/5) == 0)
+		{
+			IP2Page(6);
+			Write_Reg(P6REG_QOS_REMAP_RX0+(port*2)+1, u16dat);
+		}
+#ifdef COMBINED_PORT
+		if (port==9)
+		{
+			if ((queue/5) == 0)
+			{
+				IP2Page(6);
+				u16dat = Read_Reg(P6REG_QOS_REMAP_RX0+((port+1)*2)+1);
+			}
+			_WriteRegBits(6, P6REG_QOS_REMAP_RX0+((port+1)*2)+(queue/5), (queue%5)*3, 3, remap);
+			if ((queue/5) == 0)
+			{
+				IP2Page(6);
+				Write_Reg(P6REG_QOS_REMAP_RX0+((port+1)*2)+1, u16dat);
+			}
+		}
+#endif
+	}
+	else//TX
+	{
+		queue-=8;
+		if (port == 0)
+		{
+			_WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5), (queue%5)*3, 3, remap);
+		}
+		else if (port == 1)
+		{
+			if (queue / 5)
+				_WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1, (queue%5)*3, 3, remap);
+			else
+				_WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5), (queue%5)*3, 3, remap);
+		}
+		else
+		{
+			_WriteRegBits(8, P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1, (queue%5)*3, 3, remap);
+#ifdef COMBINED_PORT
+			if (port==9)
+				_WriteRegBits(8, P8REG_QOS_REMAP_TX0+((port+1)*2)+(queue/5)+1, (queue%5)*3, 3, remap);
+#endif
+		}
+	}
+	FUNC_MSG_OUT;
+	return 0;
+}
+int getQOSRemap(void *cdata, int len)
+{
+	int port;
+	u8 queue;
+	u16 u16dat;
+	FUNC_MSG_IN;
+	if (sizeof(struct qos_remap) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct qos_remap *)cdata) ->port;
+	queue = ((struct qos_remap *)cdata) ->queue;
+	if(port<0 || port>=MAX_PHY_NUM)
+		return -EINVAL;
+	if(queue>OP_QOS_REMAP_TX_Q7)
+	{
+		ip1811drv_err("Error: queue=%d\n", queue);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("cdata ->port=0x%d\n", ((struct qos_remap *)cdata) ->port);
+	ip1811drv_dbg("cdata ->queue=0x%d\n", ((struct qos_remap *)cdata) ->queue);
+	
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	if(queue<=OP_QOS_REMAP_RX_Q7)//RX
+	{
+		IP2Page(6);
+		u16dat = Read_Reg(P6REG_QOS_REMAP_RX0+(port*2)+(queue/5));
+	}
+	else//TX
+	{
+		queue-=8;
+		IP2Page(8);
+		if (port == 0)
+		{
+			u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5));
+		}
+		else if (port == 1)
+		{
+			if (queue / 5)
+				u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1);
+			else
+				u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5));
+		}
+		else
+		{
+			u16dat = Read_Reg(P8REG_QOS_REMAP_TX0+(port*2)+(queue/5)+1);
+		}
+	}
+	((struct qos_remap *)cdata) ->remap = (u8)((u16dat>>((queue%5)*3))&0x7);
+
+	ip1811drv_dbg("cdata ->remap=0x%d\n", ((struct qos_remap *)cdata) ->remap);
+	FUNC_MSG_OUT;
+	return 0;
+}
+//------------ QOS functions:ip1811 end--------------------------
+
+//------------ ACL functions:common ----------------------------
+struct acl_man	*m_acl;	// acl golbal manage variable
+int acl_write_table_0010(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_0100(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_0101(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_0110(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_0111(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_1x00(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_1x01(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_1x10(int block, int index, int link, struct acl_rule *r);
+int acl_write_table_1x11(int block, int index, int link, struct acl_rule *r);
+int (*acl_write_table_rule[])(int block, int index, int link, struct acl_rule *r) = {
+	NULL,
+	acl_write_table_0010,
+	NULL,
+	acl_write_table_0100,
+	acl_write_table_0101,
+	acl_write_table_0110,
+	acl_write_table_0111,
+	acl_write_table_1x00,
+	acl_write_table_1x01,
+	acl_write_table_1x10,
+	acl_write_table_1x11
+};
+int acl_write_table_drop(int block, int index, int is_link, struct acl_rule *r);
+int acl_write_table_a1(int block, int index, int is_link, struct acl_rule *r);
+int acl_write_table_a2(int block, int index, int is_link, struct acl_rule *r);
+int acl_write_table_a3(int block, int index, int is_link, struct acl_rule *r);
+int (*acl_write_table_act[])(int block, int index, int is_link, struct acl_rule *r) = {
+	acl_write_table_drop,
+	acl_write_table_a1,
+	acl_write_table_a2,
+	acl_write_table_a3
+};
+
+int set_rule_index_remap(void);
+
+void acl_init(void)
+{
+	int i;
+	ip1811drv_dbg("<DBG_DR_ACL> acl_init()\n");
+
+	m_acl = kmalloc(sizeof(struct acl_man), GFP_KERNEL);
+	if(m_acl == NULL)
+	{
+		ip1811drv_err("Error: acl_init() acl_man malloc failed.\n");
+		return;
+	}
+
+	INIT_LIST_HEAD(&m_acl ->rule_list);
+	m_acl ->num_used_rules = 0;
+	m_acl ->num_used_entries = 0;
+	for(i=0; i<4; i++)
+	{
+		m_acl ->used_entry_mask[i] = 0;
+	}
+}
+
+int acl_find_index(int num, int *block, int *index, int find_idx_blockn, int find_idx_rvs)
+{
+	int i=0, j=0;
+	unsigned char m = 0;
+	unsigned long t = 0;
+
+	for(i=0; i<num; i++) {
+		m |= BIT(i);
+	}
+
+	for(i=0; i<4; i++) {
+		t = (unsigned long)m_acl ->used_entry_mask[(find_idx_blockn+i)%4];
+		if(find_idx_rvs) { // find index in reverse
+			for(j=15; j>=0; j--) {
+				if((16-j) < num) // empty entry is not enough, find next block
+					break;
+				if(!((t>>j) & m)) {
+					*block = (i+find_idx_blockn)%4;
+					*index = j;
+					return 0;
+				}
+			}
+		} else {
+			for(j=0; j<16; j++) {
+				if((16-j) < num) // empty entry is not enough, find next block
+					break;
+				if(!((t>>j) & m)) {
+					*block = (i+find_idx_blockn)%4;
+					*index = j;
+					return 0;
+				}
+			}
+		}
+	}
+
+	return -ENOMEM;
+}
+
+int acl_clean_table_rule(int block, int index)
+{
+	IP2Page(1);
+
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_clean_table_act(int block, int index)
+{
+	IP2Page(1);
+
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0);
+
+	// act
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5));
+	return 0;
+}
+
+int acl_clean_table(int block, int index)
+{
+	acl_clean_table_rule(block, index);
+	acl_clean_table_act(block, index);
+	return 0;
+}
+
+int acl_write_table_0010(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp=0;
+
+	IP2Page(1);
+
+	/* Set user define location D3 and D4 */
+	if(r->location1)
+		Write_Reg(P1REG_ACL_PATTEM_LOCATION_D3, r->location1);
+	if(r->location2)
+		Write_Reg(P1REG_ACL_PATTEM_LOCATION_D4, r->location2);
+
+	/* E1 ~ E8 */
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->usr0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, r->mask0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->usr1);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->mask1);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->usr2);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->mask2);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, r->usr3);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, r->mask3);
+
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT) {
+		tmp |= r->ingress_port+1;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+
+	//EA
+	tmp=ACL_SELECT_MODE_0010<<6;
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+
+int acl_write_table_0100(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+
+	IP2Page(1);
+	//E1 & E2
+	if(r->rule_valid & ACL_RULE_VALID_SIP)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip4_addr&0xFFFF);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->sip4_addr>>16)&0xFFFF);
+		tmp |= ((u16)(r->sip_mask&0xF)<<7);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+		tmp |= (0xF<<7);		// any sip
+	}
+	//E3 & E4
+	if(r->rule_valid & ACL_RULE_VALID_DP_R)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->dp_lo);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->dp_hi);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+		tmp |= BIT(5);
+	}
+	//E5 & E6
+	if(r->rule_valid & ACL_RULE_VALID_SP_R)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->sp_lo);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->sp_hi);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+		tmp |= BIT(6);
+	}
+	//E7
+	if(r->rule_valid & ACL_RULE_VALID_VLAN)
+	{
+		if(r->rule_valid & ACL_RULE_VALID_COS)
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12)));
+		}
+		else
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000));
+		}
+	}
+	else
+	{
+		tmp |= (0x3<<11);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000);
+	}
+	//E8
+	tmp |= (0x3<<13);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0x8000);
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SIP) {
+		tmp |= 0x8000;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_0100<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_DP_R) {
+		tmp |= 0x1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SP_R) {
+		tmp |= 0x2;
+	}
+	if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) {
+		tmp |= 0x4;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_0101(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+
+	IP2Page(1);
+	//E1 & E2
+	if(r->rule_valid & ACL_RULE_VALID_DIP)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip4_addr&0xFFFF);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->dip4_addr>>16)&0xFFFF);
+		tmp |= ((u16)(r->dip_mask&0xF)<<7);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+		tmp |= (0xF<<7);		// any dip
+	}
+	//E3 & E4
+	if(r->rule_valid & ACL_RULE_VALID_DP_R)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->dp_lo);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->dp_hi);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+		tmp |= BIT(5);
+	}
+	//E5 & E6
+	if(r->rule_valid & ACL_RULE_VALID_SP_R)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->sp_lo);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->sp_hi);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+		tmp |= BIT(6);
+	}
+	//E7
+	if(r->rule_valid & ACL_RULE_VALID_VLAN)
+	{
+		if(r->rule_valid & ACL_RULE_VALID_COS)
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12)));
+		}
+		else
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000));
+		}
+	}
+	else
+	{
+		tmp |= (0x3<<11);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000);
+	}
+	//E8
+	tmp |= (0x3<<13);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0x8000);
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_DIP) {
+		tmp |= 0x8000;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_0101<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_DP_R) {
+		tmp |= 0x1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SP_R) {
+		tmp |= 0x2;
+	}
+	if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) {
+		tmp |= 0x4;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_0110(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+
+	IP2Page(1);
+	//E1 ~ E8
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip6_addr16[7]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, r->sip6_addr16[6]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->sip6_addr16[5]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->sip6_addr16[4]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->sip6_addr16[3]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->sip6_addr16[2]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, r->sip6_addr16[1]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, r->sip6_addr16[0]);
+	//E9
+	tmp |= ((u16)(r->sip_mask&0x3FF)<<5);
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_0110<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_0111(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+
+	IP2Page(1);
+	//E1 ~ E8
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip6_addr16[7]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, r->dip6_addr16[6]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->dip6_addr16[5]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, r->dip6_addr16[4]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, r->dip6_addr16[3]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, r->dip6_addr16[2]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, r->dip6_addr16[1]);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, r->dip6_addr16[0]);
+	//E9
+	tmp |= ((u16)(r->dip_mask&0x3FF)<<5);
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_0111<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_1x00(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp=0, tmp2=0;
+
+	IP2Page(1);
+	//E1 & E2
+	if(r->rule_valid & ACL_RULE_VALID_SIP)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip4_addr&0xFFFF);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->sip4_addr>>16)&0xFFFF);
+		tmp |= ((u16)(r->sip_mask&0xF)<<7);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+		tmp |= (0xF<<7);		// any sip
+	}
+	//E3
+	if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+		tmp |= BIT(5);
+	}
+	//E4 ~ E6
+	if(r->rule_valid & ACL_RULE_VALID_SMAC)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->smac[4]&0xFF)<<8) | ((u16)(r->smac[5]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->smac[2]&0xFF)<<8) | ((u16)(r->smac[3]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->smac[0]&0xFF)<<8) | ((u16)(r->smac[1]&0xFF)));
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+		tmp |= (0x1<<6);		// any smac
+	}
+	//E7
+	if(r->rule_valid & ACL_RULE_VALID_VLAN)
+	{
+		if(r->rule_valid & ACL_RULE_VALID_COS)
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12)));
+		}
+		else
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000));
+		}
+	}
+	else
+	{
+		tmp |= (0x3<<11);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000);
+	}
+	//E8
+	// ip_proto
+	if(r->rule_valid & ACL_RULE_VALID_IP_PROT)
+	{
+		tmp2 |= ((u16)r->ip_prot&0xFF);
+	}
+	else
+	{
+		tmp |= BIT(13);		// any ip_prot
+	}
+	// dscp
+	if(r->rule_valid & ACL_RULE_VALID_DSCP)
+	{
+		tmp2 |= ((u16)(r->r_dscp&0x3F)<<10);
+	}
+	else
+	{
+		tmp |= BIT(14);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2);
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SIP) {
+		tmp |= 0x8000;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_1x00<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) {
+		tmp |= 0x1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SMAC) {
+		tmp |= 0x2;
+	}
+	if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) {
+		tmp |= 0x4;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_1x01(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp=0, tmp2=0;
+
+	IP2Page(1);
+	//E1 & E2
+	if(r->rule_valid & ACL_RULE_VALID_DIP)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip4_addr&0xFFFF);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->dip4_addr>>16)&0xFFFF);
+		tmp |= ((u16)(r->dip_mask&0xF)<<7);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+		tmp |= (0xF<<7);		// any dip
+	}
+	//E3
+	if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+		tmp |= BIT(5);
+	}
+	//E4 ~ E6
+	if(r->rule_valid & ACL_RULE_VALID_SMAC)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->smac[4]&0xFF)<<8) | ((u16)(r->smac[5]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->smac[2]&0xFF)<<8) | ((u16)(r->smac[3]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->smac[0]&0xFF)<<8) | ((u16)(r->smac[1]&0xFF)));
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+		tmp |= (0x1<<6);		// any smac
+	}
+	//E7
+	if(r->rule_valid & ACL_RULE_VALID_VLAN)
+	{
+		if(r->rule_valid & ACL_RULE_VALID_COS)
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12)));
+		}
+		else
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000));
+		}
+	}
+	else
+	{
+		tmp |= (0x3<<11);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000);
+	}
+	//E8
+	// ip_proto
+	if(r->rule_valid & ACL_RULE_VALID_IP_PROT)
+	{
+		tmp2 |= ((u16)r->ip_prot&0xFF);
+	}
+	else
+	{
+		tmp |= BIT(13);		// any ip_prot
+	}
+	// dscp
+	if(r->rule_valid & ACL_RULE_VALID_DSCP)
+	{
+		tmp2 |= ((u16)(r->r_dscp&0x3F)<<10);
+	}
+	else
+	{
+		tmp |= BIT(14);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2);
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_DIP) {
+		tmp |= 0x8000;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_1x01<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) {
+		tmp |= 0x1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SMAC) {
+		tmp |= 0x2;
+	}
+	if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) {
+		tmp |= 0x4;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_1x10(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp=0, tmp2=0;
+
+	IP2Page(1);
+	//E1 & E2
+	if(r->rule_valid & ACL_RULE_VALID_SIP)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->sip4_addr&0xFFFF);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->sip4_addr>>16)&0xFFFF);
+		tmp |= ((u16)(r->sip_mask&0xF)<<7);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+		tmp |= (0xF<<7);		// any sip
+	}
+	//E3
+	if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+		tmp |= BIT(5);
+	}
+	//E4 ~ E6
+	if(r->rule_valid & ACL_RULE_VALID_DMAC)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->dmac[4]&0xFF)<<8) | ((u16)(r->dmac[5]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->dmac[2]&0xFF)<<8) | ((u16)(r->dmac[3]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->dmac[0]&0xFF)<<8) | ((u16)(r->dmac[1]&0xFF)));
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+		tmp |= (0x1<<6);		// any dmac
+	}
+	//E7
+	if(r->rule_valid & ACL_RULE_VALID_VLAN)
+	{
+		if(r->rule_valid & ACL_RULE_VALID_COS)
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12)));
+		}
+		else
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000));
+		}
+	}
+	else
+	{
+		tmp |= (0x3<<11);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000);
+	}
+	//E8
+	// ip_proto
+	if(r->rule_valid & ACL_RULE_VALID_IP_PROT)
+	{
+		tmp2 |= ((u16)r->ip_prot&0xFF);
+	}
+	else
+	{
+		tmp |= BIT(13);		// any ip_prot
+	}
+	// dscp
+	if(r->rule_valid & ACL_RULE_VALID_DSCP)
+	{
+		tmp2 |= ((u16)(r->r_dscp&0x3F)<<10);
+	}
+	else
+	{
+		tmp |= BIT(14);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2);
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_SIP) {
+		tmp |= 0x8000;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_1x10<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) {
+		tmp |= 0x1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_DMAC) {
+		tmp |= 0x2;
+	}
+	if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) {
+		tmp |= 0x4;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_1x11(int block, int index, int link, struct acl_rule *r)
+{
+	u16 tmp=0, tmp2=0;
+
+	IP2Page(1);
+	//E1 & E2
+	if(r->rule_valid & ACL_RULE_VALID_DIP)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, r->dip4_addr&0xFFFF);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, (r->dip4_addr>>16)&0xFFFF);
+		tmp |= ((u16)(r->dip_mask&0xF)<<7);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+		tmp |= (0xF<<7);		// any dip
+	}
+	//E3
+	if(r->rule_valid & ACL_RULE_VALID_ETH_TYPE)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, r->eth_type);
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+		tmp |= BIT(5);
+	}
+	//E4 ~ E6
+	if(r->rule_valid & ACL_RULE_VALID_DMAC)
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, ((u16)(r->dmac[4]&0xFF)<<8) | ((u16)(r->dmac[5]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, ((u16)(r->dmac[2]&0xFF)<<8) | ((u16)(r->dmac[3]&0xFF)));
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, ((u16)(r->dmac[0]&0xFF)<<8) | ((u16)(r->dmac[1]&0xFF)));
+	}
+	else
+	{
+		Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+		tmp |= (0x1<<6);		// any dmac
+	}
+	//E7
+	if(r->rule_valid & ACL_RULE_VALID_VLAN)
+	{
+		if(r->rule_valid & ACL_RULE_VALID_COS)
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan | (r->cos<<12)));
+		}
+		else
+		{
+			Write_Reg(P1REG_ACL_TABLE_DATA_E7, (r->vlan|0x8000));
+		}
+	}
+	else
+	{
+		tmp |= (0x3<<11);
+		Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0x8000);
+	}
+	//E8
+	// ip_proto
+	if(r->rule_valid & ACL_RULE_VALID_IP_PROT)
+	{
+		tmp2 |= ((u16)r->ip_prot&0xFF);
+	}
+	else
+	{
+		tmp |= BIT(13);		// any ip_prot
+	}
+	// dscp
+	if(r->rule_valid & ACL_RULE_VALID_DSCP)
+	{
+		tmp2 |= ((u16)(r->r_dscp&0x3F)<<10);
+	}
+	else
+	{
+		tmp |= BIT(14);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, tmp2);
+	//E9
+	if(r->rule_valid & ACL_RULE_VALID_INGRESS_PORT)
+	{
+		tmp |= r->ingress_port+1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_DIP) {
+		tmp |= 0x8000;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, tmp);
+	//EA
+	tmp = ((ACL_SELECT_MODE_1x11<<6) | (link<<4));
+	if(r->rule_rvs & ACL_RULE_RVS_ETH_TYPE) {
+		tmp |= 0x1;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_DMAC) {
+		tmp |= 0x2;
+	}
+	if((r->rule_rvs&ACL_RULE_RVS_VLAN) && (r->rule_rvs&ACL_RULE_RVS_COS)) {
+		tmp |= 0x4;
+	}
+	if(r->rule_rvs & ACL_RULE_RVS_INGRESS_PORT) {
+		tmp |= 0x8;
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int acl_write_table_drop(int block, int index, int is_link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+
+	IP2Page(1);
+	//E1
+	tmp = 0x1F;
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0);
+	if(is_link) {
+		tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4));
+		Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+		Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	} else {
+		Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0);
+		Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5));
+	}
+
+	return 0;
+}
+
+int acl_write_table_a1(int block, int index, int is_link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+	u16 tmp2 = 0;
+
+	IP2Page(1);
+	//E1
+	if(r->act_valid & ACL_ACT_VALID_REDIR)
+	{
+		tmp |= ((r->redir)&0x1F);
+	}
+	if(r->act_valid & ACL_ACT_VALID_CTAG)
+	{
+		tmp |= ((r->ctag&0x7F)<<5);
+	}
+	if(r->act_valid & ACL_ACT_VALID_STAG)
+	{
+		tmp |= ((r->stag&0xF)<<12);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp);
+	
+	//E2
+	tmp = 0;
+	if(r->act_valid & ACL_ACT_VALID_STAG)
+	{
+		tmp |= ((r->stag&0x70)>>4);
+	}
+	if(r->act_valid & ACL_ACT_VALID_PRI)
+	{
+		tmp |= ((BIT(3)|(r->pri&0x7))<<3);
+	}
+	if(r->act_valid & ACL_ACT_VALID_DSCP)
+	{
+		tmp |= ((BIT(3)|(r->a_dscp&0x7))<<7);
+	}
+	if(r->act_valid & ACL_ACT_VALID_BW)
+	{
+		if(is_link)
+			tmp2 |= ((BIT(2)|(r->bw&0x3))<<4);
+		else
+			tmp |= ((BIT(2)|(r->bw&0x3))<<11);
+	}
+	if(r->act_valid & ACL_ACT_VALID_SNIFFER)
+	{
+		if(is_link)
+			tmp |= BIT(15);
+		else
+			tmp |= BIT(14);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, tmp);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, tmp2);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0);
+	if(is_link) {
+		tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4));
+		Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+		Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	} else {
+		Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0);
+		Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5));
+	}
+	
+	return 0;
+}
+
+int acl_write_table_a2(int block, int index, int is_link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+	u16 tmp2 = 0;
+
+	IP2Page(1);
+	//E1
+	if(r->act_valid & ACL_ACT_VALID_REDIR)
+	{
+		tmp |= ((r->redir)&0x1F);
+	}
+	if(r->act_valid & ACL_ACT_VALID_CTAG)
+	{
+		tmp |= ((r->ctag&0x7F)<<5);
+	}
+	if(r->act_valid & ACL_ACT_VALID_STAG)
+	{
+		tmp |= ((r->stag&0xF)<<12);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp);
+	
+	//E2
+	tmp = 0;
+	if(r->act_valid & ACL_ACT_VALID_STAG)
+	{
+		tmp |= ((r->stag&0x70)>>4);
+	}
+	if(r->act_valid & ACL_ACT_VALID_PRI)
+	{
+		tmp |= ((BIT(3)|(r->pri&0x7))<<3);
+	}
+	if(r->act_valid & ACL_ACT_VALID_STORM)
+	{
+		if(is_link)
+			tmp2 |= (BIT(r->storm-1)<<1);
+		else
+			tmp |= (BIT(r->storm-1)<<7);
+	}
+	if(r->act_valid & ACL_ACT_VALID_CPU)
+	{
+		if(is_link)
+			tmp2 |= BIT(0);
+		else
+			tmp |= BIT(10);
+	}
+	if(r->act_valid & ACL_ACT_VALID_MIB_COUNTER)
+	{
+		tmp |= ((BIT(1)|((r->mib_counter-1)&0x1))<<11);
+	}
+	if(r->act_valid & ACL_ACT_VALID_PTP)
+	{
+		tmp |= BIT(13);
+	}
+	if(r->act_valid & ACL_ACT_VALID_SFLOW)
+	{
+		tmp |= BIT(14);
+	}
+	tmp |= BIT(15);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, tmp);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, tmp2);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0);
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0);
+	if(is_link) {
+		tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4));
+		Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+		Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	} else {
+		Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0);
+		Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|index|(block<<5));
+	}
+
+	return 0;
+}
+
+int acl_write_table_a3(int block, int index, int is_link, struct acl_rule *r)
+{
+	u16 tmp = 0;
+
+	IP2Page(1);
+	//E1
+	if(r->act_valid & ACL_ACT_VALID_REDIR)
+	{
+		tmp |= ((r->redir)&0x1F);
+	}
+	if(r->act_valid & ACL_ACT_VALID_CTAG)
+	{
+		tmp |= ((r->ctag&0x7F)<<5);
+	}
+	if(r->act_valid & ACL_ACT_VALID_STAG)
+	{
+		tmp |= ((r->stag&0xF)<<12);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E1, tmp);
+	
+	//E2
+	tmp = 0;
+	if(r->act_valid & ACL_ACT_VALID_STAG)
+	{
+		tmp |= ((r->stag&0x70)>>4);
+	}
+	if(r->act_valid & ACL_ACT_VALID_PRI)
+	{
+		tmp |= ((BIT(3)|(r->pri&0x7))<<3);
+	}
+	if(r->act_valid & ACL_ACT_VALID_DSCP)
+	{
+		tmp |= ((BIT(3)|(r->a_dscp&0x7))<<7);
+	}
+	if(r->act_valid & ACL_ACT_VALID_MIB_COUNTER)
+	{
+		tmp |= ((BIT(1)|(r->mib_counter&0x1))<<11);
+	}
+	if(r->act_valid & ACL_ACT_VALID_PTP)
+	{
+		tmp |= BIT(13);
+	}
+	if(r->act_valid & ACL_ACT_VALID_SFLOW)
+	{
+		tmp |= BIT(14);
+	}
+	if(r->act_valid & ACL_ACT_VALID_SNIFFER)
+	{
+		tmp |= BIT(15);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E2, tmp);
+
+	//E3
+	tmp = 0;
+	if(r->act_valid & ACL_ACT_VALID_CPU)
+	{
+		tmp |= BIT(0);
+	}
+	if(r->act_valid & ACL_ACT_VALID_STORM)
+	{
+		tmp |= (BIT(r->storm-1)<<1);
+	}
+	if(r->act_valid & ACL_ACT_VALID_BW)
+	{
+		tmp |= ((BIT(2)|(r->bw&0x3))<<4);
+	}
+	Write_Reg(P1REG_ACL_TABLE_DATA_E3, tmp);
+	
+	//E4
+	Write_Reg(P1REG_ACL_TABLE_DATA_E4, 0);
+	//E5
+	Write_Reg(P1REG_ACL_TABLE_DATA_E5, 0);
+	//E6
+	Write_Reg(P1REG_ACL_TABLE_DATA_E6, 0);
+	//E7
+	Write_Reg(P1REG_ACL_TABLE_DATA_E7, 0);
+	//E8
+	Write_Reg(P1REG_ACL_TABLE_DATA_E8, 0);
+	//E9
+	Write_Reg(P1REG_ACL_TABLE_DATA_E9, 0);
+	//EA
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, 0);
+
+	tmp = ((ACL_SELECT_MODE_0001<<6) | (ACL_LINK_TYPE_11<<4));
+	Write_Reg(P1REG_ACL_TABLE_DATA_EA, tmp);
+
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|index|(block<<5));
+	return 0;
+}
+
+int switchdSetAclRule(struct AclRuleSetting *ars)
+{
+	struct acl_rule *r = &ars ->rule;
+	unsigned long rule_v = r->rule_valid;
+	int s_mode = 0, s_num = 0, flag = 0, i = 0, block = 0, index = 0, link = 0;
+	struct acl_man_rule *mr;
+	int ret = 0;
+	int find_idx_blockn;
+	int find_idx_rvs;
+
+	ip1811drv_dbg("<DBG_DR_ACL> switchdSetAclRule(): ars ->rule_index = %i\n", ars ->rule_index);
+	// check index
+	list_for_each_entry(mr, &m_acl ->rule_list, rule_entry) {
+		if(mr->rule_index == ars ->rule_index) {
+			if((mr->func_used) & (ars->func_used)) {
+				for(i = mr->start_index; i<(mr->start_index+mr->num_entries); i++) {
+					block = mr->start_block;
+					index = i&0xF;
+					acl_clean_table(block, index);
+					m_acl ->used_entry_mask[block] &= ~BIT(i&0xF);
+					m_acl ->num_used_entries--;
+				}
+				m_acl ->num_used_rules--;
+				flag = 1;
+				break;
+			}
+		}
+	}
+
+	if(!flag) {
+		mr = NULL;
+	}
+
+	if(rule_v==0) {
+		ars->rule_index_res=0;
+		ars->reserved=0;
+		m_acl->num_used_rules++;
+		if(mr!=NULL) {
+			list_del(&mr->rule_entry);
+			kfree(mr);
+		}
+		return 0;
+	}
+
+	// selection logic
+	if((rule_v & ACL_RULE_VALID_SIP6) || (rule_v & ACL_RULE_VALID_DIP6)) {
+		if(rule_v & ACL_RULE_VALID_SIP6) {
+			// 0110
+			s_mode |= ACL_SELECT_MODE_BIT_0110;
+			s_num += 1;
+		}
+
+		if(rule_v & ACL_RULE_VALID_DIP6) {
+			// 0111
+			s_mode |= ACL_SELECT_MODE_BIT_0111;
+			s_num += 1;
+		}
+
+		if((rule_v & ACL_RULE_VALID_SP_R) || (rule_v & ACL_RULE_VALID_DP_R)) {
+			// 0101
+			s_mode |= ACL_SELECT_MODE_BIT_0101;
+			s_num += 1;
+		}
+		goto out_select_logic;
+	} else if(rule_v & ACL_RULE_VALID_USERDEF_OFFSET) {
+		//0010
+		s_mode=ACL_SELECT_MODE_BIT_0010;
+		s_num=1;
+		goto out_select_logic;
+	}
+
+	if((rule_v & ACL_RULE_VALID_SP_R) || (rule_v & ACL_RULE_VALID_DP_R)) {
+		if(rule_v & ACL_RULE_VALID_DIP) {
+			// 0101 
+			s_mode |= ACL_SELECT_MODE_BIT_0101;
+			s_num += 1;
+
+			if( (rule_v & ACL_RULE_VALID_SIP)
+				|| (rule_v & ACL_RULE_VALID_DMAC)
+				|| (rule_v & ACL_RULE_VALID_SMAC)
+				|| (rule_v & ACL_RULE_VALID_ETH_TYPE)
+				|| (rule_v & ACL_RULE_VALID_DSCP)
+				|| (rule_v & ACL_RULE_VALID_IP_PROT)
+			) {
+				if(rule_v & ACL_RULE_VALID_DMAC) {
+					// 1x10
+					s_mode |= ACL_SELECT_MODE_BIT_1x10;
+					s_num += 1;
+				
+					if(rule_v & ACL_RULE_VALID_SMAC) { 
+						// 1x00
+						s_mode |= ACL_SELECT_MODE_BIT_1x00;
+						s_num += 1;
+					}
+				} else { 
+					// 1x00
+					s_mode |= ACL_SELECT_MODE_BIT_1x00;
+					s_num += 1;
+				}
+			}
+		} else {
+			// 0100 
+			s_mode |= ACL_SELECT_MODE_BIT_0100;
+			s_num += 1;
+			if( (rule_v & ACL_RULE_VALID_DMAC)
+				|| (rule_v & ACL_RULE_VALID_SMAC)
+				|| (rule_v & ACL_RULE_VALID_ETH_TYPE)
+				|| (rule_v & ACL_RULE_VALID_DSCP)
+				|| (rule_v & ACL_RULE_VALID_IP_PROT)
+			) {
+				if(rule_v & ACL_RULE_VALID_DMAC) {
+					// 1x10
+					s_mode |= ACL_SELECT_MODE_BIT_1x10;
+					s_num += 1;
+				
+					if(rule_v & ACL_RULE_VALID_SMAC) { 
+						// 1x00
+						s_mode |= ACL_SELECT_MODE_BIT_1x00;
+						s_num += 1;
+					}
+				} else { 
+					// 1x00
+					s_mode |= ACL_SELECT_MODE_BIT_1x00;
+					s_num += 1;
+				}
+			}
+		}
+	} else {
+		if(rule_v & ACL_RULE_VALID_DIP) {
+			if(rule_v & ACL_RULE_VALID_DMAC) {
+				// 1x11
+				s_mode |= ACL_SELECT_MODE_BIT_1x11;
+				s_num += 1;
+				
+				if((rule_v & ACL_RULE_VALID_SMAC) || (rule_v & ACL_RULE_VALID_SIP)) { 
+					// 1x00
+					s_mode |= ACL_SELECT_MODE_BIT_1x00;
+					s_num += 1;
+				}
+			} else { 
+				// 1x01
+				s_mode |= ACL_SELECT_MODE_BIT_1x01;
+				s_num += 1;
+				if(rule_v & ACL_RULE_VALID_SIP) { 
+					// 1x00
+					s_mode |= ACL_SELECT_MODE_BIT_1x00;
+					s_num += 1;
+				}
+			}
+		} else {
+			if(rule_v & ACL_RULE_VALID_DMAC) {
+				// 1x10
+				s_mode |= ACL_SELECT_MODE_BIT_1x10;
+				s_num += 1;
+				if(rule_v & ACL_RULE_VALID_SMAC) { 
+					// 1x00
+					s_mode |= ACL_SELECT_MODE_BIT_1x00;
+					s_num += 1;
+				}
+			} else { 
+				// 1x00
+				s_mode |= ACL_SELECT_MODE_BIT_1x00;
+				s_num += 1;
+			}
+		}
+	}
+
+out_select_logic:
+	ip1811drv_dbg("<DBG_SWD_ACL> s_mode = %02x, s_num = %i\n", s_mode, s_num);
+
+	if((r->act_type==ACL_ACT_TYPE_3) || (s_num>=2)) {
+		s_num++;
+	}
+
+	find_idx_blockn = ars->find_index_blockn;
+	find_idx_rvs = ars->find_index_rvs;
+
+	ret = acl_find_index(s_num, &block, &index, find_idx_blockn, find_idx_rvs);
+
+	if(ret < 0) { // if acl_find_index return <0, remap acl rule index and find index again
+		set_rule_index_remap();
+		ret = acl_find_index(s_num, &block, &index, find_idx_blockn, find_idx_rvs);
+	}
+
+	if(ret < 0) {
+		if(mr != NULL) {
+			list_del(&mr->rule_entry);
+			kfree(mr);
+		}
+		ars ->rule_index_res = -2;
+		ars ->reserved = s_num;
+		return 0;
+		//return -ENOMEM;
+	}
+	ip1811drv_dbg("<DBG_SWD_ACL> block, index = %i, %i\n", block, index);
+
+	ars->find_index_blockn = block;
+	if(mr == NULL) {
+		mr = kmalloc(sizeof(struct acl_man_rule), GFP_KERNEL);
+		if(mr == NULL) {
+			ip1811drv_err("Error: switchdSetAclRule() acl_man_rule malloc failed.\n");
+			return -ENOMEM;
+		}
+		list_add_tail(&mr->rule_entry, &m_acl ->rule_list);
+	}
+
+	mr->start_block = block;
+	mr->start_index = index;
+	mr->num_entries = s_num;
+	mr->rule_index = ars ->rule_index;
+	mr->func_used = ars ->func_used;
+	if(s_num == 1) {
+		link = ACL_LINK_TYPE_00;
+		// write rule table
+		for(i=2; i<12; i++) {
+			if(s_mode & BIT(i)) {
+				acl_write_table_rule[i-1](block, index, link, r);
+				s_num--;
+				break;
+			}
+		}
+		// write action table
+		acl_write_table_act[r->act_type](block, index, s_num, r);
+	} else {
+		link = ACL_LINK_TYPE_01;
+		// write rule table
+		for(i=2; i<12; i++) {
+			if(s_mode & BIT(i)) {
+				acl_write_table_rule[i-1](block, index, link, r);
+				index++;
+				s_num--;
+				if(s_num == 1) {
+					break;
+				} else {
+					link = ACL_LINK_TYPE_10;
+				}
+			}
+		}
+		// write action table
+		//acl_write_table_act[r->act_type](block, index, s_num, r);
+		acl_write_table_act[3](block, index, s_num, r);
+	}
+
+	for(i=0; i<mr->num_entries; i++) {
+		m_acl ->used_entry_mask[mr->start_block] |= BIT((i+mr->start_index)&0xF);
+		m_acl ->num_used_entries++;
+	}
+	m_acl ->num_used_rules++;
+	ars ->rule_index_res = 0;
+	ars ->reserved = mr->num_entries;
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclRule);
+
+int setAclRule(void *cdata, int len)
+{
+	int ret;
+	struct AclRuleSetting *ars = (struct AclRuleSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclRuleSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdSetAclRule(ars);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getAclRule(void *cdata, int len)
+{
+	return 0;
+}
+
+int switchdAclCleanTable(int rule_index, int func_used)
+{
+	int i = 0;
+	struct acl_man_rule *mr, *nmr;
+	int block, index;
+
+	if ((rule_index<1 || rule_index>64) && (rule_index!=128)) {
+		ip1811drv_err("Error: rule index=%d\n", rule_index);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("<DBG_DR_ACL> aclCleanTable()\n");
+
+	if(rule_index == 128) {
+		ip1811drv_dbg("<DBG_DR_ACL> aclCleanTable() 111111\n");
+		if(list_empty(&m_acl ->rule_list)) {
+			ip1811drv_dbg("<DBG_DR_ACL> aclCleanTable() 222222\n");
+			return 0;
+		}
+
+		list_for_each_entry_safe(mr, nmr, &m_acl ->rule_list, rule_entry)
+		{
+			for(i=0; i<mr->num_entries; i++) {
+				block = mr->start_block;
+				index = mr->start_index;
+				acl_clean_table(block, index+i);
+				m_acl ->used_entry_mask[block] &= ~BIT((index+i)&0xF);
+				m_acl ->num_used_entries--;
+			}
+			m_acl ->num_used_rules--;
+			list_del(&mr->rule_entry);
+			kfree(mr);
+		}
+
+		INIT_LIST_HEAD(&m_acl ->rule_list);
+
+		if((m_acl ->num_used_rules!=0) || (m_acl ->num_used_entries!=0))
+			ip1811drv_err("<DBG_SWD_ACL> aclCleanTable something error!\n");
+	} else {
+		list_for_each_entry(mr, &m_acl ->rule_list, rule_entry)
+		{
+			if(mr->rule_index == rule_index) {
+				if((mr->func_used) & func_used) {
+					for(i=0; i<mr->num_entries; i++) {
+						block = mr->start_block;
+						index = mr->start_index;
+						acl_clean_table(block, index+i);
+						m_acl ->used_entry_mask[block] &= ~BIT((index+i)&0xF);
+						m_acl ->num_used_entries--;
+					}
+					m_acl ->num_used_rules--;
+					list_del(&mr->rule_entry);
+					kfree(mr);
+					break;
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdAclCleanTable);
+
+int aclCleanTable(void *cdata, int len)
+{
+	int ret, rule_index, func_used;
+	struct AclTableCleanSetting *atcs = (struct AclTableCleanSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclTableCleanSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	rule_index = atcs ->rule_idx;
+	func_used = atcs ->func_used;
+	ret = switchdAclCleanTable(rule_index, func_used);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdSetAclFunctionEn(int enable)
+{
+	if ((enable!=OP_FUNC_ENABLE) && (enable!=OP_FUNC_DISABLE)) {
+		ip1811drv_err("Error: value=%d\n", enable);
+		return -EINVAL;
+	}
+	_WriteRegBits(1, P1REG_MISCCFG, 0, 1, enable);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclFunctionEn);
+
+int setAclFunctionEn(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+	int func_en;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	func_en = gs ->gdata;
+	ret = switchdSetAclFunctionEn(func_en);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdGetAclFunctionEn(int *gdata_p)
+{
+	*gdata_p = _ReadRegBits(1, P1REG_MISCCFG, 0, 1);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclFunctionEn);
+
+int getAclFunctionEn(void *cdata, int len)
+{
+	int ret; 
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdGetAclFunctionEn(&(gs ->gdata));
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdSetAclEtherAfterTag(int is_after_tag)
+{
+	if ((is_after_tag!=OP_FUNC_ENABLE) && (is_after_tag!=OP_FUNC_DISABLE)) {
+		ip1811drv_err("Error: value=%d\n", is_after_tag);
+		return -EINVAL;
+	}
+	_WriteRegBits(1, P1REG_MISCCFG, 1, 1, is_after_tag);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclEtherAfterTag);
+
+int setAclEtherAfterTag(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+	int loca_v;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	loca_v = gs ->gdata;
+	ret = switchdSetAclEtherAfterTag(loca_v);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetAclEtherAfterTag(int *gdata_p)
+{
+	*gdata_p = _ReadRegBits(1, P1REG_MISCCFG, 1, 1);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclEtherAfterTag);
+
+int getAclEtherAfterTag(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdGetAclEtherAfterTag(&(gs ->gdata));
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetAclUsedRules(int *gdata_p)
+{
+	*gdata_p = m_acl ->num_used_rules;
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclUsedRules);
+
+int getAclUsedRules(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdGetAclUsedRules(&(gs ->gdata));
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdGetAclUsedEntries(int *gdata_p)
+{
+	*gdata_p = m_acl ->num_used_entries;
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclUsedEntries);
+
+int getAclUsedEntries(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdGetAclUsedEntries(&(gs ->gdata));
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetAclUsedEntryMask(unsigned short *gmask_p)
+{
+	memcpy(gmask_p, m_acl->used_entry_mask, 4*sizeof(unsigned short));
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclUsedEntryMask);
+
+int getAclUsedEntryMask(void *cdata, int len)
+{
+	int ret;
+	struct AclEntryMaskGetting *aemg = (struct AclEntryMaskGetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclEntryMaskGetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdGetAclUsedEntryMask(aemg ->mask);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetAclBW(int index, int in_rate)
+{
+	u16 rate = 0;
+	
+	if (index<0 || index>3) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	if (in_rate<0 || in_rate>2540) {
+		ip1811drv_err("Error: rate=%d\n", in_rate);
+		return -EINVAL;
+	}
+
+	if(in_rate > 163) {
+		rate |= BIT(7);
+		rate |= (in_rate*100/2000);
+		if(in_rate*100%2000) 
+			rate++;
+	} else {
+		rate = (in_rate*100/128);
+		if(in_rate*100%128) 
+			rate++;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("value=0x%x\n", rate);
+	// set 4 block
+	_WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+0, 8*(index%2), 8, rate);
+	_WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+2, 8*(index%2), 8, rate);
+	_WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+4, 8*(index%2), 8, rate);
+	_WriteRegBits(1, P1REG_ACL_BW_01+(index/2)+6, 8*(index%2), 8, rate);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclBW);
+
+int setAclBW(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int bw_index;
+	int bw_v;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	bw_index = ags ->index;
+	bw_v = ags ->data;
+	ret = switchdSetAclBW(bw_index, bw_v);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdGetAclBW(int index, int *gdata_p)
+{
+	u16 tmp = 0;
+	u32 c_rate;
+	
+	if (index<0 || index>3) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	tmp = _ReadRegBits(1, P1REG_ACL_BW_01+(index/2), (8*(index%2)), 8);
+
+	if(tmp&BIT(7)) {
+		c_rate = (tmp&(0x7F))*2000;
+	} else {
+		c_rate = (tmp&(0x7F))*128;
+	}
+
+	*gdata_p = c_rate/100;
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclBW);
+
+int getAclBW(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int bw_index;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	bw_index = ags ->index;
+	ret = switchdGetAclBW(bw_index, &(ags ->data));
+	ip1811drv_dbg("cdata ->data=%d\n", ags ->data);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetAclDscp(int index, int value)
+{
+	if (index<0 || index>7) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	if (value & (~0x3F)) {
+		ip1811drv_err("Error: value=%x\n", value);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("value=0x%x\n", value);
+
+	_WriteRegBits(7, P7REG_DSCP_REMARKING_01+(index/2), 8*(index%2), 8, value);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclDscp);
+
+int setAclDscp(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int dscp_index;
+	int dscp_v;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	dscp_index = ags ->index;
+	dscp_v = ags ->data;
+	ret = switchdSetAclDscp(dscp_index, dscp_v);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetAclDscp(int index, int *gdata_p)
+{
+	if (index<0 || index>7) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+	*gdata_p = _ReadRegBits(7, P7REG_DSCP_REMARKING_01+(index/2), (8*(index%2)), 8);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclDscp);
+
+int getAclDscp(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int dscp_index;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	dscp_index = ags ->index;
+	ret = switchdGetAclDscp(dscp_index, &(ags ->data));
+	ip1811drv_dbg("cdata ->data=%d\n", ags ->data);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdSetAclVidRemark(int index, int value)
+{
+	
+	if (index<0 || index>15) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	if (value & (~0x7FFF)) {
+		ip1811drv_err("Error: value=%x\n", value);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("value=0x%x\n", value);
+
+	_WriteRegBits(2, P2REG_ACL_VID_REMARK_00+index, 0, 15, value);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclVidRemark);
+
+int setAclVidRemark(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int vid_index;
+	int vid_v;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	vid_index = ags ->index;
+	vid_v = ags ->data;
+	ret = switchdSetAclVidRemark(vid_index, vid_v);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdGetAclVidRemark(int index, int *gdata_p)
+{
+	
+	if (index<0 || index>15) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	*gdata_p = _ReadRegBits(2, P2REG_ACL_VID_REMARK_00+index, 0, 15);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclVidRemark);
+
+int getAclVidRemark(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int vid_index;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	vid_index = ags ->index;
+	ret = switchdGetAclVidRemark(vid_index, &(ags ->data));
+	ip1811drv_dbg("cdata ->data=%d\n", ags ->data);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int acl_write_table_move(int from_block, int from_index, int to_block, int to_index)
+{
+	int i;
+	u16 u16array[10];
+	u16 u16dat;
+
+	IP2Page(1);
+
+	// rule
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0x8000|from_index|((from_block&0x3)<<5));
+	for(i=0; i<10; i++) {
+		u16dat = Read_Reg(P1REG_ACL_TABLE_DATA_E1+i);
+		u16array[i] = u16dat;
+	}
+	acl_clean_table_rule(from_block, from_index);
+	for(i=0; i<10; i++) {
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1+i, u16array[i]);
+	}
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC000|to_index|((to_block&0x3)<<5));
+	
+	// act 
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0x8100|from_index|((from_block&0x3)<<5));
+	for(i=0; i<10; i++) {
+		u16dat = Read_Reg(P1REG_ACL_TABLE_DATA_E1+i);
+		u16array[i] = u16dat;
+	}
+	acl_clean_table_act(from_block, from_index);
+	for(i=0; i<10; i++) {
+		Write_Reg(P1REG_ACL_TABLE_DATA_E1+i, u16array[i]);
+	}
+	Write_Reg(P1REG_ACL_TABLE_ACCESS, 0xC100|to_index|((to_block&0x3)<<5));
+
+	m_acl ->used_entry_mask[to_block] |= BIT(to_index);
+	m_acl ->used_entry_mask[from_block] &= ~BIT(from_index);
+
+	return 0;
+}
+
+int set_rule_index_remap(void)
+{
+	int i, j;
+	int index_move_to;
+	int block_move_to;
+	int index_move_from;
+	int block_move_from;
+	int index_move_range;
+	struct acl_man_rule *mr;
+
+	ip1811drv_dbg("<DBG_DR_ACL> set_rule_index_remap()\n");
+
+	for(i=0; i<64; i++) {
+		if(m_acl ->used_entry_mask[i>>4] & BIT(i%16)) { // entry i rule exist
+		} else { // entry i rule not exist
+			int no_entry = 1;
+			block_move_to = (i>>4)&0x3;
+			index_move_to = i&0xF;
+			block_move_from = 3;
+			index_move_from = 16;
+			index_move_range= 0;
+			// scan closest entry
+			list_for_each_entry(mr, &m_acl ->rule_list, rule_entry) { 
+				if(mr->func_used != ACL_RULE_FUNC_USED_SNOOP) {
+					if((16*mr->start_block+mr->start_index)>i) {
+						if(((16*mr->start_block+mr->start_index)<(block_move_from*16+index_move_from)) && (mr->num_entries<=(16-index_move_to))) {
+							block_move_from = mr->start_block;
+							index_move_from = mr->start_index;
+							index_move_range = mr->num_entries;
+							no_entry = 0;
+						}
+					}
+				}
+			}
+
+			if(no_entry)
+				continue;
+
+			// move exist entry to empty rule index
+			for(j=0; j<index_move_range; j++) {
+				acl_write_table_move(block_move_from, index_move_from+j, block_move_to, index_move_to+j);
+			}
+		
+			// modify entry info	
+			list_for_each_entry(mr, &m_acl ->rule_list, rule_entry) {
+				if((mr->start_block==block_move_from) && (mr->start_index==index_move_from)) {
+					mr->start_block = block_move_to;
+					mr->start_index = index_move_to;
+				}
+			}
+			// assign i to be link entry end
+			i += (index_move_range-1);
+		}
+		ip1811drv_dbg("<DBG_DR_ACL> set_rule_index_remap(): entry from block(%d)/index(%d) to block(%d)/index(%d)\n", block_move_from, index_move_from, block_move_to, index_move_to);
+
+	}
+
+	return 0;
+}
+
+int switchdSetAclStormPeriod(int period)
+{
+	if (period& (~0x3)) {
+		ip1811drv_err("Error: period=0x%x\n", period);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("clear period=0x%x\n", period);
+	_WriteRegBits(1, P1REG_MISCCFG, 4, 2, period);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclStormPeriod);
+
+int setAclStormPeriod(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+	int period;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	period = gs ->gdata;
+	ret = switchdSetAclStormPeriod(period);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetAclStormPeriod(int *gdata_p)
+{
+	*gdata_p = _ReadRegBits(1, P1REG_MISCCFG, 4, 2);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclStormPeriod);
+
+int getAclStormPeriod(void *cdata, int len)
+{
+	int ret;
+	struct GeneralSetting *gs = (struct GeneralSetting *)cdata;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	ret = switchdGetAclStormPeriod(&(gs ->gdata));
+	ip1811drv_dbg("cdata ->gdata=%d\n", gs ->gdata);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+
+int switchdSetAclStorm(int index, int value)
+{
+	if (index<0 || index>2) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+
+	if (value & (~0xFFFF)) {
+		ip1811drv_err("Error: value=%x\n", value);
+		return -EINVAL;
+	}
+	_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 1);
+	ip1811drv_dbg("index=%d\n", index);
+	ip1811drv_dbg("value=0x%x\n", value);
+	_WriteRegBits(1, P1REG_ACL_STORM_0+index, 0, 16, value);
+	_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0);
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetAclStorm);
+
+int setAclStorm(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int storm_index;
+	int storm_v;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	storm_index = ags ->index;
+	storm_v = ags ->data;
+	ret = switchdSetAclStorm(storm_index, storm_v);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdGetAclStorm(int index, int *gdata_p)
+{
+	if (index<0 || index>2) {
+		ip1811drv_err("Error: index=%d\n", index);
+		return -EINVAL;
+	}
+	_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 1);
+	*gdata_p = _ReadRegBits(1, P1REG_ACL_STORM_0+index, 0, 16);
+	_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0);
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetAclStorm);
+
+int getAclStorm(void *cdata, int len)
+{
+	int ret;
+	struct AclGeneralSetting *ags = (struct AclGeneralSetting *)cdata;
+	int storm_index;
+
+	FUNC_MSG_IN;
+	if (sizeof(struct AclGeneralSetting) != len) {
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+
+	storm_index = ags ->index;
+	ret = switchdGetAclStorm(storm_index, &(ags ->data));
+	ip1811drv_dbg("cdata ->data=%d\n", ags ->data);
+	FUNC_MSG_OUT;
+	
+	return ret;
+}
+//------------ ACL functions:common end  -----------------------
+
+//------------------------------------------------
+//common_bandwidth
+int switchdSetBandwidthIngressRate(int port, unsigned long rate)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+	{
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+	if (rate > MAX_GIGA_SPEED)
+	{
+		ip1811drv_err("Error: pdata=0x%08X\n", (u16)rate);
+		return -EINVAL;
+	}
+
+	IP2Page(0);
+	if (rate == 0 || rate == MAX_GIGA_SPEED || (port < MAX_PHY_TP_NUM && rate >= MAX_TP_SPEED))
+	{	Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,0);	}
+	else if(rate > 0 && rate < MAX_GIGA_SPEED)
+	{
+		if(port < MAX_PHY_TP_NUM && rate >= (MAX_TP_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT)
+		{	Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,0);	}
+		else if(rate >= (MAX_GIGA_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT)
+		{	
+			Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,0);
+#ifdef COMBINED_PORT
+			if (port==9)
+				Write_Reg(P0REG_INGRESS_RATE_CTRL0+port+1,0);
+#endif
+		}
+		else
+		{
+			if(rate%RATE_SCALE_UNIT)
+			{
+				Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT+1);
+#ifdef COMBINED_PORT
+				if (port==9)
+					Write_Reg(P0REG_INGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT+1);
+#endif
+			}
+			else
+			{
+				Write_Reg(P0REG_INGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT);
+#ifdef COMBINED_PORT
+				if (port==9)
+					Write_Reg(P0REG_INGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT);
+#endif
+			}
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetBandwidthIngressRate);
+int setBandwidthIngressRate(void *cdata, int len)
+{
+	int port;	//1-28
+	unsigned long rate;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting32) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting32 *)cdata)->port;
+	rate = ((struct ByPortSetting32 *)cdata)->pdata;
+
+	if(switchdSetBandwidthIngressRate(port, rate) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetBandwidthIngressRate(int port, unsigned long *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM){
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (unsigned long)(_ReadRegBits(0, P0REG_INGRESS_RATE_CTRL0+port, 0, 14)*64000);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetBandwidthIngressRate);
+int getBandwidthIngressRate(void *cdata, int len)
+{
+	int port;
+	unsigned long rate;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting32) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting32 *)cdata)->port;
+	
+	if(switchdGetBandwidthIngressRate(port, &rate) != 0)
+		return -EINVAL;
+
+	((struct ByPortSetting32 *)cdata)->pdata = rate;
+	ip1811drv_dbg("cdata->port=%d\n", ((struct ByPortSetting32 *)cdata)->port);
+	ip1811drv_dbg("cdata->pdata=0x%08X\n", (u16)((struct ByPortSetting32 *)cdata)->pdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetBandwidthEgressRate(int port, unsigned long rate)
+{
+	if (port < 0 || port >= MAX_PHY_NUM)
+	{
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+	if (rate > MAX_GIGA_SPEED)
+	{
+		ip1811drv_err("Error: pdata=0x%08X\n", (u16)rate);
+		return -EINVAL;
+	}
+	IP2Page(8);
+	if (rate == 0 || rate == MAX_GIGA_SPEED || (port < MAX_PHY_TP_NUM && rate >= MAX_TP_SPEED))
+	{	Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,0);	}
+	else if(rate > 0 && rate < MAX_GIGA_SPEED)
+	{
+		if(port < MAX_PHY_TP_NUM && rate >= (MAX_TP_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT)
+		{	Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,0);	}
+		else if(rate >= (MAX_GIGA_SPEED/RATE_SCALE_UNIT)*RATE_SCALE_UNIT)
+		{	
+			Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,0);
+#ifdef COMBINED_PORT
+			if (port==9)
+				Write_Reg(P8REG_EGRESS_RATE_CTRL0+port+1,0);
+#endif
+		}
+		else
+		{
+			if(rate%RATE_SCALE_UNIT)
+			{
+				Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT+1);
+#ifdef COMBINED_PORT
+				if (port==9)
+					Write_Reg(P8REG_EGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT+1);
+#endif
+			}
+			else
+			{
+				Write_Reg(P8REG_EGRESS_RATE_CTRL0+port,rate/RATE_SCALE_UNIT);
+#ifdef COMBINED_PORT
+				if (port==9)
+					Write_Reg(P8REG_EGRESS_RATE_CTRL0+port+1,rate/RATE_SCALE_UNIT+1);
+#endif
+			}
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetBandwidthEgressRate);
+int setBandwidthEgressRate(void *cdata, int len)
+{
+	int port;
+	unsigned long rate;
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting32) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting32 *)cdata)->port;
+	rate = ((struct ByPortSetting32 *)cdata)->pdata;
+	
+	if(switchdSetBandwidthEgressRate(port, rate) != 0)
+		return -EINVAL;
+		
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetBandwidthEgressRate(int port, unsigned long *ptrInt)
+{
+	if (port < 0 || port >= MAX_PHY_NUM){
+		ip1811drv_err("Error: port=%d\n", port);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("port=%d\n", port);
+
+#ifdef COMBINED_PORT
+	if (port==9 && _ReadRegBits(3, 0x15, 0, 1)) //port==9 && port10 link
+		port++;
+#endif
+	*ptrInt = (unsigned long)(_ReadRegBits(8, P8REG_EGRESS_RATE_CTRL0+port, 0, 14)*64000);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetBandwidthEgressRate);
+int getBandwidthEgressRate(void *cdata, int len)
+{
+	int port;
+	unsigned long rate;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct ByPortSetting32) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	port = ((struct ByPortSetting32 *)cdata)->port;
+	
+	if(switchdGetBandwidthEgressRate(port, &rate) != 0)
+		return -EINVAL;
+
+	((struct ByPortSetting32 *)cdata)->pdata = rate;
+	ip1811drv_dbg("cdata->port=%d\n", ((struct ByPortSetting32 *)cdata)->port);
+	ip1811drv_dbg("cdata->pdata=0x%08X\n", (u16)((struct ByPortSetting32 *)cdata)->pdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdSetBandwidthEgressPeriod(int period)
+{
+	if (period < 0 || period > 7){
+		ip1811drv_err("Error: gdata=%d\n", period);
+		return -EINVAL;
+	}
+	_WriteRegBits(8, P8REG_OUT_QUEUE_PARAM, 4, 3, period);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetBandwidthEgressPeriod);
+int setBandwidthEgressPeriod(void *cdata, int len)
+{
+	int period;
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len)
+	{
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	
+	period = ((struct GeneralSetting *)cdata)->gdata;
+	
+	if(switchdSetBandwidthEgressPeriod(period) != 0)
+		return -EINVAL;
+
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int switchdGetBandwidthEgressPeriod(int *ptrInt)
+{
+	*ptrInt = (int)_ReadRegBits(8,P8REG_OUT_QUEUE_PARAM,4,3);
+
+	ip1811drv_dbg("cdata ->pdata=%d\n", *ptrInt);
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdGetBandwidthEgressPeriod);
+int getBandwidthEgressPeriod(void *cdata, int len)
+{
+	int period=0;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	
+	if(switchdGetBandwidthEgressPeriod(&period) != 0)
+		return -EINVAL;
+
+	((struct GeneralSetting *)cdata)->gdata = period;
+	
+	ip1811drv_dbg("cdata->gdata=0x%08X\n", ((struct GeneralSetting *)cdata)->gdata);
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+//------------ EEPROM functions:common start  -----------------
+#define CMD_EEPROM_READ		0x8000
+#define CMD_EEPROM_WRITE	0xC000
+#define EEPROM_BIT_COMPLETE	0x8000
+#define REG_RETRY_COUNT		200
+
+u8 EE_Type = OP_EE_TYPE_Unknow;
+u8 EE_Data [OP_EEPROM_LEN_24C32] = {0x0};
+u8 EE_Flag [OP_EEPROM_LEN_24C32] = {0x0};
+
+u8 getEepromType(void)
+{
+	unsigned short val, i;
+	
+	IP2Page(0xE);
+	Write_Reg(PEREG_EEPROM_CMD+1, (unsigned short)(Read_Reg(PEREG_EEPROM_CMD+1)&0xFF00));
+	IP2Page(0xE);
+	Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_READ + 0x1));
+
+	IP2Page(0xE);
+	val = Read_Reg(PEREG_EEPROM_CMD);
+	for(i = 0 ; 0 == (val&EEPROM_BIT_COMPLETE) && i < REG_RETRY_COUNT ; i++)
+	{
+		IP2Page(0xE);
+		val = Read_Reg(PEREG_EEPROM_CMD);
+	}
+			
+	if(i == REG_RETRY_COUNT)
+	{
+		ip1811drv_err("Error: get EEPROM type REG_RETRY_COUNT reached\n");
+		return -EINVAL;
+	}
+		
+	IP2Page(0xE);
+	val = Read_Reg(PEREG_EEPROM_DATA) & 0xFF;
+	
+	udelay(5000);
+	
+	if(val == 0x0B)
+		return OP_EE_TYPE_C16;
+	else if(val == 0x0D)
+		return OP_EE_TYPE_C32;
+	else
+		return OP_EE_TYPE_Unknow;
+}
+
+// EEPROM READ/WRITE
+int setEepromByte(void *cdata, int len)
+{
+	unsigned short addr2write, i, val;
+	unsigned char val2write;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct EepromSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	
+	if(EE_Type==OP_EE_TYPE_Unknow)
+	{
+		EE_Type = getEepromType();
+		if(EE_Type==OP_EE_TYPE_Unknow)
+		{
+			ip1811drv_err("Error: setEEPROM get type failed\n");
+			return -EINVAL;
+		}
+		ip1811drv_dbg("set EEPROM type->%X\n", EE_Type);
+	}
+	
+	addr2write = ((struct EepromSetting *)cdata)->addr;
+	val2write = ((struct EepromSetting *)cdata)->value;
+	if (addr2write > (EE_Type?OP_EEPROM_LEN_24C32:OP_EEPROM_LEN_24C16))
+	{
+		ip1811drv_err("Error: addr=0x%04X\n", addr2write);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("type %X set addr:%04X , value:%02X\n", EE_Type, addr2write, val2write);
+	
+	// update eeprom hardware
+	IP2Page(0xE);
+	Write_Reg(PEREG_EEPROM_DATA, val2write);
+	IP2Page(0xE);
+	if(EE_Type==OP_EE_TYPE_C16)
+	{
+		Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_WRITE + addr2write));
+	}
+	else
+	{
+		Write_Reg(PEREG_EEPROM_CMD+1, (unsigned short)((Read_Reg(PEREG_EEPROM_CMD+1)&0xFF00)|((addr2write>>8)&0xFF)));
+		IP2Page(0xE);
+		Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_WRITE + (addr2write&0xFF)));
+	}
+	
+	IP2Page(0xE);
+	val = Read_Reg(PEREG_EEPROM_CMD);
+	for(i = 0 ; 0 == (val&EEPROM_BIT_COMPLETE) && i < REG_RETRY_COUNT ; i++)
+	{
+		IP2Page(0xE);
+		val = Read_Reg(PEREG_EEPROM_CMD);
+	}
+		
+	if(i == REG_RETRY_COUNT)
+	{
+		ip1811drv_err("Error: set EEPROM REG_RETRY_COUNT reached %04X\n", addr2write);
+		return -EINVAL;
+	}
+	
+//	udelay(5000);
+	
+	// update eeprom driver mem
+	EE_Flag[addr2write] = 0x1;
+	EE_Data[addr2write] = val2write;
+
+	ip1811drv_dbg("EE set done\n");
+	FUNC_MSG_OUT;
+	return 0;
+}
+
+int getEepromByte(void *cdata, int len)
+{
+	unsigned short addr2read, i, val;
+	unsigned char val2return;
+	
+	FUNC_MSG_IN;
+	if (sizeof(struct EepromSetting) != len)
+	{
+		ip1811drv_err("Error: length=%d\n", len);
+		return -EINVAL;
+	}
+	
+	if(EE_Type==OP_EE_TYPE_Unknow)
+	{
+		EE_Type = getEepromType();
+		if(EE_Type==OP_EE_TYPE_Unknow)
+		{
+			ip1811drv_err("Error: getEEPROM get type failed\n");
+			return -EINVAL;
+		}
+		ip1811drv_dbg("set EEPROM type->%X\n", EE_Type);
+	}
+	
+	addr2read = ((struct EepromSetting *)cdata)->addr;
+	if (addr2read > (EE_Type?OP_EEPROM_LEN_24C32:OP_EEPROM_LEN_24C16))
+	{
+		ip1811drv_err("Error: addr=0x%04X\n", addr2read);
+		return -EINVAL;
+	}
+	ip1811drv_dbg("type %X get addr:%04X\n", EE_Type, addr2read);
+	
+	if(EE_Flag[addr2read]==0x1) // return driver value
+	{
+		val2return = EE_Data[addr2read];
+	}
+	else // update driver memory
+	{
+		IP2Page(0xE);
+		if(EE_Type==OP_EE_TYPE_C16)
+		{
+			Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_READ + addr2read));
+		}
+		else
+		{
+			Write_Reg(PEREG_EEPROM_CMD+1, (unsigned short)((Read_Reg(PEREG_EEPROM_CMD+1)&0xFF00)|((addr2read>>8)&0xFF)));
+			IP2Page(0xE);
+			Write_Reg(PEREG_EEPROM_CMD, (CMD_EEPROM_READ + (addr2read & 0xFF)));
+		}
+		
+		IP2Page(0xE);
+		val = Read_Reg(PEREG_EEPROM_CMD);
+		for(i = 0 ; 0 == (val&EEPROM_BIT_COMPLETE) && i < REG_RETRY_COUNT ; i++)
+		{
+			IP2Page(0xE);
+			val = Read_Reg(PEREG_EEPROM_CMD);
+		}
+			
+		if(i == REG_RETRY_COUNT)
+		{
+			ip1811drv_err("Error: get EEPROM REG_RETRY_COUNT reached %04X\n", addr2read);
+			return -EINVAL;
+		}
+		
+		IP2Page(0xE);
+		val2return = Read_Reg(PEREG_EEPROM_DATA) & 0xFF;
+		
+		EE_Flag[addr2read] = 0x1;
+		EE_Data[addr2read] = val2return;
+		
+//		udelay(5000);
+	}
+
+	((struct EepromSetting *)cdata)->value = val2return;
+	ip1811drv_dbg("EE get done and value:%04X\n", val2return);
+	FUNC_MSG_OUT;
+	return 0;
+}
+//------------ EEPROM functions:common end  -----------------
+
+//------------ HSR functions:common Start  -----------------------
+int setHSREnable(void *cdata, int len)
+{
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _setGeneralEnable(cdata, len, 0x02, P2REG_HSR_REG_SETTING_1, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int getHSREnable(void *cdata, int len)
+{
+	int ret;
+
+	FUNC_MSG_IN;
+	ret = _getGeneralEnable(cdata, len, 0x02, P2REG_HSR_REG_SETTING_1, 0);
+	FUNC_MSG_OUT;
+
+	return ret;
+}
+
+int switchdSetHSRMode(int mode)
+{
+	if( mode != OP_HSR_MANDATORY && mode != OP_HSR_UNICAST ){
+		ip1811drv_err("Error: mode=%X\n", mode);
+		return -EINVAL;
+	}
+
+	ip1811drv_dbg("cdata ->mode=%d\n", mode);
+
+	if(mode==OP_HSR_MANDATORY){
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_1, 10, 2, 0x3);
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 8, 1, 0x1);
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 11, 1, 0x1);
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 0, 2, 0x0);
+		_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x1);
+		IP2Page(0x1);
+		Write_Reg(P1REG_LUTAGINGTIME, 0x0003);
+		_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x0);
+	}
+	else if(mode==OP_HSR_UNICAST){
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_1, 10, 2, 0x3);
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 8, 1, 0x1);
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 11, 1, 0x1);
+		_WriteRegBits(2, P2REG_HSR_REG_SETTING_2, 0, 2, 0x3);
+		_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x1);
+		IP2Page(0x1);
+		Write_Reg(P1REG_LUTAGINGTIME, 0x00A3);
+		_WriteRegBits(1, P1REG_MISCCFG, 13, 1, 0x0);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(switchdSetHSRMode);
+int setHSRMode(void *cdata, int len)
+{
+	int gdata;
+
+	if (sizeof(struct GeneralSetting) != len){
+		ip1811drv_err("Error: lengtn=%d\n", len);
+		return -EINVAL;
+	}
+	gdata = ((struct GeneralSetting *)cdata) ->gdata;
+
+	FUNC_MSG_IN;
+	if(switchdSetHSRMode(gdata) != 0)
+		return -EINVAL;
+	FUNC_MSG_OUT;
+	
+	return 0;
+}
+
+void switchdGetHSRMode(int *ptrInt)
+{
+	int val;
+	
+	val=(int)_ReadRegBits(2, P2REG_HSR_REG_SETTING_2, 0, 2);
+	if(val==0x3)
+		*ptrInt = OP_HSR_MANDATORY;
+	else if(val==0x0)
+		*ptrInt = OP_HSR_UNICAST;
+}
+EXPORT_SYMBOL(switchdGetHSRMode);
+int getHSRMode(void *cdata, int len)
+{
+	int ret;
+
+	ip1811drv_dbg("ip1811: +getHSRMode...\n");
+	if (sizeof(struct GeneralSetting) != len)
+		return -EINVAL;
+
+	FUNC_MSG_IN;
+	switchdGetHSRMode(&ret);
+	FUNC_MSG_OUT;
+
+	((struct GeneralSetting *)cdata) ->gdata = ret;
+
+	ip1811drv_dbg("cdata ->gdata=%d\n", ((struct GeneralSetting *)cdata) ->gdata);
+	ip1811drv_dbg("ip1811: -getHSRMode...\n");
+	return 0;
+}
+//------------ HSR functions:common end  -----------------------
+
+void noFunc(void)
+{}
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811op.h b/kernel/drivers/net/ethernet/ip1811/ip1811op.h
new file mode 100644
index 0000000..80591c3
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811op.h
@@ -0,0 +1,427 @@
+#ifndef IP1811OP_H
+#define IP1811OP_H
+
+#define OP_FUNC_DISABLE		0
+#define OP_FUNC_ENABLE		1
+
+#define OP_SMI_DUPLEX_HALF	0
+#define OP_SMI_DUPLEX_FULL	1
+
+#define OP_SMI_SPEED_1000	1000
+#define OP_SMI_SPEED_100	100
+#define OP_SMI_SPEED_10		10
+
+#define OP_CAP_PTCL_BPDU	0
+#define OP_CAP_PTCL_SLOW	1
+#define OP_CAP_PTCL_802_1X	2
+#define OP_CAP_PTCL_LLDP	3
+#define OP_CAP_PTCL_GRP0	4
+#define OP_CAP_PTCL_BRIDGE	5
+#define OP_CAP_PTCL_GRP1	6
+#define OP_CAP_PTCL_GARP	7
+#define OP_CAP_PTCL_GRP2	8
+#define OP_CAP_PTCL_GRP3	9
+
+#define OP_CAP_ACT_FORWARD	0
+#define OP_CAP_ACT_ALL_PORT	1
+#define OP_CAP_ACT_TO_CPU	2
+#define OP_CAP_ACT_DROP		3
+
+enum{
+	OP_CAT_INBAND_ARP,	//0
+	OP_CAT_INBAND_IPV4,
+	OP_CAT_INBAND_IPV6,
+	OP_CAT_INBAND_PPPOE,
+	OP_CAT_INBAND_ICMP,
+	OP_CAT_INBAND_TCP,
+	OP_CAT_INBAND_UDP,
+	OP_CAT_INBAND_USER_ETH,
+	OP_CAT_INBAND_USER_IP1,	//8
+	OP_CAT_INBAND_USER_IP2,
+	OP_CAT_INBAND_ICMPV6,
+	OP_CAT_INBAND_FTP,
+	OP_CAT_INBAND_SSH,
+	OP_CAT_INBAND_TELNET,
+	OP_CAT_INBAND_SMTP,
+	OP_CAT_INBAND_DNS,
+	OP_CAT_INBAND_BOOTP,	//16
+	OP_CAT_INBAND_TFTP,
+	OP_CAT_INBAND_HTTP,
+	OP_CAT_INBAND_POP3,
+	OP_CAT_INBAND_NEWS,
+	OP_CAT_INBAND_SNTP,
+	OP_CAT_INBAND_NETBIOS,
+	OP_CAT_INBAND_IMAP,
+	OP_CAT_INBAND_SNMP,	//24
+	OP_CAT_INBAND_HTTPS,
+	OP_CAT_INBAND_USER_TCPUDP_A,
+	OP_CAT_INBAND_USER_TCPUDP_B,
+	OP_CAT_INBAND_USER_TCPUDP_C,
+	OP_CAT_INBAND_USER_TCPUDP_D,
+	OP_CAT_INBAND_USER_TCPUDP_E,
+	OP_CAT_INBAND_TOTALNUM	//31
+};
+
+enum{
+	OP_CAT_L3_ICMP,	//0
+	OP_CAT_L3_TCP,
+	OP_CAT_L3_UDP,
+	OP_CAT_L3_OSPF,
+	OP_CAT_L3_USR1,
+	OP_CAT_L3_USR2,
+	OP_CAT_L3_IPV4_OTHER,
+	OP_CAT_L3_TOTALNUM	//7
+};
+
+enum{
+	OP_TCPUDP_PTCL_FTP,	//0
+	OP_TCPUDP_PTCL_SSH,
+	OP_TCPUDP_PTCL_TELNET,
+	OP_TCPUDP_PTCL_SMTP,
+	OP_TCPUDP_PTCL_DNS,
+	OP_TCPUDP_PTCL_DHCP,
+	OP_TCPUDP_PTCL_TFTP,
+	OP_TCPUDP_PTCL_HTTP,
+	OP_TCPUDP_PTCL_POP3,
+	OP_TCPUDP_PTCL_NEWS,
+	OP_TCPUDP_PTCL_SNTP,	//10
+	OP_TCPUDP_PTCL_NETBIOS,
+	OP_TCPUDP_PTCL_IMAP,
+	OP_TCPUDP_PTCL_SNMP,
+	OP_TCPUDP_PTCL_HTTPS,
+	OP_TCPUDP_PTCL_USR_A,
+	OP_TCPUDP_PTCL_USR_B,
+	OP_TCPUDP_PTCL_USR_C,
+	OP_TCPUDP_PTCL_USR_D,
+	OP_TCPUDP_PTCL_USR_E,
+	OP_TCPUDP_PTCL_TOTALNUM	//10 
+};
+
+enum{
+	OP_TCPUDP_USER_A,
+	OP_TCPUDP_USER_B,
+	OP_TCPUDP_USER_C_LOWER,
+	OP_TCPUDP_USER_C_UPPER,
+	OP_TCPUDP_USER_D_LOWER,
+	OP_TCPUDP_USER_D_UPPER,
+	OP_TCPUDP_USER_E_LOWER,
+	OP_TCPUDP_USER_E_UPPER,
+	OP_TCPUDP_USER_TOTALNUM
+};
+
+enum{
+	OP_TCPUDP_ACT_Q0,	//0
+	OP_TCPUDP_ACT_Q1,
+	OP_TCPUDP_ACT_Q2,
+	OP_TCPUDP_ACT_Q3,
+	OP_TCPUDP_ACT_Q4,
+	OP_TCPUDP_ACT_Q5,
+	OP_TCPUDP_ACT_Q6,
+	OP_TCPUDP_ACT_Q7,
+
+	OP_TCPUDP_ACT_TO_CPU = 9,	//9
+	OP_TCPUDP_ACT_DROP,
+	OP_TCPUDP_ACT_ALL_PORT
+};
+
+enum{
+	OP_TCPFLAG_FLAG0,
+	OP_TCPFLAG_FLAG1,
+	OP_TCPFLAG_FLAG2,
+	OP_TCPFLAG_FLAG3
+};
+
+enum{
+	OP_TCPFLAG_ACT_NONE,
+	OP_TCPFLAG_ACT_STORMCTRL,
+	OP_TCPFLAG_ACT_TO_CPU,
+	OP_TCPFLAG_ACT_DROP
+};
+
+enum{
+	OP_IPV6_HEADER_FRAG,
+	OP_IPV6_HEADER_ENACP,
+	OP_IPV6_HEADER_AUTH,
+	OP_IPV6_HEADER_ICMPV6,
+	OP_IPV6_HEADER_ICMPV6_MLD,
+	OP_IPV6_HEADER_ICMPV6_NDP,
+	OP_IPV6_HEADER_USER1,
+	OP_IPV6_HEADER_USER2,
+	OP_IPV6_HEADER_ICMPV6_USER1,
+	OP_IPV6_HEADER_ICMPV6_USER2,
+	OP_IPV6_HEADER_TOTALNUM
+};
+
+enum{
+	OP_IPV6_HEADER_ICMPV6_USER1_HIGH,
+	OP_IPV6_HEADER_ICMPV6_USER1_LOW,
+	OP_IPV6_HEADER_ICMPV6_USER2_HIGH,
+	OP_IPV6_HEADER_ICMPV6_USER2_LOW
+};
+
+#define OP_SNIFFER1_METHOD_DISABLE	0
+#define OP_SNIFFER1_METHOD_EGRESS	1
+#define OP_SNIFFER1_METHOD_INGRESS	2
+#define OP_SNIFFER1_METHOD_BOTHDIR	3
+
+#define OP_SNIFFER1_PKT_MODIFY	0
+#define OP_SNIFFER1_PKT_KEEP	1
+
+#define OP_SNIFFER1_TAG_KEEP	0
+#define OP_SNIFFER1_TAG_MODIFY	1
+
+#define OP_SNIFFER2_LUT_TRIGGER_TARGET_DA	0
+#define OP_SNIFFER2_LUT_TRIGGER_TARGET_SA	1
+
+#define OP_STORM_BCST		0x01
+#define OP_STORM_MCST		0x02
+#define OP_STORM_DLF		0x04
+#define OP_STORM_ARP		0x08
+#define OP_STORM_ICMP		0x10
+
+#define OP_EOC_STATUS_NORMAL		0
+#define OP_EOC_STATUS_LOOP_DETECTED	1
+
+#define OP_EOC_RELEASE_TIME_1MIN	1
+#define OP_EOC_RELEASE_TIME_10MIN	10
+
+#define OP_LD_TIME_UNIT_500MS		0
+#define OP_LD_TIME_UNIT_10S		1
+
+#define OP_LD_STATUS_NORMAL			0
+#define OP_LD_STATUS_LOOP_DETECTED	1
+
+#define OP_WOL_MODE_SLAVE		0
+#define OP_WOL_MODE_MASTER		1
+
+#define OP_WOL_IDLE_UNIT_DISABLE	0
+#define OP_WOL_IDLE_UNIT_10s		1
+#define OP_WOL_IDLE_UNIT_1min		2
+#define OP_WOL_IDLE_UNIT_10min		3
+
+#define OP_WOL_STATUS_NORMAL		0
+#define OP_WOL_STATUS_SLEEPING		1
+#define OP_WOL_STATUS_RDY4SLEEP		2
+#define OP_WOL_STATUS_SLEEP			3
+
+#define OP_CPU_PORT_NORMAL	0
+#define OP_CPU_PORT_CPU		1
+
+#define OP_MAC_SELF_TEST_PKT_NO_32768	32768
+#define OP_MAC_SELF_TEST_PKT_NO_4096	4096
+#define OP_MAC_SELF_TEST_PKT_NO_256		256
+#define OP_MAC_SELF_TEST_PKT_NO_16		16
+
+#define OP_MAC_SELF_TEST_RESULT_FAIL	0
+#define OP_MAC_SELF_TEST_RESULT_PASS	1
+
+#define OP_BPDU_CMODE_GLOBAL	0
+#define OP_BPDU_CMODE_BY_PORT	1
+
+#define OP_STP_STATE_DISCARD	0
+#define OP_STP_STATE_BLOCK	1
+#define OP_STP_STATE_LEARN	2
+#define OP_STP_STATE_FORWARD	3
+
+#define OP_TRUNK_HASH_METHOD_PORT_ID	0
+#define OP_TRUNK_HASH_METHOD_SA		1
+#define OP_TRUNK_HASH_METHOD_DA		2
+#define OP_TRUNK_HASH_METHOD_DA_SA	3
+#define OP_TRUNK_HASH_METHOD_DIP	4
+#define OP_TRUNK_HASH_METHOD_SIP	5
+#define OP_TRUNK_HASH_METHOD_DP		6
+#define OP_TRUNK_HASH_METHOD_SP		7
+
+#define OP_TRUNK_COMBINE_G1_G2		5
+#define OP_TRUNK_COMBINE_G3_G4		6
+#define OP_TRUNK_COMBINE_G5_G6		7
+
+#define OP_LUT_LEARN_MODE_ALL_BY_AGING_TIME	0x0
+#define OP_LUT_LEARN_MODE_NEVER_OVERWRITE	0x1
+#define	OP_LUT_LEARN_MODE_L2_BY_AGING_TIME	0x3
+
+#define	OP_HASH_DIRECT	0
+#define OP_HASH_CRC		1
+
+#define OP_LUT_UNKNOWN_SA_FWD_2_CPU		0x0
+#define	OP_LUT_UNKNOWN_SA_DROP			0x1
+#define	OP_LUT_UNKNOWN_SA_FWD			0x2
+
+/* LUT flushing */
+#define OP_LUT_FLUSH_DYNAMIC_ONLY	0x0
+#define OP_LUT_FLUSH_STATIC_ONLY	0x1//not implemented
+#define OP_LUT_FLUSH_ALL			0x2
+
+/* LUT cfg */
+#define OP_LUT_CFG_FID		0
+#define OP_LUT_CFG_MD		1 //multi-destination, not implemented
+#define OP_LUT_CFG_TRAN		2 //vlan translation
+#define OP_LUT_CFG_MVT		3 //mac-based vlan
+
+/* LUT action */
+#define OP_ENTRY_CREATE		0
+#define	OP_ENTRY_CONFIG		1
+#define	OP_ENTRY_DELETE		2
+#define OP_ENTRY_CREATE_REG	3
+
+#define OP_ENTRY_GET_BY_INDEX	4
+#define OP_ENTRY_GET_BY_INFO	5
+
+/* the state for getLutValidEntry */
+#ifndef BIT
+#define BIT(x) (1UL << (x))
+#endif
+#define	OP_LUT_STATE_DYNAMIC		BIT(0)
+#define	OP_LUT_STATE_STATIC			BIT(1)
+#define	OP_LUT_STATE_ALL			(OP_LUT_STATE_DYNAMIC|OP_LUT_STATE_STATIC)
+//#define	OP_LUT_STATE_ALL			(OP_LUT_STATE_DYNAMIC|OP_LUT_STATE_ALL_STATIC)
+
+
+enum{
+	/* target entry is valid and index values are matched */
+	OP_ENTRY_EXISTS=0xE0,
+	/* target entry is valid but index values are not matched */
+	OP_ENTRY_NOT_MATCH,
+	/* target entry is invalid */
+	OP_ENTRY_NOT_FOUND,
+	/* target dynamice entry is valid and index values are matched */
+	OP_ENTRY_EXISTS_DYNAMIC,
+};
+
+#define OP_IGMP_PACKET_QUERY			0
+#define OP_IGMP_PACKET_LEAVE			4
+#define OP_IGMP_PACKET_UN_REG_DATA		8
+#define OP_IGMP_PACKET_UN_DEFINED		12
+#define OP_IGMP_PACKET_REPORT			1
+#define OP_IGMP_PACKET_GROUP_SPECIFIC_QUERY	6
+#define OP_IGMP_PACKET_REG_DATA			11
+
+#define OP_IGMP_RULE_BCST			0x01
+#define OP_IGMP_RULE_CPU			0x02
+#define OP_IGMP_RULE_ROUTER			0x04
+#define OP_IGMP_RULE_DROP			0x08
+#define OP_IGMP_RULE_GROUP_MEM			0x10
+
+#define OP_IGMP_SLT_IPV4			4
+#define OP_IGMP_SLT_IPV6			6
+
+#define OP_MLD_SEND_TO_PORTS			0
+#define OP_MLD_SEND_TO_PORTS_AND_CPU		1
+#define OP_MLD_SEND_TO_CPU			2
+#define OP_MLD_DROP				3
+
+#define	OP_IMP_DROP_IP_MISMATCH	0
+#define	OP_IMP_DROP_IP_MATCH	1
+
+#define	OP_IMP_IPTYPE_4	0
+#define	OP_IMP_IPTYPE_6	1
+
+#define OP_VLAN_EGRESS_UNI_FRAME	0x1
+#define OP_VLAN_EGRESS_ARP_FRAME	0x2
+#define OP_VLAN_EGRESS_MULTI_FRAME	0x4
+
+#define OP_VLAN_TAGGING_BY_PORT		0x0
+#define OP_VLAN_TAGGING_BY_VID		0x1
+
+#define OP_VLAN_TYPE_GROUP	0x0
+#define	OP_VLAN_TYPE_TAG	0x1
+
+#define	OP_VLAN_PROTOCOL_INVALID	0x0
+#define	OP_VLAN_PROTOCOL_ETHER		0x1
+#define	OP_VLAN_PROTOCOL_LLC		0x2
+#define	OP_VLAN_PROTOCOL_1042		0x3
+
+enum{
+	OP_VLAN_QINQ_STAG_METHOD_ADDR,
+	OP_VLAN_QINQ_STAG_METHOD_ACL
+};
+
+#define OP_QOS_8021PEDTION_2005		0	//2005 edition
+#define OP_QOS_8021PEDTION_2005_EX		1	//2005 + exchange
+#define OP_QOS_8021PEDTION_EARLY		2 	//early
+
+#define OP_QOS_GROUP1   0
+#define OP_QOS_GROUP2   1
+
+#define OP_CPU_IF_SPEED_HIGH   0
+#define OP_CPU_IF_SPEED_NORMAL   1
+
+enum{
+  OP_QOS_MODE_FIFO,
+  OP_QOS_MODE_WWBBT,
+  OP_QOS_MODE_SP1_WWBBT7,
+  OP_QOS_MODE_SP2_WWBBT6,
+  OP_QOS_MODE_SP4_WWBBT4,
+  OP_QOS_MODE_SP8
+};
+
+enum{
+  OP_QOS_NUM_Q0,
+  OP_QOS_NUM_Q1,
+  OP_QOS_NUM_Q2,
+  OP_QOS_NUM_Q3,
+  OP_QOS_NUM_Q4,
+  OP_QOS_NUM_Q5,
+  OP_QOS_NUM_Q6,
+  OP_QOS_NUM_Q7
+};
+enum{
+  OP_QOS_UNIT_64KBS,
+  OP_QOS_UNIT_1MBS,
+  OP_QOS_UNIT_2MBS,
+  OP_QOS_UNIT_4MBS  
+};
+enum{
+  OP_QOS_REMAP_RX_Q0,
+  OP_QOS_REMAP_RX_Q1,
+  OP_QOS_REMAP_RX_Q2,
+  OP_QOS_REMAP_RX_Q3,
+  OP_QOS_REMAP_RX_Q4,
+  OP_QOS_REMAP_RX_Q5,
+  OP_QOS_REMAP_RX_Q6,
+  OP_QOS_REMAP_RX_Q7,
+  OP_QOS_REMAP_TX_Q0,
+  OP_QOS_REMAP_TX_Q1,
+  OP_QOS_REMAP_TX_Q2,
+  OP_QOS_REMAP_TX_Q3,
+  OP_QOS_REMAP_TX_Q4,
+  OP_QOS_REMAP_TX_Q5,
+  OP_QOS_REMAP_TX_Q6,
+  OP_QOS_REMAP_TX_Q7
+};
+#define OP_QOS_REMPA_RX  0
+#define OP_QOS_REMPA_TX  1 
+enum{
+	OP_QOS_METHOD_WRR,
+	OP_QOS_METHOD_BW,
+	OP_QOS_METHOD_WFQ,
+	OP_QOS_METHOD_TWRR
+};
+
+#define OP_QOS_QBASE_DBM  0
+#define OP_QOS_QBASE_SBM  1  
+
+enum{
+	OP_BW_PERIOD_4KB_500MS,
+	OP_BW_PERIOD_2KB_250MS,
+	OP_BW_PERIOD_1KB_125MS,
+	OP_BW_PERIOD_512B_63MS,
+	OP_BW_PERIOD_256B_31MS,
+	OP_BW_PERIOD_128B_16MS,
+	OP_BW_PERIOD_64B_8MS,
+	OP_BW_PERIOD_32B_4MS
+};
+
+#define OP_EEPROM_LEN_24C16	2048
+#define OP_EEPROM_LEN_24C32	4096
+
+enum Eeprom_Type {
+	OP_EE_TYPE_C16,
+	OP_EE_TYPE_C32,
+	OP_EE_TYPE_Unknow
+};
+
+#define OP_HSR_MANDATORY 0
+#define OP_HSR_UNICAST	 1
+
+#endif		/* IP1811OP_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/ip1811reg.h b/kernel/drivers/net/ethernet/ip1811/ip1811reg.h
new file mode 100644
index 0000000..a42c842
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip1811reg.h
@@ -0,0 +1,231 @@
+
+#define REG_Page			0xFF
+
+// Page0
+#define P0REG_MACBEHAVIOR			0x01
+#define P0REG_L2FRAMEGETCTRL		0x04
+#define P0REG_L2FRAMEGETCTRL1		0x05
+#define P0REG_BPDUPORTCAPCFG		0x0A
+#define P0REG_QOS8021PBASEPRIEN		0x26
+#define P0REG_QOSDSCPBASEPRIEN		0x27
+#define P0REG_QOSDSCPPRISETTING0	0x28
+#define P0REG_QOSDSCPPRISETTING1	0x29
+#define P0REG_QOSDSCPVALUE0			0x2A
+#define P0REG_QOSIPBASEPRIEN		0x31
+#define P0REG_INGRESS_RATE_CTRL0	0x40
+#define P0REG_TEST_PACKET_CTRL		0x4D
+#define P0REG_TEST_RESULT			0x4E
+#define P0REG_MACADDRESS			0x84
+#define P0REG_COSPORTBASEPRIEN		0x60
+#define P0REG_COS8021PBASEPRIEN		0x62
+#define P0REG_COSDSCPBASEPRIEN		0x64
+#define P0REG_COSTCPUDPBASEPRIEN	0x21
+#define P0REG_COSMACBASEPRIEN		0x66
+#define P0REG_COSVIDBASEPRIEN		0x68
+#define P0REG_COSIGMPBASEPRIEN		0x6A
+#define P0REG_COSPORTBASEQUEUE0		0x70
+#define P0REG_COSPORTBASEQUEUE1		0x71
+#define P0REG_COSPORTBASEQUEUE2		0x72
+#define P0REG_COSDSCPPRISETTING0	0x76
+#define P0REG_COSDSCPPRISETTING1	0x77
+#define P0REG_COSDSCPVALUE0			0x78
+#define P0REG_COSDSCPVALUE1			0x79
+#define P0REG_COSDSCPVALUE2			0x7A
+#define P0REG_COSDSCPVALUE3			0x7B
+#define P0REG_TCPUDPUSERDEF			0x10
+#define P0REG_TCPUDPPRICFG			0x18
+#define P0REG_TCPUDFUNCEN			0x1F
+#define P0REG_L3FRAMEGETCTRL		0x07
+#define P0REG_TCPCHECKEN			0x23
+#define P0REG_UDPCHECKEN			0x25
+#define P0REG_TCPFLGCFGGLB			0x30
+#define P0REG_TCPFLGCFG0			0x32
+#define P0REG_TCPFLGPORTEN			0x38
+#define P0REG_PORTLOCKEN		0x91
+#define P0REG_IPV6RLTCFG		0xA1
+#define P0REG_IPV6RLTFWD		0xA2
+#define POREG_MIBCOUN_CMD		0xA7
+#define POREG_MIBCOUN_DATA_L		0xA8
+#define POREG_MIBCOUN_DATA_H		0xA9
+#define P0REG_LDCONFIG			0xC0
+#define P0REG_LDEN			0xC1
+#define P0REG_LDTIMER			0xC3
+#define P0REG_LDSTATUS			0xCB
+#define P0REG_LDDA0			0xC4
+#define P0REG_LDSUBTYPE			0xC8
+#define P0REG_PTPCFG				0xA0
+
+// Page 1
+#define P1REG_CONFIG_CPUPORT		0x01
+#define P1REG_LUTAGINGTIME			0x02
+#define P1REG_SRCLEARNCFG			0x03
+#define P1REG_SRCLEARN_ENABLE		0x04
+#define P1REG_BSTORMTHRESH			0x09
+#define P1REG_ARPSTORMCFG			0x0A
+#define P1REG_ICMPSTORMCFG			0x0B
+#define P1REG_BSTORMEN				0x0C
+#define P1REG_MSTORMEN				0x0E
+#define P1REG_DLFSTORMEN			0x10
+#define P1REG_ARPSTORMEN			0x12
+#define P1REG_ICMPSTORMEN			0x14
+#define P1REG_OAM_8023_LB_CFG		0x14
+#define P1REG_TRUNKCFG				0x16
+#define P1REG_TRUNKGRP				0x17
+#define P1REG_SNIFCFG				0x1A
+#define P1REG_SNIFDEST				0x1B
+#define P1REG_SNIFSRC				0x1D
+#define P1REG_MEM_COMMAND			0x1D
+#define P1REG_MEM_TABLE_0			0x1E
+#define P1REG_PORTFLUSH				0x25
+#define P1REG_LUTFLUSH_CFG			0x27
+#define P1REG_LUTCFG				0x28
+#define P1REG_LUTDATA_0				0x29
+#define P1REG_LUTDATA_1				0x2A
+#define P1REG_LUTDATA_2				0x2B
+#define P1REG_LUTDATA_3				0x2C
+#define P1REG_LUTDATA_4				0x2D
+#define P1REG_LUTDATA_5				0x2E
+#define P1REG_MISCCFG				0x2F
+#define P1REG_MEM_MCT_COMMAND		0xA0
+#define P1REG_MEM_MCT_TABLE_0		0xA1
+#define P1REG_IGMPSNOP			0xA8
+#define P1REG_IGMPPKTFWD_0		0xA9
+#define P1REG_IGMPPKTFWD_1		0xAA
+#define P1REG_ROUTLIST			0xAE
+#define P1REG_MEM_SLT_COMMAND		0xB0
+#define P1REG_MEM_SLT_TABLE_0		0xB1
+#define P1REG_ACL_PATTEM_LOCATION_D3	0xD3
+#define P1REG_ACL_PATTEM_LOCATION_D4	0xD4
+#define P1REG_ACL_STORM_0			0xD7
+#define P1REG_ACL_BW_01				0xD7
+#define P1REG_ACL_TABLE_ACCESS		0xE0
+#define P1REG_ACL_TABLE_DATA_E1		0xE1
+#define P1REG_ACL_TABLE_DATA_E2		0xE2
+#define P1REG_ACL_TABLE_DATA_E3		0xE3
+#define P1REG_ACL_TABLE_DATA_E4		0xE4
+#define P1REG_ACL_TABLE_DATA_E5		0xE5
+#define P1REG_ACL_TABLE_DATA_E6		0xE6
+#define P1REG_ACL_TABLE_DATA_E7		0xE7
+#define P1REG_ACL_TABLE_DATA_E8		0xE8
+#define P1REG_ACL_TABLE_DATA_E9		0xE9
+#define P1REG_ACL_TABLE_DATA_EA		0xEA
+
+// Page2
+#define P2REG_VLANCFG				0x01
+#define P2REG_VLAN_INACTIVE_VID		0x02
+#define P2REG_VLAN_INGRESS_FRAME_0	0x04 //bit 0 for per port 
+#define P2REG_VLAN_INGRESS_FRAME_1	0x06 //bit 1 for per port
+#define P2REG_VLAN_INGRESS_CHK		0x0A
+#define P2REG_VLANLOCAL				0x0C
+#define P2REG_VLAN_EGRESS_CFG		0x0E
+#define P2REG_VLAN_EGRESS_CFG1		0x10
+#define P2REG_VLAN_EXCLUSIVE		0x11
+#define P2REG_VLAN_ADDTAG			0x13
+#define P2REG_VLAN_RMVTAG			0x15
+#define P2REG_VLAN_UPLINK			0x17
+#define P2REG_VLAN_PVIDCFG			0x20
+#define P2REG_VLANGROUP				0x40
+#define P2REG_VLAN_MACBASED_ENTRY_0	0x80
+#define P2REG_VLAN_MACBASED_UNKNOWN	0x9B
+#define P2REG_VLAN_PROCOTOL_CFG		0xA0
+#define P2REG_SPANTREE_PORTCMD		0xB2
+#define P2REG_SPANTREE_PORTDTA		0xB3
+#define P2REG_VLANCMD				0xB5
+#define P2REG_VLANDAT0				0xB6
+#define P2REG_ACL_VID_REMARK_00		0xD0
+#define P2REG_HSR_REG_SETTING_1		0xFC
+#define P2REG_HSR_REG_SETTING_2		0xFD
+
+// Page 3
+#define P3REG_AN			0x01
+#define P3REG_SPG			0x02
+#define P3REG_SP			0x03
+#define P3REG_DUPLEX		0x04
+#define P3REG_PAUSE			0x05
+#define P3REG_ASPAUSE		0x06
+#define P3REG_BPRESS		0x07
+#define P3REG_POWERDOWN		0x08
+#define P3REG_UNIDIRECT		0x09
+#define P3REG_PORTSTS0		0x10
+#define P3REG_FORCELINK		0x24
+
+// Page4
+#define P4REG_OAM_8023AH_DYING_GASP			0x01
+#define P4REG_OAM_8023AH_CFG0				0x02
+#define P4REG_OAM_8023AH_REMOTE_CMD0		0x08
+#define P4REG_OAM_8023AH_REMOTE_DAT0		0x09
+#define P4REG_OAM_8023AH_STAT0				0x10
+#define P4REG_OAM_8023AH_REMOTE_INFO_OUI	0x1B
+#define P4REG_OAM_8023AH_RECV_DAT0			0x1D
+#define P4REG_OAM_8023AH_RECV_CMD0			0x1E
+#define P4REG_OAM_8023AH_FAULT_RECORD		0x1F
+
+// Page 6
+#define P6REG_QOS_REMAP_RX0		0x19
+
+// Page 7
+#define P7REG_QINQ_RMVTAG			0x01	
+#define P7REG_QINQ_ADDTAG			0x02	
+#define P7REG_QINQEGTYPELEN			0x03
+#define P7REG_QINQ_DET_RX			0x05	
+#define P7REG_QINQ_DATA				0x06
+#define P7REG_QINQ_P_DATA			0x16
+#define P7REG_DSCP_REMARKING_01 	0x22
+#define P7REG_TXDMA					0x33
+
+// Page8
+#define P8REG_QOSMODESELGROUP1		0x01
+#define P8REG_QOSGP1_WEIGHT0		0x02
+#define P8REG_QOSGP1_MAXBDWT0		0x0A
+#define P8REG_EGRESS_RATE_CTRL0		0x4C
+#define P8REG_OUT_QUEUE_PARAM		0x5E
+#define P8REG_QOSAGINGTIME			0x37
+#define P8REG_QOSPORTAGINGEN0		0x38
+#define P8REG_QOS_REMAP_TX0			0x11
+#define P8REG_QOSGROUPSEL			0x3F
+#define P8REG_QOSMODESELGROUP2		0x3E
+#define P8REG_QOSGP2_WEIGHT0		0x40
+#define P8REG_QOSGP2_MAXBDWT0		0x48
+#define P8REG_QOSQUEUEDBMEN			0x36
+#define P8REG_QOS_SBMDBMSEL0		0x30
+
+// Page9
+#define P9REG_PTP_CLOCK_RESET		0x00
+#define P9REG_PTP_TIMESTAMP_READ	0x01
+#define P9REG_PTP_CONFIGURATION		0x02
+#define P9REG_PTP_PORT_TIMESTAMP0	0x03
+#define P9REG_PTP_PORT_TIMESTAMP1	0x04
+#define P9REG_PTP_TIMESTAMP_CLEAR0	0x05
+#define P9REG_PTP_TIMESTAMP_CLEAR1	0x06
+#define P9REG_PTP_TIMEDATA_NANOSEC0 0x07
+#define P9REG_PTP_TIMEDATA_NANOSEC1	0x08
+#define P9REG_PTP_TIMEDATA_SEC0		0x09
+#define P9REG_PTP_TIMEDATA_SEC1		0x0A
+#define P9REG_PTP_TIMEDATA_SEC2		0x0B
+#define P9REG_PTP_CLOCK_CONTROL		0x0C
+#define P9REG_PTP_FREQUENCY_ADD0	0x0D
+#define P9REG_PTP_FREQUENCY_ADD1	0x0E
+#define P9REG_PTP_CLOCK_PERIOD		0x0F
+#define P9REG_PTP_FREQUENCY_COMPENSATION0	0x10
+#define P9REG_PTP_FREQUENCY_COMPENSATION1	0x11
+#define P9REG_PTP_FREQUENCY_COMPENSATION2	0x12
+#define P9REG_PTP_FREQUENCY_COMPENSATION3	0x13
+#define P9REG_PTP_FREQUENCY_COMPENSATION_CONTROL	0x14
+#define P9REG_PTP_PROGRAMMABLE_OUTPUT	0x15
+#define P9REG_PTP_INGRESS_LATENCY_10TP	0x1A
+#define P9REG_PTP_EGRESS_LATENCY_10TP	0x1B
+#define P9REG_PTP_INGRESS_LATENCY_100TP	0x1C
+#define P9REG_PTP_EGRESS_LATENCY_100TP	0x1D
+#define P9REG_PTP_INGRESS_LATENCY_FIBER	0x20
+#define P9REG_PTP_EGRESS_LATENCY_FIBER	0x21
+
+// PageD
+
+// PageE
+#define PEREG_SW_RESET				0x00
+#define PEREG_CPUMODE				0x03
+#define PEREG_SPTAG					0x05
+#define PEREG_INT_STATUS			0x07
+#define PEREG_LAST_GASP_CONFIG		0x08
+#define PEREG_EEPROM_CMD			0x0A
+#define PEREG_EEPROM_DATA			0x0C
diff --git a/kernel/drivers/net/ethernet/ip1811/ip218.h b/kernel/drivers/net/ethernet/ip1811/ip218.h
new file mode 100644
index 0000000..4ea77f3
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/ip218.h
@@ -0,0 +1,29 @@
+#ifndef IP218_H
+#define IP218_H
+
+#if 1
+#define IP218_MAC_BASE			0xBC400000	//Virtual Address
+#else
+#define IP218_MAC_BASE			0x1C400000	//Physical Address
+#endif
+
+#define	IP218_MAC_SMICTRL0		0x0004
+#define	IP218_MAC_SMICTRL1		0x0008
+
+struct ip218_smictrl0{
+	unsigned long wr_data:16;
+	unsigned long en:1;
+	unsigned long rdwr:1;
+	unsigned long rev2:1;
+	unsigned long phy:5;
+	unsigned long rev1:3;
+	unsigned long reg:5;
+};
+
+struct ip218_smictrl1{
+	unsigned long mdc_clk_divisor:3;
+	unsigned long rev:13;
+	unsigned long rd_data:16;
+};
+
+#endif
diff --git a/kernel/drivers/net/ethernet/ip1811/libcommon.h b/kernel/drivers/net/ethernet/ip1811/libcommon.h
new file mode 100644
index 0000000..3aaa686
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/libcommon.h
@@ -0,0 +1,53 @@
+#ifndef __LIB_COMMON_H__
+#define __LIB_COMMON_H__
+#include <sys/types.h>//for u_int8_t
+
+#undef OK
+#define OK		0
+
+#undef ERROR
+#define	ERROR	-1
+
+#undef FALSE
+#define FALSE	0
+
+#undef TRUE
+#define TRUE	1
+
+#undef DISABLE
+#define DISABLE	0
+
+#undef ENABLE
+#define ENABLE	1
+
+#define FREE_SAFE(a)	if(a!=NULL){free(a);a=NULL;}
+
+#define	SV_WDT_WDT_TIME	(100)//Unit depends on WORKQUEUE_DELAY_TIME defined in supervisor.c
+
+/************************************************************
+ * Name:	getSysUptime
+ * Description: get system uptime from proc file
+ * Parameters:	None
+ * Return value:failed:		-1
+ *				success:	float type uptime
+ * **********************************************************/
+float getSysUptime(void);
+long getSysUptime_10ms(void);
+void daemonize(void);
+int lock_file(char *filename);
+int unlock_file(int fd, char *filename);
+
+void get_switch_mac(u_int8_t* macaddr);
+void get_switch_ip(u_int8_t *ip);
+void get_switch_netmask(u_int8_t *mask);
+void get_gateway_ip(u_int8_t *ip);
+void get_gateway_ipv6(u_int8_t *ipv6);
+void DER_OID_decoder(unsigned char *input_OID, unsigned int OIDLen, char *outputString);
+char popen_d(char *cmd, char *ret, unsigned int ret_len);
+void printfd(char *file, char *buf);
+char ipStr2Array(char *ip, char *buf);
+int do_fork_execvp(char *argv[]);
+int supervisor_wdt_add(char *command, const char *func_name, int wdt_life_time);
+int supervisor_wdt_del(char *command);
+int supervisor_wdt_reset(char *command);
+#endif//__LIB_COMMON_H__
diff --git a/kernel/drivers/net/ethernet/ip1811/list.h b/kernel/drivers/net/ethernet/ip1811/list.h
new file mode 100644
index 0000000..0bbafbf
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/list.h
@@ -0,0 +1,517 @@
+/**
+ * 
+ * I grub it from linux kernel source code and fix it for user space
+ * program. Of course, this is a GPL licensed header file.
+ *
+ * Here is a recipe to cook list.h for user space program
+ *
+ * 1. copy list.h from linux/include/list.h
+ * 2. remove 
+ *     - #ifdef __KERNE__ and its #endif
+ *     - all #include line
+ *     - prefetch() and rcu related functions
+ * 3. add macro offsetof() and container_of
+ *
+ * - kazutomo@mcs.anl.gov
+ */
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+#include <stddef.h>
+/**
+ * @name from other kernel headers
+ */
+/*@{*/
+
+/**
+ * Get offset of a member
+ */
+//#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * Casts a member of a structure out to the containing structure
+ * @param ptr        the pointer to the member.
+ * @param type       the type of the container struct this is embedded in.
+ * @param member     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+        (type *)( (char *)__mptr - offsetof(type,member) );})
+/*@}*/
+
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1  ((void *) 0x00100100)
+#define LIST_POISON2  ((void *) 0x00200200)
+
+/**
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+struct list_head {
+	struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+	struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+			      struct list_head *prev,
+			      struct list_head *next)
+{
+	next->prev = new;
+	new->next = next;
+	new->prev = prev;
+	prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+	__list_add(new, head->prev, head);
+}
+
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+	next->prev = prev;
+	prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	entry->next = LIST_POISON1;
+	entry->prev = LIST_POISON2;
+}
+
+
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+	__list_del(entry->prev, entry->next);
+	INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+				  struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+	return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+				 struct list_head *head)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->next;
+
+	first->prev = head;
+	head->next = first;
+
+	last->next = at;
+	at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+				    struct list_head *head)
+{
+	if (!list_empty(list)) {
+		__list_splice(list, head);
+		INIT_LIST_HEAD(list);
+	}
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:	the &struct list_head pointer.
+ * @type:	the type of the struct this is embedded in.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+	container_of(ptr, type, member)
+
+/**
+ * list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+
+#define list_for_each(pos, head) \
+  for (pos = (head)->next; pos != (head);	\
+       pos = pos->next)
+
+/**
+ * __list_for_each	-	iterate over a list
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ *
+ * This variant differs from list_for_each() in that it's the
+ * simplest possible list iteration code, no prefetching is done.
+ * Use this for code that knows the list to be very short (empty
+ * or 1 entry) most of the time.
+ */
+#define __list_for_each(pos, head) \
+	for (pos = (head)->next; pos != (head); pos = pos->next)
+
+/**
+ * list_for_each_prev	-	iterate over a list backwards
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @head:	the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+	for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
+        	pos = pos->prev)
+
+/**
+ * list_for_each_safe	-	iterate over a list safe against removal of list entry
+ * @pos:	the &struct list_head to use as a loop counter.
+ * @n:		another &struct list_head to use as temporary storage
+ * @head:	the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+	for (pos = (head)->next, n = pos->next; pos != (head); \
+		pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry	-	iterate over list of given type
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)				\
+	for (pos = list_entry((head)->next, typeof(*pos), member);	\
+	     &pos->member != (head);					\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member)			\
+	for (pos = list_entry((head)->prev, typeof(*pos), member);	\
+	     &pos->member != (head); 	\
+	     pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use as a start point in
+ *			list_for_each_entry_continue
+ * @pos:	the type * to use as a start point
+ * @head:	the head of the list
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_prepare_entry(pos, head, member) \
+	((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue -	iterate over list of given type
+ *			continuing after existing point
+ * @pos:	the type * to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_continue(pos, head, member) 		\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head);	\
+	     pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)			\
+	for (pos = list_entry((head)->next, typeof(*pos), member),	\
+		n = list_entry(pos->member.next, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue -	iterate over list of given type
+ *			continuing after existing point safe against removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) 		\
+	for (pos = list_entry(pos->member.next, typeof(*pos), member), 		\
+		n = list_entry(pos->member.next, typeof(*pos), member);		\
+	     &pos->member != (head);						\
+	     pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse - iterate backwards over list of given type safe against
+ *				      removal of list entry
+ * @pos:	the type * to use as a loop counter.
+ * @n:		another type * to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member)		\
+	for (pos = list_entry((head)->prev, typeof(*pos), member),	\
+		n = list_entry(pos->member.prev, typeof(*pos), member);	\
+	     &pos->member != (head); 					\
+	     pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+
+
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+	struct hlist_node *first;
+};
+
+struct hlist_node {
+	struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
+#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
+#define INIT_HLIST_NODE(ptr) ((ptr)->next = NULL, (ptr)->pprev = NULL)
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+	return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+	return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+	struct hlist_node *next = n->next;
+	struct hlist_node **pprev = n->pprev;
+	*pprev = next;
+	if (next)
+		next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+	__hlist_del(n);
+	n->next = LIST_POISON1;
+	n->pprev = LIST_POISON2;
+}
+
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+	if (n->pprev)  {
+		__hlist_del(n);
+		INIT_HLIST_NODE(n);
+	}
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+	struct hlist_node *first = h->first;
+	n->next = first;
+	if (first)
+		first->pprev = &n->next;
+	h->first = n;
+	n->pprev = &h->first;
+}
+
+
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+					struct hlist_node *next)
+{
+	n->pprev = next->pprev;
+	n->next = next;
+	next->pprev = &n->next;
+	*(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+					struct hlist_node *next)
+{
+	next->next = n->next;
+	n->next = next;
+	next->pprev = &n->next;
+
+	if(next->next)
+		next->next->pprev  = &next->next;
+}
+
+
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+	for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+	     pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+	for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+	     pos = n)
+
+/**
+ * hlist_for_each_entry	- iterate over list of given type
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member)			 \
+	for (pos = (head)->first;					 \
+	     pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after existing point
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member)		 \
+	for (pos = (pos)->next;						 \
+	     pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from existing point
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member)			 \
+	for (; pos && ({ prefetch(pos->next); 1;}) &&			 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos:	the type * to use as a loop counter.
+ * @pos:	the &struct hlist_node to use as a loop counter.
+ * @n:		another &struct hlist_node to use as temporary storage
+ * @head:	the head for your list.
+ * @member:	the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) 		 \
+	for (pos = (head)->first;					 \
+	     pos && ({ n = pos->next; 1; }) && 				 \
+		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+	     pos = n)
+
+
+#endif
diff --git a/kernel/drivers/net/ethernet/ip1811/port_config.h b/kernel/drivers/net/ethernet/ip1811/port_config.h
new file mode 100644
index 0000000..96e556e
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/port_config.h
@@ -0,0 +1,16 @@
+#ifndef __PORT_CONFIG_H__
+#define __PORT_CONFIG_H__
+#include "portnumber.h"
+
+#define MAX_PORT_NUM		get_MaxPort()
+#define GIGA_PORT_START		get_GPStart()
+#define GIGA_PORT_END		get_GPEnd()
+
+#define MAX_IPORT_CNT		SWITCH_MAX_IPORT_CNT
+#define	ALL_PORTS_LIST		(~(-1 << MAX_PORT_NUM))
+#define	GIGA_PORT_NUM		(GIGA_PORT_END - GIGA_PORT_START)
+#define CPU_PORT_NUM		MAX_IPORT_CNT
+#define MAX_TP_PORT_NUM		(GIGA_PORT_START -1)
+
+#endif
+
diff --git a/kernel/drivers/net/ethernet/ip1811/system_config.h b/kernel/drivers/net/ethernet/ip1811/system_config.h
new file mode 100644
index 0000000..b80d6f5
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/system_config.h
@@ -0,0 +1,36 @@
+
+#ifndef __SYSTEM_CONFIG_H__
+#define __SYSTEM_CONFIG_H__
+///////////////////////////////////////////////
+//// board config
+///////////////////////////////////////////////
+
+//#define SYSTEM_CONFIG__FPGA
+//#define SYSTEM_CONFIG__ASIC//this is ASIC_135
+//#define SYSTEM_CONFIG__ASIC125
+//#define SYSTEM_CONFIG__ASIC_135
+#define SYSTEM_CONFIG__ASIC_150
+
+
+#define SYSTEM_CONFIG__SERVER_MODE
+//#define SYSTEM_CONFIG__PCI_MODE
+
+
+///////////////////////////////////////////////
+//// DRAM parameter - ref: sdram_support_list
+///////////////////////////////////////////////
+
+#define SYSTEM_CONFIG_DRAM__ARCH_4CH
+//#define SYSTEM_CONFIG_DRAM__USED_2CHIPS
+//#define SYSTEM_CONFIG_FLASH__USED_2CHIPS
+
+//#define SYSTEM_CONFIG_DRAM__NT5SV16M16CS_6K
+//#define SYSTEM_CONFIG_DRAM__PMS308416BTR_6
+//#define SYSTEM_CONFIG_DRAM__IS42S16320D
+#define SYSTEM_CONFIG_DRAM__W9825G6KH_6I
+//#define SYSTEM_CONFIG_DRAM__A3V56S30
+
+//#define SYS_CONFIG_WITH_IP102_PHY
+
+#endif
+
diff --git a/kernel/drivers/net/ethernet/ip1811/types.h b/kernel/drivers/net/ethernet/ip1811/types.h
new file mode 100644
index 0000000..bfcfab4
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/types.h
@@ -0,0 +1,17 @@
+#ifndef _TYPES_H_
+#define _TYPES_H_
+
+typedef unsigned char		u8;
+typedef unsigned short		u16;
+typedef unsigned int		u32;
+typedef unsigned long long	u64;
+typedef char				s8;
+typedef short				s16;
+typedef int					s32;
+typedef long long			s64;
+
+#define BIT(x)	(1UL<<(x))
+
+#define err (-1)
+
+#endif
diff --git a/kernel/drivers/net/ethernet/ip1811/zconf.h b/kernel/drivers/net/ethernet/ip1811/zconf.h
new file mode 100644
index 0000000..8912fe6
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/zconf.h
@@ -0,0 +1,506 @@
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-2012 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id$ */
+
+#ifndef ZCONF_H
+#define ZCONF_H
+
+/*
+ * If you *really* need a unique prefix for all types and library functions,
+ * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
+ * Even better than compiling with -DZ_PREFIX would be to use configure to set
+ * this permanently in zconf.h using "./configure --zprefix".
+ */
+#ifdef Z_PREFIX     /* may be set to #if 1 by ./configure */
+#  define Z_PREFIX_SET
+
+/* all linked symbols */
+#  define _dist_code            z__dist_code
+#  define _length_code          z__length_code
+#  define _tr_align             z__tr_align
+#  define _tr_flush_block       z__tr_flush_block
+#  define _tr_init              z__tr_init
+#  define _tr_stored_block      z__tr_stored_block
+#  define _tr_tally             z__tr_tally
+#  define adler32               z_adler32
+#  define adler32_combine       z_adler32_combine
+#  define adler32_combine64     z_adler32_combine64
+#  ifndef Z_SOLO
+#    define compress              z_compress
+#    define compress2             z_compress2
+#    define compressBound         z_compressBound
+#  endif
+#  define crc32                 z_crc32
+#  define crc32_combine         z_crc32_combine
+#  define crc32_combine64       z_crc32_combine64
+#  define deflate               z_deflate
+#  define deflateBound          z_deflateBound
+#  define deflateCopy           z_deflateCopy
+#  define deflateEnd            z_deflateEnd
+#  define deflateInit2_         z_deflateInit2_
+#  define deflateInit_          z_deflateInit_
+#  define deflateParams         z_deflateParams
+#  define deflatePending        z_deflatePending
+#  define deflatePrime          z_deflatePrime
+#  define deflateReset          z_deflateReset
+#  define deflateResetKeep      z_deflateResetKeep
+#  define deflateSetDictionary  z_deflateSetDictionary
+#  define deflateSetHeader      z_deflateSetHeader
+#  define deflateTune           z_deflateTune
+#  define deflate_copyright     z_deflate_copyright
+#  define get_crc_table         z_get_crc_table
+#  ifndef Z_SOLO
+#    define gz_error              z_gz_error
+#    define gz_intmax             z_gz_intmax
+#    define gz_strwinerror        z_gz_strwinerror
+#    define gzbuffer              z_gzbuffer
+#    define gzclearerr            z_gzclearerr
+#    define gzclose               z_gzclose
+#    define gzclose_r             z_gzclose_r
+#    define gzclose_w             z_gzclose_w
+#    define gzdirect              z_gzdirect
+#    define gzdopen               z_gzdopen
+#    define gzeof                 z_gzeof
+#    define gzerror               z_gzerror
+#    define gzflush               z_gzflush
+#    define gzgetc                z_gzgetc
+#    define gzgetc_               z_gzgetc_
+#    define gzgets                z_gzgets
+#    define gzoffset              z_gzoffset
+#    define gzoffset64            z_gzoffset64
+#    define gzopen                z_gzopen
+#    define gzopen64              z_gzopen64
+#    ifdef _WIN32
+#      define gzopen_w              z_gzopen_w
+#    endif
+#    define gzprintf              z_gzprintf
+#    define gzputc                z_gzputc
+#    define gzputs                z_gzputs
+#    define gzread                z_gzread
+#    define gzrewind              z_gzrewind
+#    define gzseek                z_gzseek
+#    define gzseek64              z_gzseek64
+#    define gzsetparams           z_gzsetparams
+#    define gztell                z_gztell
+#    define gztell64              z_gztell64
+#    define gzungetc              z_gzungetc
+#    define gzwrite               z_gzwrite
+#  endif
+#  define inflate               z_inflate
+#  define inflateBack           z_inflateBack
+#  define inflateBackEnd        z_inflateBackEnd
+#  define inflateBackInit_      z_inflateBackInit_
+#  define inflateCopy           z_inflateCopy
+#  define inflateEnd            z_inflateEnd
+#  define inflateGetHeader      z_inflateGetHeader
+#  define inflateInit2_         z_inflateInit2_
+#  define inflateInit_          z_inflateInit_
+#  define inflateMark           z_inflateMark
+#  define inflatePrime          z_inflatePrime
+#  define inflateReset          z_inflateReset
+#  define inflateReset2         z_inflateReset2
+#  define inflateSetDictionary  z_inflateSetDictionary
+#  define inflateSync           z_inflateSync
+#  define inflateSyncPoint      z_inflateSyncPoint
+#  define inflateUndermine      z_inflateUndermine
+#  define inflateResetKeep      z_inflateResetKeep
+#  define inflate_copyright     z_inflate_copyright
+#  define inflate_fast          z_inflate_fast
+#  define inflate_table         z_inflate_table
+#  ifndef Z_SOLO
+#    define uncompress            z_uncompress
+#  endif
+#  define zError                z_zError
+#  ifndef Z_SOLO
+#    define zcalloc               z_zcalloc
+#    define zcfree                z_zcfree
+#  endif
+#  define zlibCompileFlags      z_zlibCompileFlags
+#  define zlibVersion           z_zlibVersion
+
+/* all zlib typedefs in zlib.h and zconf.h */
+#  define Byte                  z_Byte
+#  define Bytef                 z_Bytef
+#  define alloc_func            z_alloc_func
+#  define charf                 z_charf
+#  define free_func             z_free_func
+#  ifndef Z_SOLO
+#    define gzFile                z_gzFile
+#  endif
+#  define gz_header             z_gz_header
+#  define gz_headerp            z_gz_headerp
+#  define in_func               z_in_func
+#  define intf                  z_intf
+#  define out_func              z_out_func
+#  define uInt                  z_uInt
+#  define uIntf                 z_uIntf
+#  define uLong                 z_uLong
+#  define uLongf                z_uLongf
+#  define voidp                 z_voidp
+#  define voidpc                z_voidpc
+#  define voidpf                z_voidpf
+
+/* all zlib structs in zlib.h and zconf.h */
+#  define gz_header_s           z_gz_header_s
+#  define internal_state        z_internal_state
+
+#endif
+
+#if defined(__MSDOS__) && !defined(MSDOS)
+#  define MSDOS
+#endif
+#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2)
+#  define OS2
+#endif
+#if defined(_WINDOWS) && !defined(WINDOWS)
+#  define WINDOWS
+#endif
+#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
+#  ifndef WIN32
+#    define WIN32
+#  endif
+#endif
+#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
+#  if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)
+#    ifndef SYS16BIT
+#      define SYS16BIT
+#    endif
+#  endif
+#endif
+
+/*
+ * Compile with -DMAXSEG_64K if the alloc function cannot allocate more
+ * than 64k bytes at a time (needed on systems with 16-bit int).
+ */
+#ifdef SYS16BIT
+#  define MAXSEG_64K
+#endif
+#ifdef MSDOS
+#  define UNALIGNED_OK
+#endif
+
+#ifdef __STDC_VERSION__
+#  ifndef STDC
+#    define STDC
+#  endif
+#  if __STDC_VERSION__ >= 199901L
+#    ifndef STDC99
+#      define STDC99
+#    endif
+#  endif
+#endif
+#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32))
+#  define STDC
+#endif
+#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__))
+#  define STDC
+#endif
+
+#if defined(__OS400__) && !defined(STDC)    /* iSeries (formerly AS/400). */
+#  define STDC
+#endif
+
+#ifndef STDC
+#  ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */
+#    define const       /* note: need a more gentle solution here */
+#  endif
+#endif
+
+#if defined(ZLIB_CONST) && !defined(z_const)
+#  define z_const const
+#else
+#  define z_const
+#endif
+
+/* Some Mac compilers merge all .h files incorrectly: */
+#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__)
+#  define NO_DUMMY_DECL
+#endif
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#  ifdef STDC
+#    define OF(args)  args
+#  else
+#    define OF(args)  ()
+#  endif
+#endif
+
+#ifndef Z_ARG /* function prototypes for stdarg */
+#  if defined(STDC) || defined(Z_HAVE_STDARG_H)
+#    define Z_ARG(args)  args
+#  else
+#    define Z_ARG(args)  ()
+#  endif
+#endif
+
+/* The following definitions for FAR are needed only for MSDOS mixed
+ * model programming (small or medium model with some far allocations).
+ * This was tested only with MSC; for other MSDOS compilers you may have
+ * to define NO_MEMCPY in zutil.h.  If you don't need the mixed model,
+ * just define FAR to be empty.
+ */
+#ifdef SYS16BIT
+#  if defined(M_I86SM) || defined(M_I86MM)
+     /* MSC small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef _MSC_VER
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#  if (defined(__SMALL__) || defined(__MEDIUM__))
+     /* Turbo C small or medium model */
+#    define SMALL_MEDIUM
+#    ifdef __BORLANDC__
+#      define FAR _far
+#    else
+#      define FAR far
+#    endif
+#  endif
+#endif
+
+#if defined(WINDOWS) || defined(WIN32)
+   /* If building or using zlib as a DLL, define ZLIB_DLL.
+    * This is not mandatory, but it offers a little performance increase.
+    */
+#  ifdef ZLIB_DLL
+#    if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500))
+#      ifdef ZLIB_INTERNAL
+#        define ZEXTERN extern __declspec(dllexport)
+#      else
+#        define ZEXTERN extern __declspec(dllimport)
+#      endif
+#    endif
+#  endif  /* ZLIB_DLL */
+   /* If building or using zlib with the WINAPI/WINAPIV calling convention,
+    * define ZLIB_WINAPI.
+    * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI.
+    */
+#  ifdef ZLIB_WINAPI
+#    ifdef FAR
+#      undef FAR
+#    endif
+#    include <windows.h>
+     /* No need for _export, use ZLIB.DEF instead. */
+     /* For complete Windows compatibility, use WINAPI, not __stdcall. */
+#    define ZEXPORT WINAPI
+#    ifdef WIN32
+#      define ZEXPORTVA WINAPIV
+#    else
+#      define ZEXPORTVA FAR CDECL
+#    endif
+#  endif
+#endif
+
+#if defined (__BEOS__)
+#  ifdef ZLIB_DLL
+#    ifdef ZLIB_INTERNAL
+#      define ZEXPORT   __declspec(dllexport)
+#      define ZEXPORTVA __declspec(dllexport)
+#    else
+#      define ZEXPORT   __declspec(dllimport)
+#      define ZEXPORTVA __declspec(dllimport)
+#    endif
+#  endif
+#endif
+
+#ifndef ZEXTERN
+#  define ZEXTERN extern
+#endif
+#ifndef ZEXPORT
+#  define ZEXPORT
+#endif
+#ifndef ZEXPORTVA
+#  define ZEXPORTVA
+#endif
+
+#ifndef FAR
+#  define FAR
+#endif
+
+#if !defined(__MACTYPES__)
+typedef unsigned char  Byte;  /* 8 bits */
+#endif
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+
+#ifdef SMALL_MEDIUM
+   /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
+#  define Bytef Byte FAR
+#else
+   typedef Byte  FAR Bytef;
+#endif
+typedef char  FAR charf;
+typedef int   FAR intf;
+typedef uInt  FAR uIntf;
+typedef uLong FAR uLongf;
+
+#ifdef STDC
+   typedef void const *voidpc;
+   typedef void FAR   *voidpf;
+   typedef void       *voidp;
+#else
+   typedef Byte const *voidpc;
+   typedef Byte FAR   *voidpf;
+   typedef Byte       *voidp;
+#endif
+
+/* ./configure may #define Z_U4 here */
+
+#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC)
+#  include <limits.h>
+#  if (UINT_MAX == 0xffffffffUL)
+#    define Z_U4 unsigned
+#  else
+#    if (ULONG_MAX == 0xffffffffUL)
+#      define Z_U4 unsigned long
+#    else
+#      if (USHRT_MAX == 0xffffffffUL)
+#        define Z_U4 unsigned short
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef Z_U4
+   typedef Z_U4 z_crc_t;
+#else
+   typedef unsigned long z_crc_t;
+#endif
+
+#if 1    /* was set to #if 1 by ./configure */
+#  define Z_HAVE_UNISTD_H
+#endif
+
+#if 1    /* was set to #if 1 by ./configure */
+#  define Z_HAVE_STDARG_H
+#endif
+
+#ifdef STDC
+#  ifndef Z_SOLO
+#    include <sys/types.h>      /* for off_t */
+#  endif
+#endif
+
+#ifdef _WIN32
+#  include <stddef.h>           /* for wchar_t */
+#endif
+
+/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
+ * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
+ * though the former does not conform to the LFS document), but considering
+ * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
+ * equivalently requesting no 64-bit operations
+ */
+#if defined(LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1
+#  undef _LARGEFILE64_SOURCE
+#endif
+
+#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
+#  define Z_HAVE_UNISTD_H
+#endif
+#ifndef Z_SOLO
+#  if defined(Z_HAVE_UNISTD_H) || defined(LARGEFILE64_SOURCE)
+#    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
+#    ifdef VMS
+#      include <unixio.h>       /* for off_t */
+#    endif
+#    ifndef z_off_t
+#      define z_off_t off_t
+#    endif
+#  endif
+#endif
+
+#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0
+#  define Z_LFS64
+#endif
+
+#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64)
+#  define Z_LARGE64
+#endif
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64)
+#  define Z_WANT64
+#endif
+
+#if !defined(SEEK_SET) && !defined(Z_SOLO)
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#ifndef z_off_t
+#  define z_off_t long
+#endif
+
+#if !defined(_WIN32) && defined(Z_LARGE64)
+#  define z_off64_t off64_t
+#else
+#  if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO)
+#    define z_off64_t __int64
+#  else
+#    define z_off64_t z_off_t
+#  endif
+#endif
+
+/* MVS linker does not support external names larger than 8 bytes */
+#if defined(__MVS__)
+  #pragma map(deflateInit_,"DEIN")
+  #pragma map(deflateInit2_,"DEIN2")
+  #pragma map(deflateEnd,"DEEND")
+  #pragma map(deflateBound,"DEBND")
+  #pragma map(inflateInit_,"ININ")
+  #pragma map(inflateInit2_,"ININ2")
+  #pragma map(inflateEnd,"INEND")
+  #pragma map(inflateSync,"INSY")
+  #pragma map(inflateSetDictionary,"INSEDI")
+  #pragma map(compressBound,"CMBND")
+  #pragma map(inflate_table,"INTABL")
+  #pragma map(inflate_fast,"INFA")
+  #pragma map(inflate_copyright,"INCOPY")
+#endif
+
+#endif /* ZCONF_H */
diff --git a/kernel/drivers/net/ethernet/ip1811/zlib.h b/kernel/drivers/net/ethernet/ip1811/zlib.h
new file mode 100644
index 0000000..3edf3ac
--- /dev/null
+++ b/kernel/drivers/net/ethernet/ip1811/zlib.h
@@ -0,0 +1,1744 @@
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.2.7, May 2nd, 2012
+
+  Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950
+  (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format).
+*/
+
+#ifndef ZLIB_H
+#define ZLIB_H
+
+#include "zconf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ZLIB_VERSION "1.2.7"
+#define ZLIB_VERNUM 0x1270
+#define ZLIB_VER_MAJOR 1
+#define ZLIB_VER_MINOR 2
+#define ZLIB_VER_REVISION 7
+#define ZLIB_VER_SUBREVISION 0
+
+/*
+    The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed data.
+  This version of the library supports only one compression method (deflation)
+  but other algorithms will be added later and will have the same stream
+  interface.
+
+    Compression can be done in a single step if the buffers are large enough,
+  or can be done by repeated calls of the compression function.  In the latter
+  case, the application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+    The compressed data format used by default by the in-memory functions is
+  the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped
+  around a deflate stream, which is itself documented in RFC 1951.
+
+    The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio using the functions that start
+  with "gz".  The gzip format is different from the zlib format.  gzip is a
+  gzip wrapper, documented in RFC 1952, wrapped around a deflate stream.
+
+    This library can optionally read and write gzip streams in memory as well.
+
+    The zlib format was designed to be compact and fast for use in memory
+  and on communications channels.  The gzip format was designed for single-
+  file compression on file systems, has a larger header than zlib to maintain
+  directory information, and uses a different, slower check method than zlib.
+
+    The library does not install any signal handler.  The decoder checks
+  the consistency of the compressed data, so the library should never crash
+  even in case of corrupted input.
+*/
+
+typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));
+typedef void   (*free_func)  OF((voidpf opaque, voidpf address));
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    z_const Bytef *next_in;     /* next input byte */
+    uInt     avail_in;  /* number of bytes available at next_in */
+    uLong    total_in;  /* total number of input bytes read so far */
+
+    Bytef    *next_out; /* next output byte should be put there */
+    uInt     avail_out; /* remaining free space at next_out */
+    uLong    total_out; /* total number of bytes output so far */
+
+    z_const char *msg;  /* last error message, NULL if no error */
+    struct internal_state FAR *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    voidpf     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: binary or text */
+    uLong   adler;      /* adler32 value of the uncompressed data */
+    uLong   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream FAR *z_streamp;
+
+/*
+     gzip header information passed to and from zlib routines.  See RFC 1952
+  for more details on the meanings of these fields.
+*/
+typedef struct gz_header_s {
+    int     text;       /* true if compressed data believed to be text */
+    uLong   time;       /* modification time */
+    int     xflags;     /* extra flags (not used when writing a gzip file) */
+    int     os;         /* operating system */
+    Bytef   *extra;     /* pointer to extra field or Z_NULL if none */
+    uInt    extra_len;  /* extra field length (valid if extra != Z_NULL) */
+    uInt    extra_max;  /* space at extra (only when reading header) */
+    Bytef   *name;      /* pointer to zero-terminated file name or Z_NULL */
+    uInt    name_max;   /* space at name (only when reading header) */
+    Bytef   *comment;   /* pointer to zero-terminated comment or Z_NULL */
+    uInt    comm_max;   /* space at comment (only when reading header) */
+    int     hcrc;       /* true if there was or will be a header crc */
+    int     done;       /* true when done reading gzip header (not used
+                           when writing a gzip file) */
+} gz_header;
+
+typedef gz_header FAR *gz_headerp;
+
+/*
+     The application must update next_in and avail_in when avail_in has dropped
+   to zero.  It must update next_out and avail_out when avail_out has dropped
+   to zero.  The application must initialize zalloc, zfree and opaque before
+   calling the init function.  All other fields are set by the compression
+   library and must not be updated by the application.
+
+     The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree.  This can be useful for custom
+   memory management.  The compression library attaches no meaning to the
+   opaque value.
+
+     zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+     On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this if
+   the symbol MAXSEG_64K is defined (see zconf.h).  WARNING: On MSDOS, pointers
+   returned by zalloc for objects of exactly 65536 bytes *must* have their
+   offset normalized to zero.  The default allocation function provided by this
+   library ensures this (see zutil.c).  To reduce memory requirements and avoid
+   any allocation of 64K objects, at the expense of compression ratio, compile
+   the library with -DMAX_WBITS=14 (see zconf.h).
+
+     The fields total_in and total_out can be used for statistics or progress
+   reports.  After compression, total_in holds the total size of the
+   uncompressed data and may be saved for use in the decompressor (particularly
+   if the decompressor wants to decompress everything in a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+#define Z_BLOCK         5
+#define Z_TREES         6
+/* Allowed flush values; see deflate() and inflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative values
+ * are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_RLE                 3
+#define Z_FIXED               4
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_TEXT     1
+#define Z_ASCII    Z_TEXT   /* for compatibility with 1.2.2 and earlier */
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field (though see inflate()) */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+
+                        /* basic functions */
+
+ZEXTERN const char * ZEXPORT zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is not
+   compatible with the zlib.h header file used by the application.  This check
+   is automatically made by deflateInit and inflateInit.
+ */
+
+/*
+ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression.  The fields
+   zalloc, zfree and opaque must be initialized before by the caller.  If
+   zalloc and zfree are set to Z_NULL, deflateInit updates them to use default
+   allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at all
+   (the input data is simply copied a block at a time).  Z_DEFAULT_COMPRESSION
+   requests a default compromise between speed and compression (currently
+   equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if level is not a valid compression level, or
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).  msg is set to null
+   if there is no error message.  deflateInit does not perform any compression:
+   this will be done by deflate().
+*/
+
+
+ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows.  deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).  Some
+    output may be provided even if flush is not set.
+
+    Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating avail_in or avail_out accordingly; avail_out should
+  never be zero before the call.  The application can consume the compressed
+  output when it wants, for example when the output buffer is full (avail_out
+  == 0), or after each call of deflate().  If deflate returns Z_OK and with
+  zero avail_out, it must be called again after making room in the output
+  buffer because there might be more output pending.
+
+    Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to
+  decide how much data to accumulate before producing output, in order to
+  maximize compression.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far.  (In
+  particular avail_in is zero after the call if enough output space has been
+  provided before the call.) Flushing may degrade compression for some
+  compression algorithms and so it should be used only when necessary.  This
+  completes the current deflate block and follows it with an empty stored block
+  that is three bits plus filler bits to the next byte, followed by four bytes
+  (00 00 ff ff).
+
+    If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the
+  output buffer, but the output is not aligned to a byte boundary.  All of the
+  input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
+  This completes the current deflate block and follows it with an empty fixed
+  codes block that is 10 bits long.  This assures that enough bytes are output
+  in order for the decompressor to finish the block before the empty fixed code
+  block.
+
+    If flush is set to Z_BLOCK, a deflate block is completed and emitted, as
+  for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to
+  seven bits of the current block are held to be written as the next byte after
+  the next deflate block is completed.  In this case, the decompressor may not
+  be provided enough bits at this point in order to complete decompression of
+  the data provided so far to the compressor.  It may need to wait for the next
+  block to be emitted.  This is for advanced applications that need to control
+  the emission of deflate blocks.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired.  Using Z_FULL_FLUSH too often can seriously degrade
+  compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).  In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that
+  avail_out is greater than six to avoid repeated flush markers due to
+  avail_out == 0 on return.
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there was
+  enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error.  After
+  deflate has returned Z_STREAM_END, the only possible operations on the stream
+  are deflateReset or deflateEnd.
+
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step.  In this case, avail_out must be at least the
+  value returned by deflateBound (see below).  Then deflate is guaranteed to
+  return Z_STREAM_END.  If not enough output space is provided, deflate will
+  not return Z_STREAM_END, and it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so far (that is, total_in bytes).
+
+    deflate() may update strm->data_type if it can make a good guess about
+  the input data type (Z_BINARY or Z_TEXT).  In doubt, the data is considered
+  binary.  This field is only for information purposes and does not affect the
+  compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).  Note that Z_BUF_ERROR is not
+  fatal, and deflate() can be called again with more input and more output
+  space to continue compressing.
+*/
+
+
+ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded).  In the error case, msg
+   may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/*
+ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression.  The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller.  If next_in is not Z_NULL and avail_in is large enough (the
+   exact value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit() does not process any header information -- that is deferred
+   until inflate() is called.
+*/
+
+
+ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full.  It may introduce
+  some output latency (reading input without producing any output) except when
+  forced to flush.
+
+  The detailed semantics are as follows.  inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly.  If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing will
+    resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there is
+    no more input data or no more space in the output buffer (see below about
+    the flush parameter).
+
+    Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming more
+  output, and updating the next_* and avail_* values accordingly.  The
+  application can consume the uncompressed output when it wants, for example
+  when the output buffer is full (avail_out == 0), or after each call of
+  inflate().  If inflate returns Z_OK and with zero avail_out, it must be
+  called again after making room in the output buffer because there might be
+  more output pending.
+
+    The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,
+  Z_BLOCK, or Z_TREES.  Z_SYNC_FLUSH requests that inflate() flush as much
+  output as possible to the output buffer.  Z_BLOCK requests that inflate()
+  stop if and when it gets to the next deflate block boundary.  When decoding
+  the zlib or gzip format, this will cause inflate() to return immediately
+  after the header and before the first block.  When doing a raw inflate,
+  inflate() will go ahead and process the first block, and will return when it
+  gets to the end of that block, or when it runs out of data.
+
+    The Z_BLOCK option assists in appending to or combining deflate streams.
+  Also to assist in this, on return inflate() will set strm->data_type to the
+  number of unused bits in the last byte taken from strm->next_in, plus 64 if
+  inflate() is currently decoding the last block in the deflate stream, plus
+  128 if inflate() returned immediately after decoding an end-of-block code or
+  decoding the complete header up to just before the first byte of the deflate
+  stream.  The end-of-block will not be indicated until all of the uncompressed
+  data from that block has been written to strm->next_out.  The number of
+  unused bits may in general be greater than seven, except when bit 7 of
+  data_type is set, in which case the number of unused bits will be less than
+  eight.  data_type is set as noted here every time inflate() returns for all
+  flush options, and so can be used to determine the amount of currently
+  consumed input in bits.
+
+    The Z_TREES option behaves as Z_BLOCK does, but it also returns when the
+  end of each deflate block header is reached, before any actual data in that
+  block is decoded.  This allows the caller to determine the length of the
+  deflate block header for later use in random access within a deflate block.
+  256 is added to the value of strm->data_type when inflate() returns
+  immediately after reaching the end of the deflate block header.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error.  However if all decompression is to be performed in a single step (a
+  single call of inflate), the parameter flush should be set to Z_FINISH.  In
+  this case all pending input is processed and all pending output is flushed;
+  avail_out must be large enough to hold all of the uncompressed data for the
+  operation to complete.  (The size of the uncompressed data may have been
+  saved by the compressor for this purpose.) The use of Z_FINISH is not
+  required to perform an inflation in one step.  However it may be used to
+  inform inflate that a faster approach can be used for the single inflate()
+  call.  Z_FINISH also informs inflate to not maintain a sliding window if the
+  stream completes, which reduces inflate's memory footprint.  If the stream
+  does not complete, either because not all of the stream is provided or not
+  enough output space is provided, then a sliding window will be allocated and
+  inflate() can be called again to continue the operation as if Z_NO_FLUSH had
+  been used.
+
+     In this implementation, inflate() always flushes as much output as
+  possible to the output buffer, and always uses the faster approach on the
+  first call.  So the effects of the flush parameter in this implementation are
+  on the return value of inflate() as noted below, when inflate() returns early
+  when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of
+  memory for a sliding window when Z_FINISH is used.
+
+     If a preset dictionary is needed after this call (see inflateSetDictionary
+  below), inflate sets strm->adler to the Adler-32 checksum of the dictionary
+  chosen by the compressor and returns Z_NEED_DICT; otherwise it sets
+  strm->adler to the Adler-32 checksum of all output produced so far (that is,
+  total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described
+  below.  At the end of the stream, inflate() checks that its computed adler32
+  checksum is equal to that saved by the compressor and returns Z_STREAM_END
+  only if the checksum is correct.
+
+    inflate() can decompress and check either zlib-wrapped or gzip-wrapped
+  deflate data.  The header type is detected automatically, if requested when
+  initializing with inflateInit2().  Any information contained in the gzip
+  header is not retained, so applications that need that information should
+  instead use raw inflate, see inflateInit2() below, or inflateBack() and
+  perform their own processing of the gzip header and trailer.  When processing
+  gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output
+  producted so far.  The CRC-32 is checked against the gzip trailer.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect check
+  value), Z_STREAM_ERROR if the stream structure was inconsistent (for example
+  next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory,
+  Z_BUF_ERROR if no progress is possible or if there was not enough room in the
+  output buffer when Z_FINISH is used.  Note that Z_BUF_ERROR is not fatal, and
+  inflate() can be called again with more input and more output space to
+  continue decompressing.  If Z_DATA_ERROR is returned, the application may
+  then call inflateSync() to look for a good compression block if a partial
+  recovery of the data is desired.
+*/
+
+
+ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any pending
+   output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent.  In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*
+ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options.  The
+   fields next_in, zalloc, zfree and opaque must be initialized before by the
+   caller.
+
+     The method parameter is the compression method.  It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library.  Larger values of this parameter result in better
+   compression at the expense of memory usage.  The default value is 15 if
+   deflateInit is used instead.
+
+     windowBits can also be -8..-15 for raw deflate.  In this case, -windowBits
+   determines the window size.  deflate() will then generate raw deflate data
+   with no zlib header or trailer, and will not compute an adler32 check value.
+
+     windowBits can also be greater than 15 for optional gzip encoding.  Add
+   16 to windowBits to write a simple gzip header and trailer around the
+   compressed data instead of a zlib wrapper.  The gzip header will have no
+   file name, no extra data, no comment, no modification time (set to zero), no
+   header crc, and the operating system will be set to 255 (unknown).  If a
+   gzip stream is being written, strm->adler is a crc32 instead of an adler32.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state.  memLevel=1 uses minimum memory but is
+   slow and reduces compression ratio; memLevel=9 uses maximum memory for
+   optimal speed.  The default value is 8.  See zconf.h for total memory usage
+   as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm.  Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match), or Z_RLE to limit match distances to one (run-length
+   encoding).  Filtered data consists mostly of small values with a somewhat
+   random distribution.  In this case, the compression algorithm is tuned to
+   compress them better.  The effect of Z_FILTERED is to force more Huffman
+   coding and less string matching; it is somewhat intermediate between
+   Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY.  Z_RLE is designed to be almost as
+   fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data.  The
+   strategy parameter only affects the compression ratio but not the
+   correctness of the compressed output even if it is not set appropriately.
+   Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler
+   decoder for special applications.
+
+     deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid
+   method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is
+   incompatible with the version assumed by the caller (ZLIB_VERSION).  msg is
+   set to null if there is no error message.  deflateInit2 does not perform any
+   compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output.  When using the zlib format, this
+   function must be called immediately after deflateInit, deflateInit2 or
+   deflateReset, and before any call of deflate.  When doing raw deflate, this
+   function must be called either before any call of deflate, or immediately
+   after the completion of a deflate block, i.e. after all input has been
+   consumed and all output has been delivered when using any of the flush
+   options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH.  The
+   compressor and decompressor must use exactly the same dictionary (see
+   inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary.  Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size
+   provided in deflateInit or deflateInit2.  Thus the strings most likely to be
+   useful should be put at the end of the dictionary, not at the front.  In
+   addition, the current implementation of deflate will use at most the window
+   size minus 262 bytes of the provided dictionary.
+
+     Upon return of this function, strm->adler is set to the adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor.  (The adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.) If a raw deflate was requested, then the
+   adler32 value is not computed and strm->adler is not set.
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if not at a block boundary for raw deflate).  deflateSetDictionary does
+   not perform any compression: this will be done by deflate().
+*/
+
+ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter.  The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and can
+   consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.  The
+   stream will keep the same compression level and any other attributes that
+   may have been set by deflateInit2.
+
+     deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
+                                      int level,
+                                      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different strategy.
+   If the compression level is changed, the input available so far is
+   compressed with the old level (and may be flushed); the new level will take
+   effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to be
+   compressed and flushed.  In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if
+   strm->avail_out was zero.
+*/
+
+ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
+                                    int good_length,
+                                    int max_lazy,
+                                    int nice_length,
+                                    int max_chain));
+/*
+     Fine tune deflate's internal compression parameters.  This should only be
+   used by someone who understands the algorithm used by zlib's deflate for
+   searching for the best matching string, and even then only by the most
+   fanatic optimizer trying to squeeze out the last compressed bit for their
+   specific input data.  Read the deflate.c source code for the meaning of the
+   max_lazy, good_length, nice_length, and max_chain parameters.
+
+     deflateTune() can be called after deflateInit() or deflateInit2(), and
+   returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
+ */
+
+ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
+                                       uLong sourceLen));
+/*
+     deflateBound() returns an upper bound on the compressed size after
+   deflation of sourceLen bytes.  It must be called after deflateInit() or
+   deflateInit2(), and after deflateSetHeader(), if used.  This would be used
+   to allocate an output buffer for deflation in a single pass, and so would be
+   called before deflate().  If that first deflate() call is provided the
+   sourceLen input bytes, an output buffer allocated to the size returned by
+   deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed
+   to return Z_STREAM_END.  Note that it is possible for the compressed size to
+   be larger than the value returned by deflateBound() if flush options other
+   than Z_FINISH or Z_NO_FLUSH are used.
+*/
+
+ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm,
+                                       unsigned *pending,
+                                       int *bits));
+/*
+     deflatePending() returns the number of bytes and bits of output that have
+   been generated, but not yet provided in the available output.  The bytes not
+   provided would be due to the available output space having being consumed.
+   The number of bits of output not provided are between 0 and 7, where they
+   await more bits to join them in order to fill out a full byte.  If pending
+   or bits are Z_NULL, then those values are not set.
+
+     deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+ */
+
+ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     deflatePrime() inserts bits in the deflate output stream.  The intent
+   is that this function is used to start off the deflate output with the bits
+   leftover from a previous deflate stream when appending to it.  As such, this
+   function can only be used for raw deflate, and must be used before the first
+   deflate() call after a deflateInit2() or deflateReset().  bits must be less
+   than or equal to 16, and that many of the least significant bits of value
+   will be inserted in the output.
+
+     deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough
+   room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     deflateSetHeader() provides gzip header information for when a gzip
+   stream is requested by deflateInit2().  deflateSetHeader() may be called
+   after deflateInit2() or deflateReset() and before the first call of
+   deflate().  The text, time, os, extra field, name, and comment information
+   in the provided gz_header structure are written to the gzip header (xflag is
+   ignored -- the extra flags are set according to the compression level).  The
+   caller must assure that, if not Z_NULL, name and comment are terminated with
+   a zero byte, and that if extra is not Z_NULL, that extra_len bytes are
+   available there.  If hcrc is true, a gzip header crc is included.  Note that
+   the current versions of the command-line version of gzip (up through version
+   1.3.x) do not support header crc's, and will report that it is a "multi-part
+   gzip file" and give up.
+
+     If deflateSetHeader is not used, the default gzip header has text false,
+   the time set to zero, and os set to 255, with no extra, name, or comment
+   fields.  The gzip header is returned to the default state by deflateReset().
+
+     deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter.  The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library.  The default value is 15 if inflateInit is used
+   instead.  windowBits must be greater than or equal to the windowBits value
+   provided to deflateInit2() while compressing, or it must be equal to 15 if
+   deflateInit2() was not used.  If a compressed stream with a larger window
+   size is given as input, inflate() will return with the error code
+   Z_DATA_ERROR instead of trying to allocate a larger window.
+
+     windowBits can also be zero to request that inflate use the window size in
+   the zlib header of the compressed stream.
+
+     windowBits can also be -8..-15 for raw inflate.  In this case, -windowBits
+   determines the window size.  inflate() will then process raw deflate data,
+   not looking for a zlib or gzip header, not generating a check value, and not
+   looking for any check values for comparison at the end of the stream.  This
+   is for use with other formats that use the deflate compressed data format
+   such as zip.  Those formats provide their own check values.  If a custom
+   format is developed using the raw deflate format for compressed data, it is
+   recommended that a check value such as an adler32 or a crc32 be applied to
+   the uncompressed data as is done in the zlib, gzip, and zip formats.  For
+   most applications, the zlib format should be used as is.  Note that comments
+   above on the use in deflateInit2() applies to the magnitude of windowBits.
+
+     windowBits can also be greater than 15 for optional gzip decoding.  Add
+   32 to windowBits to enable zlib and gzip decoding with automatic header
+   detection, or add 16 to decode only the gzip format (the zlib format will
+   return a Z_DATA_ERROR).  If a gzip stream is being decoded, strm->adler is a
+   crc32 instead of an adler32.
+
+     inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller, or Z_STREAM_ERROR if the parameters are
+   invalid, such as a null pointer to the structure.  msg is set to null if
+   there is no error message.  inflateInit2 does not perform any decompression
+   apart from possibly reading the zlib header if present: actual decompression
+   will be done by inflate().  (So next_in and avail_in may be modified, but
+   next_out and avail_out are unused and unchanged.) The current implementation
+   of inflateInit2() does not process any header information -- that is
+   deferred until inflate() is called.
+*/
+
+ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
+                                             const Bytef *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence.  This function must be called immediately after a call of inflate,
+   if that call returned Z_NEED_DICT.  The dictionary chosen by the compressor
+   can be determined from the adler32 value returned by that call of inflate.
+   The compressor and decompressor must use exactly the same dictionary (see
+   deflateSetDictionary).  For raw inflate, this function can be called at any
+   time to set the dictionary.  If the provided dictionary is smaller than the
+   window and there is already data in the window, then the provided dictionary
+   will amend what's there.  The application must insure that the dictionary
+   that was used for compression is provided.
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (e.g.  dictionary being Z_NULL) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect adler32 value).  inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
+/*
+     Skips invalid compressed data until a possible full flush point (see above
+   for the description of deflate with Z_FULL_FLUSH) can be found, or until all
+   available input is skipped.  No output is provided.
+
+     inflateSync searches for a 00 00 FF FF pattern in the compressed data.
+   All full flush points have this pattern, but not all occurences of this
+   pattern are full flush points.
+
+     inflateSync returns Z_OK if a possible full flush point has been found,
+   Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point
+   has been found, or Z_STREAM_ERROR if the stream structure was inconsistent.
+   In the success case, the application may save the current current value of
+   total_in which indicates where valid compressed data was found.  In the
+   error case, the application may repeatedly call inflateSync, providing more
+   input each time, until success or end of the input data.
+*/
+
+ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when randomly accessing a large stream.  The
+   first pass through the stream can periodically record the inflate state,
+   allowing restarting inflate at those points when randomly accessing the
+   stream.
+
+     inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being Z_NULL).  msg is left unchanged in both source and
+   destination.
+*/
+
+ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.  The
+   stream will keep attributes that may have been set by inflateInit2.
+
+     inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL).
+*/
+
+ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm,
+                                      int windowBits));
+/*
+     This function is the same as inflateReset, but it also permits changing
+   the wrap and window size requests.  The windowBits parameter is interpreted
+   the same as it is for inflateInit2.
+
+     inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being Z_NULL), or if
+   the windowBits parameter is invalid.
+*/
+
+ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm,
+                                     int bits,
+                                     int value));
+/*
+     This function inserts bits in the inflate input stream.  The intent is
+   that this function is used to start inflating at a bit position in the
+   middle of a byte.  The provided bits will be used before any bytes are used
+   from next_in.  This function should only be used with raw inflate, and
+   should be used before the first inflate() call after inflateInit2() or
+   inflateReset().  bits must be less than or equal to 16, and that many of the
+   least significant bits of value will be inserted in the input.
+
+     If bits is negative, then the input stream bit buffer is emptied.  Then
+   inflatePrime() can be called again to put bits in the buffer.  This is used
+   to clear out bits leftover after feeding inflate a block description prior
+   to feeding inflate codes.
+
+     inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
+/*
+     This function returns two values, one in the lower 16 bits of the return
+   value, and the other in the remaining upper bits, obtained by shifting the
+   return value down 16 bits.  If the upper value is -1 and the lower value is
+   zero, then inflate() is currently decoding information outside of a block.
+   If the upper value is -1 and the lower value is non-zero, then inflate is in
+   the middle of a stored block, with the lower value equaling the number of
+   bytes from the input remaining to copy.  If the upper value is not -1, then
+   it is the number of bits back from the current bit position in the input of
+   the code (literal or length/distance pair) currently being processed.  In
+   that case the lower value is the number of bytes already emitted for that
+   code.
+
+     A code is being processed if inflate is waiting for more input to complete
+   decoding of the code, or if it has completed decoding but is waiting for
+   more output space to write the literal or match data.
+
+     inflateMark() is used to mark locations in the input data for random
+   access, which may be at bit positions, and to note those cases where the
+   output of a code may span boundaries of random access blocks.  The current
+   location in the input stream can be determined from avail_in and data_type
+   as noted in the description for the Z_BLOCK flush parameter for inflate.
+
+     inflateMark returns the value noted above or -1 << 16 if the provided
+   source stream state was inconsistent.
+*/
+
+ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm,
+                                         gz_headerp head));
+/*
+     inflateGetHeader() requests that gzip header information be stored in the
+   provided gz_header structure.  inflateGetHeader() may be called after
+   inflateInit2() or inflateReset(), and before the first call of inflate().
+   As inflate() processes the gzip stream, head->done is zero until the header
+   is completed, at which time head->done is set to one.  If a zlib stream is
+   being decoded, then head->done is set to -1 to indicate that there will be
+   no gzip header information forthcoming.  Note that Z_BLOCK or Z_TREES can be
+   used to force inflate() to return immediately after header processing is
+   complete and before any actual data is decompressed.
+
+     The text, time, xflags, and os fields are filled in with the gzip header
+   contents.  hcrc is set to true if there is a header CRC.  (The header CRC
+   was valid if done is set to one.) If extra is not Z_NULL, then extra_max
+   contains the maximum number of bytes to write to extra.  Once done is true,
+   extra_len contains the actual extra field length, and extra contains the
+   extra field, or that field truncated if extra_max is less than extra_len.
+   If name is not Z_NULL, then up to name_max characters are written there,
+   terminated with a zero unless the length is greater than name_max.  If
+   comment is not Z_NULL, then up to comm_max characters are written there,
+   terminated with a zero unless the length is greater than comm_max.  When any
+   of extra, name, or comment are not Z_NULL and the respective field is not
+   present in the header, then that field is set to Z_NULL to signal its
+   absence.  This allows the use of deflateSetHeader() with the returned
+   structure to duplicate the header.  However if those fields are set to
+   allocated memory, then the application will need to save those pointers
+   elsewhere so that they can be eventually freed.
+
+     If inflateGetHeader is not used, then the header information is simply
+   discarded.  The header is always checked for validity, including the header
+   CRC if present.  inflateReset() will reset the process to discard the header
+   information.  The application would need to call inflateGetHeader() again to
+   retrieve the header from the next gzip stream.
+
+     inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent.
+*/
+
+/*
+ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits,
+                                        unsigned char FAR *window));
+
+     Initialize the internal stream state for decompression using inflateBack()
+   calls.  The fields zalloc, zfree and opaque in strm must be initialized
+   before the call.  If zalloc and zfree are Z_NULL, then the default library-
+   derived memory allocation routines are used.  windowBits is the base two
+   logarithm of the window size, in the range 8..15.  window is a caller
+   supplied buffer of that size.  Except for special applications where it is
+   assured that deflate was used with small window sizes, windowBits must be 15
+   and a 32K byte window must be supplied to be able to decompress general
+   deflate streams.
+
+     See inflateBack() for the usage of these routines.
+
+     inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of
+   the parameters are invalid, Z_MEM_ERROR if the internal state could not be
+   allocated, or Z_VERSION_ERROR if the version of the library does not match
+   the version of the header file.
+*/
+
+typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *));
+typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned));
+
+ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm,
+                                    in_func in, void FAR *in_desc,
+                                    out_func out, void FAR *out_desc));
+/*
+     inflateBack() does a raw inflate with a single call using a call-back
+   interface for input and output.  This is more efficient than inflate() for
+   file i/o applications in that it avoids copying between the output and the
+   sliding window by simply making the window itself the output buffer.  This
+   function trusts the application to not change the output buffer passed by
+   the output function, at least until inflateBack() returns.
+
+     inflateBackInit() must be called first to allocate the internal state
+   and to initialize the state with the user-provided window buffer.
+   inflateBack() may then be used multiple times to inflate a complete, raw
+   deflate stream with each call.  inflateBackEnd() is then called to free the
+   allocated state.
+
+     A raw deflate stream is one with no zlib or gzip header or trailer.
+   This routine would normally be used in a utility that reads zip or gzip
+   files and writes out uncompressed files.  The utility would decode the
+   header and process the trailer on its own, hence this routine expects only
+   the raw deflate stream to decompress.  This is different from the normal
+   behavior of inflate(), which expects either a zlib or gzip header and
+   trailer around the deflate stream.
+
+     inflateBack() uses two subroutines supplied by the caller that are then
+   called by inflateBack() for input and output.  inflateBack() calls those
+   routines until it reads a complete deflate stream and writes out all of the
+   uncompressed data, or until it encounters an error.  The function's
+   parameters and return types are defined above in the in_func and out_func
+   typedefs.  inflateBack() will call in(in_desc, &buf) which should return the
+   number of bytes of provided input, and a pointer to that input in buf.  If
+   there is no input available, in() must return zero--buf is ignored in that
+   case--and inflateBack() will return a buffer error.  inflateBack() will call
+   out(out_desc, buf, len) to write the uncompressed data buf[0..len-1].  out()
+   should return zero on success, or non-zero on failure.  If out() returns
+   non-zero, inflateBack() will return with an error.  Neither in() nor out()
+   are permitted to change the contents of the window provided to
+   inflateBackInit(), which is also the buffer that out() uses to write from.
+   The length written by out() will be at most the window size.  Any non-zero
+   amount of input may be provided by in().
+
+     For convenience, inflateBack() can be provided input on the first call by
+   setting strm->next_in and strm->avail_in.  If that input is exhausted, then
+   in() will be called.  Therefore strm->next_in must be initialized before
+   calling inflateBack().  If strm->next_in is Z_NULL, then in() will be called
+   immediately for input.  If strm->next_in is not Z_NULL, then strm->avail_in
+   must also be initialized, and then if strm->avail_in is not zero, input will
+   initially be taken from strm->next_in[0 ..  strm->avail_in - 1].
+
+     The in_desc and out_desc parameters of inflateBack() is passed as the
+   first parameter of in() and out() respectively when they are called.  These
+   descriptors can be optionally used to pass any information that the caller-
+   supplied in() and out() functions need to do their job.
+
+     On return, inflateBack() will set strm->next_in and strm->avail_in to
+   pass back any unused input that was provided by the last in() call.  The
+   return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR
+   if in() or out() returned an error, Z_DATA_ERROR if there was a format error
+   in the deflate stream (in which case strm->msg is set to indicate the nature
+   of the error), or Z_STREAM_ERROR if the stream was not properly initialized.
+   In the case of Z_BUF_ERROR, an input or output error can be distinguished
+   using strm->next_in which will be Z_NULL only if in() returned an error.  If
+   strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning
+   non-zero.  (in() will always be called before out(), so strm->next_in is
+   assured to be defined if out() returns non-zero.) Note that inflateBack()
+   cannot return Z_OK.
+*/
+
+ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
+/*
+     All memory allocated by inflateBackInit() is freed.
+
+     inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream
+   state was inconsistent.
+*/
+
+ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
+/* Return flags indicating compile-time options.
+
+    Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other:
+     1.0: size of uInt
+     3.2: size of uLong
+     5.4: size of voidpf (pointer)
+     7.6: size of z_off_t
+
+    Compiler, assembler, and debug options:
+     8: DEBUG
+     9: ASMV or ASMINF -- use ASM code
+     10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention
+     11: 0 (reserved)
+
+    One-time table building (smaller code, but not thread-safe if true):
+     12: BUILDFIXED -- build static block decoding tables when needed
+     13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed
+     14,15: 0 (reserved)
+
+    Library content (indicates missing functionality):
+     16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking
+                          deflate code when not needed)
+     17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect
+                    and decode gzip streams (to avoid linking crc code)
+     18-19: 0 (reserved)
+
+    Operation variations (changes in library functionality):
+     20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate
+     21: FASTEST -- deflate algorithm with only one, lowest compression level
+     22,23: 0 (reserved)
+
+    The sprintf variant used by gzprintf (zero is best):
+     24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format
+     25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure!
+     26: 0 = returns value, 1 = void -- 1 means inferred string length returned
+
+    Remainder:
+     27-31: 0 (reserved)
+ */
+
+#ifndef Z_SOLO
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the basic
+   stream-oriented functions.  To simplify the interface, some default options
+   are assumed (compression level and memory usage, standard memory allocation
+   functions).  The source code of these utility functions can be modified if
+   you need special options.
+*/
+
+ZEXTERN int ZEXPORT compress OF((Bytef *dest,   uLongf *destLen,
+                                 const Bytef *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
+                                  const Bytef *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer.  The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer.  Upon entry, destLen is the total size of the
+   destination buffer, which must be at least the value returned by
+   compressBound(sourceLen).  Upon exit, destLen is the actual size of the
+   compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
+/*
+     compressBound() returns an upper bound on the compressed size after
+   compress() or compress2() on sourceLen bytes.  It would be used before a
+   compress() or compress2() call to allocate the destination buffer.
+*/
+
+ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
+                                   const Bytef *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer.  Upon entry, destLen is the total size
+   of the destination buffer, which must be large enough to hold the entire
+   uncompressed data.  (The size of the uncompressed data must have been saved
+   previously by the compressor and transmitted to the decompressor by some
+   mechanism outside the scope of this compression library.) Upon exit, destLen
+   is the actual size of the uncompressed buffer.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.  In
+   the case where there is not enough room, uncompress() will fill the output
+   buffer with the uncompressed data up to that point.
+*/
+
+                        /* gzip file access functions */
+
+/*
+     This library supports reading and writing files in gzip (.gz) format with
+   an interface similar to that of stdio, using the functions that start with
+   "gz".  The gzip format is different from the zlib format.  gzip is a gzip
+   wrapper, documented in RFC 1952, wrapped around a deflate stream.
+*/
+
+typedef struct gzFile_s *gzFile;    /* semi-opaque gzip file descriptor */
+
+/*
+ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
+
+     Opens a gzip (.gz) file for reading or writing.  The mode parameter is as
+   in fopen ("rb" or "wb") but can also include a compression level ("wb9") or
+   a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only
+   compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F'
+   for fixed code compression as in "wb9F".  (See the description of
+   deflateInit2 for more information about the strategy parameter.)  'T' will
+   request transparent writing or appending with no compression and not using
+   the gzip format.
+
+     "a" can be used instead of "w" to request that the gzip stream that will
+   be written be appended to the file.  "+" will result in an error, since
+   reading and writing to the same gzip file is not supported.  The addition of
+   "x" when writing will create the file exclusively, which fails if the file
+   already exists.  On systems that support it, the addition of "e" when
+   reading or writing will set the flag to close the file on an execve() call.
+
+     These functions, as well as gzip, will read and decode a sequence of gzip
+   streams in a file.  The append function of gzopen() can be used to create
+   such a file.  (Also see gzflush() for another way to do this.)  When
+   appending, gzopen does not test whether the file begins with a gzip stream,
+   nor does it look for the end of the gzip streams to begin appending.  gzopen
+   will simply append a gzip stream to the existing file.
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.  When
+   reading, this will be detected automatically by looking for the magic two-
+   byte gzip header.
+
+     gzopen returns NULL if the file could not be opened, if there was
+   insufficient memory to allocate the gzFile state, or if an invalid mode was
+   specified (an 'r', 'w', or 'a' was not provided, or '+' was provided).
+   errno can be checked to determine if the reason gzopen failed was that the
+   file could not be opened.
+*/
+
+ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
+/*
+     gzdopen associates a gzFile with the file descriptor fd.  File descriptors
+   are obtained from calls like open, dup, creat, pipe or fileno (if the file
+   has been previously opened with fopen).  The mode parameter is as in gzopen.
+
+     The next call of gzclose on the returned gzFile will also close the file
+   descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor
+   fd.  If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd,
+   mode);.  The duplicated descriptor should be saved to avoid a leak, since
+   gzdopen does not close fd if it fails.  If you are using fileno() to get the
+   file descriptor from a FILE *, then you will have to use dup() to avoid
+   double-close()ing the file descriptor.  Both gzclose() and fclose() will
+   close the associated file descriptor, so they need to have different file
+   descriptors.
+
+     gzdopen returns NULL if there was insufficient memory to allocate the
+   gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not
+   provided, or '+' was provided), or if fd is -1.  The file descriptor is not
+   used until the next gz* read, write, seek, or close operation, so gzdopen
+   will not detect if fd is invalid (unless fd is -1).
+*/
+
+ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
+/*
+     Set the internal buffer size used by this library's functions.  The
+   default buffer size is 8192 bytes.  This function must be called after
+   gzopen() or gzdopen(), and before any other calls that read or write the
+   file.  The buffer memory allocation is always deferred to the first read or
+   write.  Two buffers are allocated, either both of the specified size when
+   writing, or one of the specified size and the other twice that size when
+   reading.  A larger buffer size of, for example, 64K or 128K bytes will
+   noticeably increase the speed of decompression (reading).
+
+     The new buffer size also affects the maximum length for gzprintf().
+
+     gzbuffer() returns 0 on success, or -1 on failure, such as being called
+   too late.
+*/
+
+ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy.  See the description
+   of deflateInit2 for the meaning of these parameters.
+
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.  If
+   the input file is not in gzip format, gzread copies the given number of
+   bytes into the buffer directly from the file.
+
+     After reaching the end of a gzip stream in the input, gzread will continue
+   to read, looking for another gzip stream.  Any number of gzip streams may be
+   concatenated in the input file, and will all be decompressed by gzread().
+   If something other than a gzip stream is encountered after a gzip stream,
+   that remaining trailing garbage is ignored (and no error is returned).
+
+     gzread can be used to read a gzip file that is being concurrently written.
+   Upon reaching the end of the input, gzread will return with the available
+   data.  If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then
+   gzclearerr can be used to clear the end of file indicator in order to permit
+   gzread to be tried again.  Z_OK indicates that a gzip stream was completed
+   on the last gzread.  Z_BUF_ERROR indicates that the input file ended in the
+   middle of a gzip stream.  Note that gzread does not return -1 in the event
+   of an incomplete gzip stream.  This error is deferred until gzclose(), which
+   will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip
+   stream.  Alternatively, gzerror can be used before gzclose to detect this
+   case.
+
+     gzread returns the number of uncompressed bytes actually read, less than
+   len for end of file, or -1 for error.
+*/
+
+ZEXTERN int ZEXPORT gzwrite OF((gzFile file,
+                                voidpc buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes written or 0 in case of
+   error.
+*/
+
+ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the arguments to the compressed file under
+   control of the format string, as in fprintf.  gzprintf returns the number of
+   uncompressed bytes actually written, or 0 in case of error.  The number of
+   uncompressed bytes written is limited to 8191, or one less than the buffer
+   size given to gzbuffer().  The caller should assure that this limit is not
+   exceeded.  If it is exceeded, then gzprintf() will return an error (0) with
+   nothing written.  In this case, there may also be a buffer overflow with
+   unpredictable consequences, which is possible only if zlib was compiled with
+   the insecure functions sprintf() or vsprintf() because the secure snprintf()
+   or vsnprintf() functions were not available.  This can be determined using
+   zlibCompileFlags().
+*/
+
+ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
+/*
+     Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+
+     gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
+/*
+     Reads bytes from the compressed file until len-1 characters are read, or a
+   newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  If any characters are read or if len == 1, the
+   string is terminated with a null character.  If no characters are read due
+   to an end-of-file or len < 1, then the buffer is left untouched.
+
+     gzgets returns buf which is a null-terminated string, or it returns NULL
+   for end-of-file or in case of error.  If there was an error, the contents at
+   buf are indeterminate.
+*/
+
+ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
+/*
+     Writes c, converted to an unsigned char, into the compressed file.  gzputc
+   returns the value that was written, or -1 in case of error.
+*/
+
+ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
+/*
+     Reads one byte from the compressed file.  gzgetc returns this byte or -1
+   in case of end of file or error.  This is implemented as a macro for speed.
+   As such, it does not do all of the checking the other functions do.  I.e.
+   it does not check to see if file is NULL, nor whether the structure file
+   points to has been clobbered or not.
+*/
+
+ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
+/*
+     Push one character back onto the stream to be read as the first character
+   on the next read.  At least one character of push-back is allowed.
+   gzungetc() returns the character pushed, or -1 on failure.  gzungetc() will
+   fail if c is -1, and may fail if a character has been pushed but not read
+   yet.  If gzungetc is used immediately after gzopen or gzdopen, at least the
+   output buffer size of pushed characters is allowed.  (See gzbuffer above.)
+   The pushed character will be discarded if the stream is repositioned with
+   gzseek() or gzrewind().
+*/
+
+ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file.  The parameter flush
+   is as in the deflate() function.  The return value is the zlib error number
+   (see function gzerror below).  gzflush is only permitted when writing.
+
+     If the flush parameter is Z_FINISH, the remaining data is written and the
+   gzip stream is completed in the output.  If gzwrite() is called again, a new
+   gzip stream will be started in the output.  gzread() is able to read such
+   concatented gzip streams.
+
+     gzflush should be called only when strictly necessary because it will
+   degrade compression if called too often.
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file,
+                                   z_off_t offset, int whence));
+
+     Sets the starting position for the next gzread or gzwrite on the given
+   compressed file.  The offset represents a number of bytes in the
+   uncompressed data stream.  The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow.  If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+     gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+ZEXTERN int ZEXPORT    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+     gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT    gztell OF((gzFile file));
+
+     Returns the starting position for the next gzread or gzwrite on the given
+   compressed file.  This position represents a number of bytes in the
+   uncompressed data stream, and is zero when starting, even if appending or
+   reading a gzip stream from the middle of a file using gzdopen().
+
+     gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+/*
+ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file));
+
+     Returns the current offset in the file being read or written.  This offset
+   includes the count of bytes that precede the gzip stream, for example when
+   appending or when using gzdopen() for reading.  When reading, the offset
+   does not include as yet unused buffered input.  This information can be used
+   for a progress indicator.  On error, gzoffset() returns -1.
+*/
+
+ZEXTERN int ZEXPORT gzeof OF((gzFile file));
+/*
+     Returns true (1) if the end-of-file indicator has been set while reading,
+   false (0) otherwise.  Note that the end-of-file indicator is set only if the
+   read tried to go past the end of the input, but came up short.  Therefore,
+   just like feof(), gzeof() may return false even if there is no more data to
+   read, in the event that the last read request was for the exact number of
+   bytes remaining in the input file.  This will happen if the input file size
+   is an exact multiple of the buffer size.
+
+     If gzeof() returns true, then the read functions will return no more data,
+   unless the end-of-file indicator is reset by gzclearerr() and the input file
+   has grown since the previous end of file was detected.
+*/
+
+ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
+/*
+     Returns true (1) if file is being copied directly while reading, or false
+   (0) if file is a gzip stream being decompressed.
+
+     If the input file is empty, gzdirect() will return true, since the input
+   does not contain a gzip stream.
+
+     If gzdirect() is used immediately after gzopen() or gzdopen() it will
+   cause buffers to be allocated to allow reading the file to determine if it
+   is a gzip file.  Therefore if gzbuffer() is used, it should be called before
+   gzdirect().
+
+     When writing, gzdirect() returns true (1) if transparent writing was
+   requested ("wT" for the gzopen() mode), or false (0) otherwise.  (Note:
+   gzdirect() is not needed when writing.  Transparent writing must be
+   explicitly requested, so the application already knows the answer.  When
+   linking statically, using gzdirect() will include all of the zlib code for
+   gzip file reading and decompression, which may not be desired.)
+*/
+
+ZEXTERN int ZEXPORT    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file and
+   deallocates the (de)compression state.  Note that once file is closed, you
+   cannot call gzerror with file, since its structures have been deallocated.
+   gzclose must not be called more than once on the same file, just as free
+   must not be called more than once on the same allocation.
+
+     gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a
+   file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the
+   last read ended in the middle of a gzip stream, or Z_OK on success.
+*/
+
+ZEXTERN int ZEXPORT gzclose_r OF((gzFile file));
+ZEXTERN int ZEXPORT gzclose_w OF((gzFile file));
+/*
+     Same as gzclose(), but gzclose_r() is only for use when reading, and
+   gzclose_w() is only for use when writing or appending.  The advantage to
+   using these instead of gzclose() is that they avoid linking in zlib
+   compression or decompression code that is not used when only reading or only
+   writing respectively.  If gzclose() is used, then both compression and
+   decompression code will be included the application when linking to a static
+   zlib library.
+*/
+
+ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the given
+   compressed file.  errnum is set to zlib error number.  If an error occurred
+   in the file system and not in the compression library, errnum is set to
+   Z_ERRNO and the application may consult errno to get the exact error code.
+
+     The application must not modify the returned string.  Future calls to
+   this function may invalidate the previously returned string.  If file is
+   closed, then the string previously returned by gzerror will no longer be
+   available.
+
+     gzerror() should be used to distinguish errors from end-of-file for those
+   functions above that do not distinguish those cases in their return values.
+*/
+
+ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
+/*
+     Clears the error and end-of-file flags for file.  This is analogous to the
+   clearerr() function in stdio.  This is useful for continuing to read a gzip
+   file that is being written concurrently.
+*/
+
+#endif /* !Z_SOLO */
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the compression
+   library.
+*/
+
+ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum.  If buf is Z_NULL, this function returns the
+   required initial value for the checksum.
+
+     An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster.
+
+   Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
+                                          z_off_t len2));
+
+     Combine two Adler-32 checksums into one.  For two sequences of bytes, seq1
+   and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
+   each, adler1 and adler2.  adler32_combine() returns the Adler-32 checksum of
+   seq1 and seq2 concatenated, requiring only adler1, adler2, and len2.  Note
+   that the z_off_t type (like off_t) is a signed integer.  If len2 is
+   negative, the result has no meaning or utility.
+*/
+
+ZEXTERN uLong ZEXPORT crc32   OF((uLong crc, const Bytef *buf, uInt len));
+/*
+     Update a running CRC-32 with the bytes buf[0..len-1] and return the
+   updated CRC-32.  If buf is Z_NULL, this function returns the required
+   initial value for the crc.  Pre- and post-conditioning (one's complement) is
+   performed within this function so it shouldn't be done by the application.
+
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+/*
+ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
+
+     Combine two CRC-32 check values into one.  For two sequences of bytes,
+   seq1 and seq2 with lengths len1 and len2, CRC-32 check values were
+   calculated for each, crc1 and crc2.  crc32_combine() returns the CRC-32
+   check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and
+   len2.
+*/
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits,
+                                         unsigned char FAR *window,
+                                         const char *version,
+                                         int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy), ZLIB_VERSION, (int)sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, \
+                      (int)sizeof(z_stream))
+#define inflateBackInit(strm, windowBits, window) \
+        inflateBackInit_((strm), (windowBits), (window), \
+                      ZLIB_VERSION, (int)sizeof(z_stream))
+
+#ifndef Z_SOLO
+
+/* gzgetc() macro and its supporting function and exposed data structure.  Note
+ * that the real internal state is much larger than the exposed structure.
+ * This abbreviated structure exposes just enough for the gzgetc() macro.  The
+ * user should not mess with these exposed elements, since their names or
+ * behavior could change in the future, perhaps even capriciously.  They can
+ * only be used by the gzgetc() macro.  You have been warned.
+ */
+struct gzFile_s {
+    unsigned have;
+    unsigned char *next;
+    z_off64_t pos;
+};
+ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));  /* backward compatibility */
+#ifdef Z_PREFIX_SET
+#  undef z_gzgetc
+#  define z_gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#else
+#  define gzgetc(g) \
+          ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : gzgetc(g))
+#endif
+
+/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
+ * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
+ * both are true, the application gets the *64 functions, and the regular
+ * functions are changed to 64 bits) -- in case these are set on systems
+ * without large file support, _LFS64_LARGEFILE must also be true
+ */
+#ifdef Z_LARGE64
+   ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+   ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
+   ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
+   ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
+   ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
+#endif
+
+#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
+#  ifdef Z_PREFIX_SET
+#    define z_gzopen z_gzopen64
+#    define z_gzseek z_gzseek64
+#    define z_gztell z_gztell64
+#    define z_gzoffset z_gzoffset64
+#    define z_adler32_combine z_adler32_combine64
+#    define z_crc32_combine z_crc32_combine64
+#  else
+#    define gzopen gzopen64
+#    define gzseek gzseek64
+#    define gztell gztell64
+#    define gzoffset gzoffset64
+#    define adler32_combine adler32_combine64
+#    define crc32_combine crc32_combine64
+#  endif
+#  ifndef Z_LARGE64
+     ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
+     ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int));
+     ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile));
+     ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
+     ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
+     ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
+#  endif
+#else
+   ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
+   ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int));
+   ZEXTERN z_off_t ZEXPORT gztell OF((gzFile));
+   ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+#endif
+
+#else /* Z_SOLO */
+
+   ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
+   ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
+
+#endif /* !Z_SOLO */
+
+/* hack for buggy compilers */
+#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL)
+    struct internal_state {int dummy;};
+#endif
+
+/* undocumented functions */
+ZEXTERN const char   * ZEXPORT zError           OF((int));
+ZEXTERN int            ZEXPORT inflateSyncPoint OF((z_streamp));
+ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table    OF((void));
+ZEXTERN int            ZEXPORT inflateUndermine OF((z_streamp, int));
+ZEXTERN int            ZEXPORT inflateResetKeep OF((z_streamp));
+ZEXTERN int            ZEXPORT deflateResetKeep OF((z_streamp));
+#if defined(_WIN32) && !defined(Z_SOLO)
+ZEXTERN gzFile         ZEXPORT gzopen_w OF((const wchar_t *path,
+                                            const char *mode));
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ZLIB_H */

--
Gitblit v1.6.2